На этом шаге мы рассмотрим создание и использование управляющих элементов.
Диалоговые окна являются объектами, которые наиболее широко используются для получения информации от пользователя в приложении Windows. Конечно, диалоговые окна не очень удобны без тех элементов управления, которые можно в них поместить. Области ввода, окна списков, комбинированнные окна, радиокнопки, кнопки с независимой фиксацией, линейки прокрутки и другие управляющие элементы - все вместе работают, чтобы обеспечить удобство ввода данных в программу пользователю данного приложения.
Хотя управляющие элементы наиболее часто используются в диалоговых окнах, они могут размещаться в любом окне. В самом деле, основное различие между размещением управляющих элементов в диалоговом окне и их размещением в окне другого типа заключается в той процедуре, которая обеспечивает введение управляющих элементов в окно. При работе с диалоговыми окнами управляющие элементы можно "нарисовать" в этом окне с помощью Resource Workshop, задолго до первого запуска пользователем вашей программы. При работе с окном другого типа вы создаете и размещаете управляющие элементы внутри вашего приложения, что требует больших усилий.
Начиная с этого шага вы научитесь работать с управляющими элементами в диалоговых окнах и в окнах других типов. Вы также узнаете о новых способах получения информации с помощью элементов, управляющих окнами.
До сих пор речь шла о диалоговых окнах, содержащих такие базовые управляющие элементы как области ввода и кнопки. Области ввода и кнопки, вероятно, являются нанболее важными управляющими элементами, имеющимися в вашем распоряжении. Однако вы зачастую можете предоставить пользователю вашей программы более простые способы выбора данных, которые должны быть введены в программу.
Имеется несколько типов управляющих элементов, которые вы можете разместить в диалоговом окне, включая кнопки с независимой фиксацией, окна списков, комбинированные окна, линейки прокрутки. Вы уже, видимо, знакомы с тем, как работают эти управляющие элементы, как с точки зрения пользователя, так и с точки зрения программиста. Если вам никогда не приходилось программировать с использованием ObjectWindows, вы можете не знать тех классов, в которых OWL инкапсулирует каждый из этих управляющих элементов. К этим классам относятся TCheckBox, TRadioButton, TGroupBox, TListBox, TComboBox и TScrollBar. К другим классам управляющих элементов, которыми вы уже пользовались, относятся TEdit и TButton.
Как упоминалось выше, любой из этих элементов управления вы можете ввести в диалоговое окно, попросту используя Resource Workshop. На рисунке 1 показано диалоговое окно, используемое в нижеприведенной программе, которое находится в процессе построения в Resource Workshop. В слндующем примере показано, как работать с этими управляющими элементами внутри вашего приложения.
Рис.1. Создание диалогового окна в Resource Workshop
#include <owl\applicat.h> #include <owl\framewin.h> #include <owl\dialog.h> #include <owl\radiobut.h> #include <owl\edit.h> #include <owl\listbox.h> #include <owl\combobox.h> #include <owl\scrollba.h> #include <owl\dc.h> #include <string.h> #include "pr55_1.rc" // Буфер обмена диалогового окна. struct { char edit[81]; BOOL radio1; BOOL radio2; BOOL radio3; TScrollBarData scrollerData; BOOL check1; BOOL check2; BOOL check3; TListBoxData listBoxData; TComboBoxData comboBoxData; } transBuf; // Класс приложения. class TApp: public TApplication { public: TApp():TApplication() {} void InitMainWindow(); }; // Класс главного окна. class TWndw : public TFrameWindow { public: TWndw (TWindow *parent, const char far *title); protected: void Paint(TDC&, BOOL, TRect&); void CmDialog(); DECLARE_RESPONSE_TABLE(TWndw); }; DEFINE_RESPONSE_TABLE1 (TWndw, TFrameWindow) EV_COMMAND (CM_DIALOG, CmDialog), END_RESPONSE_TABLE; // Класс диалогового окна. class TDlg : public TDialog { public: TDlg(TWindow *parent, TResId resId); }; // TWndw::TWndw() // Это конструктор главного окна. TWndw::TWndw(TWindow *parent, const char far *title): TFrameWindow (parent, title) { // Определить расположение и размеры окна. Attr.X = 20; Attr.Y = 20; Attr.W = 500; Attr.H = 300; // Добавить меню к окну. AssignMenu(MENU_1); // Инициализировать буфер обмена. strcpy(transBuf.edit, "Default"); transBuf.radio1 = TRUE; transBuf.radio2 = FALSE; transBuf.radio3 = FALSE; transBuf.check1 = TRUE; transBuf.check2 = FALSE; transBuf.check3 = FALSE; transBuf.scrollerData.HighValue = 100; transBuf.scrollerData.LowValue = 0; transBuf.scrollerData.Position = 50; transBuf.listBoxData.AddString("ListString1", TRUE) ; transBuf.listBoxData.AddString("Liststring2"); transBuf.listBoxData.AddString("ListString3"); transBuf.listBoxData.AddString("ListString4"); transBuf.listBoxData.AddString("ListString5"); transBuf.listBoxData.AddString("ListString6"); transBuf.comboBoxData.AddString("ComboString1", TRUE); transBuf.comboBoxData.AddString("ComboString2"); transBuf.comboBoxData.AddString("ComboString3"); transBuf.comboBoxData.AddString("ComboString4"); transBuf.comboBoxData.AddString("ComboString5"); transBuf.comboBoxData.AddString("ComboString6"); } // TWndw::CmDialog() // Эта функция реагирует на команду Test Dialog из // меню Dialog, отображая и управляя диалоговым окном. void TWndw::CmDialog() { // Создать диалоговое окно. TDialog *dialog = new TDlg(this, DIALOG_1); // Отобразить диалоговое окно. int result = dialog->Execute(); // Проверить, вышел ли пользователь из // диалогового окна по кнопке OK и // отобразить новые данные диалогового окна, если это так. if (result == IDOK) Invalidate(); } // TWndw::Paint() // Эта функция, которая реагирует на сообщение // WM_PAINT, вызывается каждый раз, когда // окно должно быть пперерисовано. void TWndw::Paint(TDC &paintDC, BOOL, TRect&) { TEXTMETRIC textMetrics; int num; char s[40]; // Получить текущие параметры текста. paintDC.GetTextMetrics(textMetrics); // Установить выравнивание вправо выводимого текста. paintDC.SetTextAlign(TA_RIGHT); // Определить размер самой длинной метки. TSize size = paintDC.GetTextExtent("EDIT CONTROL:", 13); // Напечатать все метки в рабочей области окна. paintDC.TextOut(size.cx + 12, textMetrics.tmHeight, "EDIT CONTROL:"); paintDC.TextOut(size.cx + 12, textMetrics.tmHeight*2, "RADIO BUTTON:"); paintDC.TextOut(size.cx + 12, textMetrics.tmHeight*3, "SCROLL BAR:"); paintDC.TextOut(size.cx + 12, textMetrics.tmHeight*4, "CHECK BOX 1:"); paintDC.TextOut(size.cx + 12, textMetrics.tmHeight*5, "CHECK BOX 2:"); paintDC.TextOut(size.cx + 12, textMetrics.tmHeight*6, "CHECK BOX 3:"); paintDC.TextOut(size.cx + 12, textMetrics.tmHeight*7, "LIST BOX:"); paintDC.TextOut(size.cx + 12, textMetrics.tmHeight*8, "COMBO BOX;"); // Установить выравнивание влево выводимого текста. paintDC.SetTextAlign(TA_LEFT); // Установить цвет текста. paintDC.SetTextColor(TColor::LtBlue); // Напечатать данные диалогового окна в // соответствующих позициях, основываясь на // длине самой длинной метки и высоте текущего шрифта. paintDC.TextOut(size.cx + 20, textMetrics.tmHeight, transBuf.edit); if (transBuf.radio1) num = 1; else if (transBuf.radio2) num = 2; else num = 3; wsprintf(s, "Radio button #%d chosen", num); paintDC.TextOut(size.cx + 20, textMetrics.tmHeight*2, s); wsprintf(s, "%d", transBuf.scrollerData.Position); paintDC.TextOut(size.cx + 20, textMetrics.tmHeight*3, s); if (transBuf.check1) strcpy (s, "Chosen"); else strcpy(s, "Not chosen"); paintDC.TextOut(size.cx + 20, textMetrics.tmHeight*4, s); if (transBuf.check2) strcpy(s, "Chosen"); else strcpy(s, "Not chosen"); paintDC.TextOut(size.cx + 20, textMetrics.tmHeight*5, s); if (transBuf.check3) strcpy(s, "Chosen"); else strcpy(s, "Not chosen"); paintDC.TextOut(size.cx + 20, textMetrics.tmHeight*6, s); transBuf.listBoxData.GetSelString(s, sizeof(s)); paintDC.TextOut(size.cx + 20, textMetrics.tmHeight*7, s); transBuf.comboBoxData.GetSelString(s, sizeof(s)); paintDC.TextOut(size.cx + 20, textMetrics.tmHeight*8, s); } //************************************** // Реализация класса TDlg. //************************************** // TDlg::TDlg() // Это конструктор диалогового окна. TDlg::TDlg(TWindow *parent, TResId resId): TDialog (parent, resId) { // Построить OWL-объекты для управляющих элементов // в диалоговом окне. Механизм передачи работает // правильно, если управляющие элементы OWL строятся // в таком же порядке, в каком они появляются // в структуре буфера обмена transBuf. new TEdit (this, ID_EDIT, sizeof(transBuf.edit)); new TRadioButton (this, ID_RADIO1, 0); new TRadioButton (this, ID_RADIO2, 0); new TRadioButton (this, ID_RADIO3, 0); new TScrollBar (this, ID_SCROLLER); new TCheckBox (this, ID_CHECK1); new TCheckBox (this, ID_CHECK2); new TCheckBox (this, ID_CHECK3); new TListBox (this, ID_LISTBOX); new TComboBox (this, ID_COMBOBOX, 20); // Установить адрес буфера обмена. TransferBuffer = &transBuf; } void TApp::InitMainWindow() { TFrameWindow *wndw = new TWndw (0,"Управляющие элементы"); SetMainWindow(wndw); } int OwlMain(int,char *[]) { return TApp().Run(); }
Файл ресурсов:
#ifndef WORKSHOP_INVOKED #include "windows.h" #endif #include <owl\window.rh> #define MENU_1 100 #define DIALOG_1 200 #define CM_DIALOG 201 #define ID_EDIT 101 #define ID_RADIO1 102 #define ID_RADIO2 103 #define ID_RADIO3 104 #define ID_SCROLLER 105 #define ID_CHECK1 106 #define ID_CHECK2 107 #define ID_CHECK3 108 #define ID_LISTBOX 109 #define ID_COMBOBOX 110 #ifdef RC_INVOKED MENU_1 MENU { POPUP "&File" { MENUITEM "E&xit", CM_EXIT } POPUP "&Dialog" { MENUITEM "&Test Dialog...", CM_DIALOG } } DIALOG_1 DIALOG 9, 17, 296, 135 STYLE WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME CAPTION "Control Dialog" { EDITTEXT ID_EDIT, 14, 18, 51, 12, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP CONTROL "R1", ID_RADIO1, "BUTTON", BS_AUTORADIOBUTTON | WS_TABSTOP, 91, 19, 20, 10 CONTROL "R2", ID_RADIO2, "BUTTON", BS_AUTORADIOBUTTON | WS_TABSTOP, 115, 19, 20, 10 CONTROL "R3", ID_RADIO3, "BUTTON", BS_AUTORADIOBUTTON | WS_TABSTOP, 141, 19, 20, 10 SCROLLBAR ID_SCROLLER, 184, 20, 101, 12, SBS_HORZ CHECKBOX "Check1", ID_CHECK1, 20, 53, 35, 12, BS_AUTOCHECKBOX | WS_TABSTOP CHECKBOX "Check2", ID_CHECK2, 20, 65, 36, 12, BS_AUTOCHECKBOX | WS_TABSTOP CHECKBOX "Check3", ID_CHECK3, 20, 77, 37, 12, BS_AUTOCHECKBOX | WS_TABSTOP LISTBOX ID_LISTBOX, 85, 53, 84, 37, LBS_NOTIFY | LBS_DISABLENOSCROLL | WS_BORDER | WS_VSCROLL COMBOBOX ID_COMBOBOX, 184, 53, 86, 49, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP PUSHBUTTON "OK", 1, 172, 108, 50, 14 PUSHBUTTON "Cancel", 2, 233, 108, 50, 14 LTEXT "Edit:", -1, 16, 6, 16, 8, NOT WS_GROUP GROUPBOX "Radio Buttons", -1, 87, 6, 80, 26, BS_GROUPBOX | WS_GROUP LTEXT "Scroll Bar", -1, 186, 7, 42, 10 GROUPBOX "Check Boxes", -1, 14, 37, 54, 62, BS_GROUPBOX LTEXT "List Box", -1, 86, 39, 36, 10 LTEXT "Combo Box", -1, 185, 40, 48, 10 } #endif
Когда вы запускаете эту программу, появляется окно, представленное на рисунке 2.
Рис.2. Результат работы приложения
В этом окне приведены текущие данные, выбранные пользователем. В начале программы этим данным присваиваются значения по умолчанию. В поле EDIT CONTROL на экране показана текущая строка в области ввода. В поле при RADIO BUTTON определена радио-кнопка. В поле CHECK BOX показан статус каждой из трех кнопок с независимой фиксацией. В поле LIST BOX показана текущая строка, выбранная в окне списка, и в поле COMBO BOX показана текущая строка, выбранная в комбинированном окне. Наконец, в поле SCROLL BAR показана текущая установка прокрутки в диалоговом окне.
Чтобы найти все эти управляющие элементы, выберите команду Test Dialog в меню Dialog, которая выводит на экран окно Control Dialog, показанное на рисунке 3.
Рис.3. Диалоговое окно
В этом диалоговом окне содержатся те управляющие элементы, данные которых приведены в основном окне. Вы можете произвольно менять установки этих управляющих элементов. Когда вы выходите из диалогового окна Control Dialog по кнопке ОК, в главном окне появляются новые установки управляющих элементов.
На следующем шаге мы рассмотрим работу программы, приведенную на этом шаге.