Шаг 55.
Библиотека OWL.
Управляющие элементы окна

    На этом шаге мы рассмотрим создание и использование управляющих элементов.

    Диалоговые окна являются объектами, которые наиболее широко используются для получения информации от пользователя в приложении Windows. Конечно, диалоговые окна не очень удобны без тех элементов управления, которые можно в них поместить. Области ввода, окна списков, комбинированнные окна, радиокнопки, кнопки с независимой фиксацией, линейки прокрутки и другие управляющие элементы - все вместе работают, чтобы обеспечить удобство ввода данных в программу пользователю данного приложения.

    Хотя управляющие элементы наиболее часто используются в диалоговых окнах, они могут размещаться в любом окне. В самом деле, основное различие между размещением управляющих элементов в диалоговом окне и их размещением в окне другого типа заключается в той процедуре, которая обеспечивает введение управляющих элементов в окно. При работе с диалоговыми окнами управляющие элементы можно "нарисовать" в этом окне с помощью Resource Workshop, задолго до первого запуска пользователем вашей программы. При работе с окном другого типа вы создаете и размещаете управляющие элементы внутри вашего приложения, что требует больших усилий.

    Начиная с этого шага вы научитесь работать с управляющими элементами в диалоговых окнах и в окнах других типов. Вы также узнаете о новых способах получения информации с помощью элементов, управляющих окнами.

    До сих пор речь шла о диалоговых окнах, содержащих такие базовые управляющие элементы как области ввода и кнопки. Области ввода и кнопки, вероятно, являются нанболее важными управляющими элементами, имеющимися в вашем распоряжении. Однако вы зачастую можете предоставить пользователю вашей программы более простые способы выбора данных, которые должны быть введены в программу.

    Имеется несколько типов управляющих элементов, которые вы можете разместить в диалоговом окне, включая кнопки с независимой фиксацией, окна списков, комбинированные окна, линейки прокрутки. Вы уже, видимо, знакомы с тем, как работают эти управляющие элементы, как с точки зрения пользователя, так и с точки зрения программиста. Если вам никогда не приходилось программировать с использованием ObjectWindows, вы можете не знать тех классов, в которых OWL инкапсулирует каждый из этих управляющих элементов. К этим классам относятся TCheckBox, TRadioButton, TGroupBox, TListBox, TComboBox и TScrollBar. К другим классам управляющих элементов, которыми вы уже пользовались, относятся TEdit и TButton.

   


Замечание. Хотя OWL содержит классы, в которых инкапсулируются оконные управляющие элементы, однако Windows обеспечивает боыпинство сервисных средств, необходимых для работы с этими управляющими элементами. Ниже следует описание каждого из управляющих элементов окон.

    Как упоминалось выше, любой из этих элементов управления вы можете ввести в диалоговое окно, попросту используя 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 по кнопке ОК, в главном окне появляются новые установки управляющих элементов.

    На следующем шаге мы рассмотрим работу программы, приведенную на этом шаге.




Предыдущий шаг Содержание Следующий шаг