- •О.С. Зеленський
- •Розділ 1. Загальні відомості створення додатку windows
- •1.1. Створення додатку Windows за допомогою майстра AppWizard
- •1.2. Варіанти майстрів для різних проектів
- •1.3. Короткий опис sdi програми
- •1.4. Короткий опис mdi програми
- •1.5. Короткий опис простого діалогового додатку
- •Контрольні питання
- •Розділ 2. Повідомлення і команди
- •2.1. Обробка повідомлень
- •2.2. Цикли обробки повідомлень
- •2.3. Карти повідомлень
- •Контрольні питання
- •Розділ 3. Документи та види
- •3.1. Клас додатку
- •3.2. Клас головного вікна
- •3.3. Клас документа
- •3.4. Класи виду
- •Контрольні питання
- •Розділ 4. Робота з клавіатурою, мишею і меню
- •4.1. Робота з клавіатурою
- •4.2. Робота з мишею
- •4.3. Робота з меню
- •Контрольні питання
- •Розділ 5. Виведення на екран
- •5.1. Класи графічних об'єктів
- •5.2. Робота зі шрифтами
- •5.3. Робота з пензликами та малювання графічних фігур
- •5.4. Робота з пензликом
- •5.5. Робота зі скролінгом
- •5.6. Приклад роботи з таблицями
- •5.7. Малювання на екрані маніпулятором "миша"
- •5.8. Завантаження та виведення на екран бітових зображень
- •5.9. Копіювання бітових образів
- •5.10. Малювання графічних об'єктів з використанням резинових контурів та метафайлів
- •5.11. Виділення графічних об'єктів у прямокутній області
- •5.12. Універсальний приклад роботи з двовимірною графікою з використанням резинового контуру
- •5.13. Запис на диск та зчитування з диску графічних об'єктів
- •5.14. Побудова кругових діаграм і гістограм
- •5.15. Користувацький режим роботи з графікою на прикладі малювання годинника Clock
- •Контрольні питання
- •Завдання
- •Розділ 6. Друк і попередній перегляд документів
- •6.1. Вибір і налаштування параметрів друку
- •6.2. Створення контекста пристрою
- •6.3. Друк документів і бібліотека mfc
- •6.4. Масштабування
- •6.5. Друк багатосторінкового документа
- •Контрольні питання
- •Розділ 7. Робота з файлами
- •7.1. Приклад роботи з файлами на основі класів cFile, cStdioFile та потоку fstream
- •7.1.1. Робота з класом cFile
- •7.1.2. Робота з потоком fstream
- •Можливі режими доступу
- •7.1.3. Робота з класом cStdioFile
- •7.2. Серіалізація даних, клас cArchive
- •7.3. Використання реєстру в додатках
- •Контрольні питання
- •Завдання
- •Розділ 8. Діалогові вікна
- •8.1. Створення діалогового вікна та простіші елементи керування
- •8.2. Робота зі списками і комбінованими полями
- •8.3. Ускладнений приклад зі списками
- •8.4. Робота з повзунками
- •8.5. Виведення бітових матриць в діалозі та у вікні виду
- •8.6. Лінійний регулятор, лінійний індикатор, інкриментний регулятор
- •8.7. Стандартні діалоги вибору файлів, шрифтів та кольору
- •8.8. Взаємоз'вязок діалога, документа та виду при розробці додатку
- •8.8.1. Клас cDialDoc
- •8.8.2. Клас cDialView
- •8.8.3. Клас Cdlg
- •8.9. Формування вхідного документа на основі діалогу
- •Контрольні питання
- •Завдання Робота з типовими елементами керування
- •Робота зі списками і комбінованими полями
- •Список літератури
8.9. Формування вхідного документа на основі діалогу
Приклад формування вхідного документа на основі діалогу знаходиться у папці DISK\dialog\dialog10.
Розглянемо динамічне формування вікна діалогу на основі вхідних параметрів. У програмі мають місце 2 вікна діалогу. Перше вікно призначене для введення кількості рядків (рис. 8.19), а друге в залежності від введеної цифри буде створювати таку ж кількість рядків із полів для введення значень кутів (рис. 8.20). Створимо простий SDI проект з назвою Vvod.
Створимо перший діалог на основі ресурсу IDD_DIALOG1 та класу з назвою Dialog1. У редакторі ресурсів створимо текстове поле та підпис до нього. Код ресурса діалога прийме такий вид:
IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 186, 87
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Dialog"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "OK",ID_OK,129,66,50,14,NOT WS_TABSTOP
PUSHBUTTON "Cancel",IDCANCEL,75,66,50,14,NOT WS_TABSTOP
EDITTEXT IDC_EDIT100,27,29,33,16,ES_AUTOHSCROLL
LTEXT "К-во строк",IDC_STATIC,26,15,50,15
END
Для контролю текстового поля додамо у клас діалогу вказівку на об'єкт типу CEdit:
class Dialog1 : public CDialog
{
// Construction
public:
.............................................................
CEdit* kol_p;
int kol_punk;
.............................................................
};
У функції OnInitDialog допишемо підключення вказівки kol_p до текстового поля, та змінимо настройки максимальної довжини поля до 1-го символа функцією SetLimitText:
BOOL Dialog1::OnInitDialog()
{
CDialog::OnInitDialog();
kol_p = (CEdit*)GetDlgItem(IDC_EDIT100);
kol_p->SetLimitText(1);
return TRUE;
}
Для реакції діалогового вікна на події операційної системи додамо функцію OnCommand:
BOOL Dialog1::OnCommand(WPARAM wParam, LPARAM lParam)
{
char buf[5];
bool log;
CString vr;
if (!IsWindowVisible()) return 0;
if((HIWORD(wParam) == 768 || HIWORD(wParam) == 256)
&& LOWORD(wParam) == IDC_EDIT100 )
{
kol_p->GetWindowText(vr);
strcpy(buf,vr.GetBuffer(1));
log = IsNumeric(buf);
if ((!log && buf[0]!=0) || buf[0]=='+' || buf[0]=='-' || buf[0]=='0')
{
kol_p->Undo();
kol_p->SetSel(65534, 65534);
kol_p->SetFocus();
return 0;
}
else kol_p->EmptyUndoBuffer();
SetWindowText("Диалог");
}
if (LOWORD(wParam) == ID_OK)
{
kol_p->GetWindowText(vr);
strcpy(buf,vr.GetBuffer(1));
if (buf[0]== 0)
{
kol_p->SetFocus();
SetWindowText("Внимание !!! Введите к-во строк");
return 0;
}
kol_punk = atoi(buf);
OnOK();
return CDialog::OnCommand(wParam, lParam);
}
if(wParam == 1) return 0;
return CDialog::OnCommand(wParam, lParam);
}
При натисненні кнопки OK у змінну діалогу kol_punk записується число введене у текстове поле. У випадку коли поле буде пустим буде виведено повідомлення про необхідність введення данних.
В класі документа додамо двомірний масив mas_zas:
class CVvodDoc : public CDocument
{
.............................................................
public:
int mas_zas[10][8];
.............................................................
};
У конструкторі класу документа обнуляємо усі значення крім 1-го стовпчика:
CVvodDoc::CVvodDoc()
{
for (int i=0;i<10;i++)
{
mas_zas[i][0]=i+1;
for (int j = 1;j<8;j++)
mas_zas[i][j]=0;
}
}
Додамо пункт меню з назвою Vvod зробимо функцію для цього пункта меню з назвою OnVvod:
void CVvodDoc::OnVvod()
{
Dialog1 dlg1;
if(dlg1.DoModal() != IDOK) return;
Dialog2 dlg2;
dlg2.doc = this;
dlg2.kol_punk = dlg1.kol_punk;
dlg2.DoModal();
}
Тут створюється спочатку об'єкт класу Dialog1 а потім вікно Dialog2. Як видно з коду наведеної функції значення змінної kol_punk копіюється із першого діалога у другий.
Рис. 8.19. Діалог для введення кількості рядків
Створимо другий діалог на основі ресурсу IDD_DIALOG2 та класу з назвою Dialog2. Додамо у клас діалогу масиви вказівок на елементи керування:
class Dialog2 : public CDialog
{
.............................................................
CEdit* Ugl[9][7];
CButton* Zn_nak[9];
.............................................................
int kol_punk;
.............................................................
};
Використання змінної kol_punk у діалозі Dialog2 можна побачити у функції ShowDlgElement:
void Dialog2::ShowDlgElement() // Показ елементів
{
int i,j;
CString vr;
for(i=0; i<9; i++)
{
if(i < kol_punk)
{
Zn_nak[i]->ShowWindow(SW_SHOW);
if(doc->mas_zas[i][4]>0)
Zn_nak[i]->SetWindowText("+");
else Zn_nak[i]->SetWindowText("--");
}
else Zn_nak[i]->ShowWindow(SW_HIDE);
for(j=0; j<7; j++)
{
if(i < kol_punk)
{
Ugl[i][j]->ShowWindow(SW_SHOW);
vr.Format("%d",
abs(doc->mas_zas[i][j]));
Ugl[i][j]->SetWindowText(vr);
}
else Ugl[i][j]->ShowWindow(SW_HIDE);
} // for j
} // for i
}
Як видно із коду елементи керування Ugl (текстові поля) і Zn_nak (кнопки) завдяки викликам функції ShowWindow будуть показані або сховані на вікні діалогу. Кількість показаних елементів буде залежати від значення змінної kol_punk. На елементах Zn_nak завдяки функції SetWindowText встановлюється підпис, що означає додатнє або від'ємне значення кута. Функція ShowDlgElement викликається у програмі тільки при створенні вікна діалогу із функції OnInitDialog:
BOOL Dialog2::OnInitDialog()
{
CDialog::OnInitDialog();
int i,j;
for(i=0; i<9; i++)
{
Zn_nak[i] = (CButton*)GetDlgItem(IDC_BUTTON1 + i);
for(j = 0; j < 7; j++)
Ugl[i][j] = (CEdit*)GetDlgItem(IDC_EDIT1 + i*7 + j);
Ugl[i][0]->SetReadOnly();
}
ShowDlgElement();
SetWindowText("Ввод данных");
MoveDlg(); //подтягивание снизу
hb = ::CreateSolidBrush(RGB(200,0,0));
return TRUE;
}
Оскільки кожен раз при відкритті діалогу Dialog2 кількість рядків для введення буде різною то і його розміри доцільно робити відповідними кількості полів. Функція MoveDlg створена для розрахунку розмірів вікна діалогу:
void Dialog2::MoveDlg() //Подтягивание окна и елементов
{
CRect vr_top,vr_bott,vr_st;
CWnd* elem;
int i,delta=0;
int mas_elem[5]={ID_OK,IDCANCEL,IDC_STATIC120,
IDC_STATIC_B1,IDC_STATIC_B2};
Ugl[kol_punk-1][0]->GetWindowRect(vr_top);
Ugl[8][0]->GetWindowRect(vr_bott);
delta = vr_bott.bottom - vr_top.bottom;
for(i=0;i<5;i++)
{
elem=GetDlgItem(mas_elem[i]);
elem->GetWindowRect(vr_st);
ScreenToClient(vr_st);
if (i<3) vr_st.OffsetRect(0,-delta);
else vr_st.bottom-=delta;
elem->MoveWindow(vr_st);
}
GetWindowRect(vr_st);
vr_st.bottom-=delta;
MoveWindow(vr_st);
}
У змінній delta розраховується відстань між нижніми границям останнього поля у масиві та останього використовуємого поля для введення. Отже у delta отримаємо саме те значення, на яке потрібно підняти кнопки OK і Cancel а також зменшити висоту вікна. Функція MoveWindow змінює розміри вікна та його розташування. Переміщення елементів керування відбувається відносно батьківського вікна а переміщення самостійних вікон відбувається відносно екрану. Саме тому перед переміщенням елементів керування ми використали функцію ScreenToClient, котра перераховує екранні координати у координати відносно батьківського вікна.
Рис. 8.20. Діалог для введення значень кутів