- •О.С. Зеленський
- •Розділ 9. Структура створення додатків
- •9.1. Загальна структура додатків
- •9.2. Додатки без використання архітектури «Документ-вид»
- •9.2.1. Приклад додатку реєстрації wnd-класу вікна
- •9.2.2. Створення та видалення дочірніх вікон без використання архітектури «Документ-Вид»
- •9.2.3. Створення дочірніх вікон без використання архітектури «Документ-Вид» (переключення вікон з використанням функції ShowWindow)
- •9.3. Архітектура «Документ-Вид»
- •Idr_mainframe формат строкового ресурсу.
- •9.3.1. Приклад додатку з використанням архітектури «Документ-Вид»
- •9.3.2. Види у архітектурі «Документ-Вид»
- •9.3.3. Створення видів у архітектурі «Документ-Вид» (переключення видів з використанням функції ShowWindow)
- •9.3.4. Робота з документами та видами на прикладі додатку SingleTemplate
- •9.4. Додатки mdi, робота з шаблонами
- •9.4.1. Приклад додатку mdi з одним шаблоном
- •9.4.2. Приклад додатку mdi з декількома шаблонами
- •Контрольні питання
- •Розділ 10. Робота з базами даних з використанням об'єктів ado
- •10.1.1. Ініціалізація об'єктів com з використанням директиви #import
- •10.1.2. Підтримка класів сом
- •10.2. Об'єкт Connection
- •10.3. Об'єкт Command
- •10.4. Об'єкт Recordset
- •10.5. Об'єкт Field і колекція Fields
- •10.6. Об'єкт Error і колекція Errors
- •10.8. Коротка характеристика структури мови sql
- •10.9. Синтаксис оператора вибору Select
- •10.10. Приклад програмування об'єктів ado
- •10.11. Опис розробленого навчального пакету ado6 для роботи з базами даних access та MySql
- •Int tip_bd; // тип бд 1- ms access, 2- MySql, 3 - xml
- •Void Connect_Baza(cString str);
- •Void ErrMessage(_com_error &ce);
- •If(pConn.CreateInstance("adodb.Connection"))
- •If(pRecordset.CreateInstance("adodb.RecordSet"))
- •Void cAdo6Doc::ErrMessage(_com_error &ce)
- •Void cAdo6Doc::OnMsaccess()
- •Void cAdo6Doc::OnMysql()
- •Void cAdo6Doc::OnXmlRead()
- •Void cAdo6Doc::Connect_Baza(cString str)
- •Virtual void DoDataExchange(cDataExchange* pDx);
- •Void cAdo6Dlg::DoDataExchange(cDataExchange* pDx)
- •Void cAdo6Dlg::Struct_MySql()
- •Void cAdo6Dlg::OnSelchangeListBaza()
- •Void cAdo6Dlg::OnVibor_bd()
- •Void cAdo6Dlg::AccessOpen()
- •Void cAdo6Dlg::xmlOpen()
- •Void cAdo6Dlg::Structura_bd()
- •Void cAdo6Dlg::OnSelchangeListTab()
- •Void cAdo6Dlg::show(int kod, int kod_bd)
- •Void cAdo6Dlg::Recordset_Baza(cString str)
- •Void cAdo6Dlg::OnClose()
- •10.11.2. Формування списку бд (MySql), відкриття бази даних (ms access), відкриття xml-файлу, формування списку таблиць (MySql і ms access) та полів (MySql, ms access, xml)
- •Void cAdo6Dlg::OnSelchangeListTab()
- •1. Обрану таблицю необхідно брати в зворотні лапки "`", щоб виключити помилку в тому випадку, якщо в імені таблиці будуть зустрічатися пробіли.
- •10.11.3. Робота з sql-запитами
- •Void cAdo6Dlg::OnZapros_Select()
- •If (str_query.Mid(0,6).Compare("select"))
- •If(!baza.Left(3).Compare("otl") &&
- •Void cAdo6Dlg::Recordset_Baza(cString str)
- •Void cado6Dlg::OnZapros_Make()
- •Vr_zap.Format(" Запрос выполнен за %f сек ",conec - nach);
- •10.11.4. Видалення, сортування, пошук, фільтрація, оновлення набору записів
- •Void cado6Dlg::OnZapis_Delete()
- •Void cado6Dlg::OnCheck_Sort()
- •Void cado6Dlg::OnFind()
- •0L,adSearchForward,bb);
- •Void cado6Dlg::OnFilter()
- •Void cado6Dlg::OnVozvrat()
- •10.11.5. Переходи по записах
- •Void cado6Dlg::OnButtonFirst()
- •Void cado6Dlg::OnButtonLast()
- •Void cado6Dlg::OnButtonLeft()
- •Void cado6Dlg::OnButtonRight()
- •Void cado6Dlg::OnButtonRecno()
- •Void cado6Dlg::OnButtonPgup()
- •Void cado6Dlg::OnButtonPgdn()
- •Void cado6Dlg::OnButtonBookmark()
- •10.11.6. Запис даних до xml-файлу
- •Void cAdo6Dlg::OnButtonSave()
- •10.11.7. Кнопки, призначені тільки для роботи з otl_tab
- •Void cado6Dlg::OnZapis_Add1()
- •Void cado6Dlg::OnZapis_Add2()
- •Void cado6Dlg::OnZapis_Update1()
- •Void cado6Dlg::OnZapis_Update2()
- •Void cado6Dlg::OnFormir_bd()
- •Void cAdo6Dlg::OnValues_Fields()
- •10.12. Використання у якості джерела даних електронної таблиці Excel
- •Контрольні питання
- •Завдання
- •Розділ 11. Програмування для інтернет
- •11.1. Створення броузера
- •11.3. Використання протоколу http
- •If ((pInternetSession)
- •11.4. Використання протоколу ftp
- •Контрольні питання
- •Розділ 12. Створення елементів activex
- •12.1. Створення елементів ActiveX
- •Invalidate();
- •12.2. Тестування елемента ActiveX
- •12.4. Створення елемента ActiveX на базі стандартних елементів
- •12.5. Відображення елементів ActiveX
- •Контрольні питання
- •Розділ 13. Налагодження програм
- •Int data[5];
- •Invalidate();
- •13.3. Установка точки переривання
- •13.2. Покрокове виконання програми
- •13.4. Перевірка значень змінних під час виконання програми
- •Контрольні питання
- •Список літератури
- •Додатки
9.2.2. Створення та видалення дочірніх вікон без використання архітектури «Документ-Вид»
Приклад створення та видалення дочірніх вікон знаходиться у папці DISK\Structure\Dchild_no_tem_1.
Створимо додаток Dchild_no_tem_1. В цьому додатку буде 2 дочірніх вікна та 1 клієнтське. Клієнтське вікно буде залежним від одного з дочірніх (рис. 9.5).
Дочірні вікна, це вікна, які вбудовані в головне вікно. Вони мають стиль WS_CHILD, та не можуть вийти за межі головного вікна.
Клієнтське вікно належить до батьківського вікна, але не має стилю WS_CHILD. Воно може виходити за межі головного вікна.
Рис. 9.5. Схема підключення класів вікон у додатку Dchild_no_tem_1
Для першого дочірнього вікна буде слугувати створений майстром клас CChildView (який ми перейменуємо у CChild1). Для другого вікна створимо клас CChild2 похідний від CFrameWnd, конструктор та деструктор якого винесемо у область видимості public.
Створимо клієнтське вікно CClient1, похідне від CFrameWnd, конструктор та деструктор якого також винесемо у public.
В класі CMainFrame зробимо вказівки на ці вікна.
class CMainFrame : public CFrameWnd
{
.............................................................
CChild1* m_child1;
CChild2* m_child2;
CClient1* m_client1;
.............................................................
};
В конструкторі CMainFrame вказівкам поставимо 0:
CMainFrame::CMainFrame()
{
m_child1 = 0;
m_child2 = 0;
m_client1 = 0;
}
Додамо в клас CMainFrame функції-відгуки OnChild1, OnChild2, відповідно для створення вікон CChild1, CChild2. Розглянемо функцію OnChild1 створення першого дочірнього вікна.
void CMainFrame::OnChild1()
{
if(m_child2) {delete m_child2; m_child2 = 0;}
if(m_child1) return;
SetWindowText("Child 1");
m_child1 = new CChild1;
if (!m_child1->CreateEx(
0, NULL, "", AFX_WS_DEFAULT_VIEW,
CRect(0, 0, 0, 0), this, AFX_IDW_PANE_FIRST))
return;
RecalcLayout();
}
В цій функції перевіряється наявність другого вікна – вказівка m_child2. Якщо вказівка не дорівнює нулю, об’єкт вікна видаляється. Далі йде перевірка чи вже є відкрите вікно m_child1, якщо є, – то виходимо з функції. На наступному етапі створюється вікно функцією Create. Якщо задано параметр NULL, то ім’я класу приймає значення "AfxFrameOrView42d" – це ім’я стандартного класу вікна. Останній рядок це виклик функції RecalcLayout для передачі повідомлення WM_SIZE вікну CMainFrame. Це повідомлення визиває перерахунок розмірів вікна m_child1, так як воно є дочірнім. Ми задали пустий прямокутник CRect(0, 0, 0, 0), так як вікно є вкладеним, тому заданий параметр ігнорується.
void CMainFrame::OnChild2()
{
if(m_client1) { delete m_client1;m_client1 = 0;}
if(m_child1) { delete m_child1;m_child1 = 0;}
if(m_child2) return;
SetWindowText("Child 2");
m_child2 = new CChild2;
// AFX_WS_DEFAULT_VIEW -> WS_CHILD|WS_VISIBLE|WS_BORDER
if(!m_child2->CreateEx(0, str, "Child 2",
WS_CHILD|WS_VISIBLE|WS_BORDER, CRect(0, 0, 0, 0),
this, AFX_IDW_PANE_FIRST))
return;
RecalcLayout();
}
Для створення вікна m_child2 виконуємо майже аналогічні дії. Відмінність полягає у тому, що перевіряється також наявність вікна m_client1. Це вікно створено на основі Windows-класу вікна, ім’я якого міститься у змінній str. А замість константи AFX_WS_DEFAULT_VIEW підставляємо 3 стиля вікна WS_CHILD | WS_VISIBLE | WS_BORDER. Ці стилі відповідають стилю AFX_WS_DEFAULT_VIEW.
Щоб побачити на екрані, яке саме вікно активне в даний момент, додамо в кожен з класів функції OnPaint:
void CChild1::OnPaint()
{
CPaintDC dc(this); // device context for painting
dc.TextOut(20,20,"Child 1");
}
void CClient1::OnPaint()
{
CPaintDC dc(this); // контекст для малювання
dc.TextOut(20,20,((CMainFrame*)
par_mainframe)->m_child1->str);
}
void CChild2::OnPaint()
{
CPaintDC dc(this);
dc.TextOut(50,50,"Child 2");
}
Як видно з коду функції CClient1::OnPaint, що вікно CClient1 виводить на екран текст з вікна CChild1, відносно якого воно є клієнтським. В клас CChild1 ми внесли текстову змінну у область public, яку і будемо виводити у клієнтському вікні:
CString str;
Виклик самого цього вікна (CClient1) робиться наступним чином:
void CMainFrame::OnClient1()
{
if(!m_child1||m_client1) return;
CRect rect;
GetWindowRect(&rect);
rect.OffsetRect(20,80);
SetWindowText("Client 1");
m_client1 = new CClient1;
m_client1->par_mainframe = this;
m_client1->CreateEx(0,NULL, "Client 1",
WS_VISIBLE|WS_OVERLAPPEDWINDOW,
rect,m_child1,0);
}
Відразу йде перевірка на наявність вікон: m_child1 – щоб було до чого прив’язати клієнтське вікно, m_client1 – щоб не створювати вікно повторно. За допомогою функцій GetWindowRect та OffsetRect визначаємо розміри вікна CMainFrame та переміщуємо отриманий прямокутник (на 20 пікселів праворуч, на 80 – вниз).
Далі важлива послідовність дій: 1) викликаємо конструктор CClient1 (вікно Windows ще не створено, але виділена пам’ять для класу); 2) вказівку par_mainframe прирівнюємо до this (прив’язуємо створюване вікно до головного вікна CMainFrame. Через цю прив’язку можна отримати дані CString str класу CChild1); 3) створюємо вікно функцією Create; зверніть увагу на параметр m_child1 (вікно буде клієнтським не відносно CMainFrame а відносно CChild1).
Змінимо стандартну панель інструментів. Замість стандартних кнопок створимо три власних для виклику вікон з ідентифікаторами ID_CLIENT1, ID_CHILD1, ID_CHILD2. Додамо функцію OnUpdateAll в клас CMainFrame, у якій буде контролюватися стан кнопок в залежності від відкритих вікон:
void CMainFrame::OnUpdateAll(CCmdUI* pCmdUI)
{
if(pCmdUI->m_nID==ID_CLIENT1)
{
if(m_child1)pCmdUI->Enable(1);
else pCmdUI->Enable(0);
}
if(pCmdUI->m_nID==ID_CHILD1)
{
if(m_child1)pCmdUI->SetCheck(1);
else pCmdUI->SetCheck(0);
}
if(pCmdUI->m_nID==ID_CHILD2)
{
if(m_child2)pCmdUI->SetCheck(1);
else pCmdUI->SetCheck(0);
}
}
При використанні функції SetCheck з параметром 1 відбувається натискання кнопки, а з параметром 0 – повертає кнопку у початкове становище (відтискає).
На рисунку 9.6. показано роботу додатку:
Рис. 9.6. Приклад роботи додатку Dchild_no_tem_1, із вікнами Child1 та Client1