Программирование для IBM OS/2© Александр Фролов, Григорий ФроловТом 25, М.: Диалог-МИФИ, 1993, 286 стр. 8.1. КнопкиРаботая в среде Workplace Shell с приложениями Presentation Manager, вы имели дело с кнопками и переключателями. Последние бывают квадратной либо круглой формы. Переключатели создаются на базе того же самого предопределенного класса окна, что и кнопки прямоугольной формы с надписанным на них текстом или нарисованным графическим изображением. Для создания кнопки или переключателя (а так же других органов управления) используется функция WinCreateWindow . Кнопка создается на базе предопределенного класса окна WC_BUTTON , например, следующим образом: hWndButton = WinCreateWindow (hWnd, WC_BUTTON , "Кнопка", WS_VISIBLE | BS_PUSHBUTTON, 0, 0, 0, 0, hWnd, HWND_TOP , BTN1_ID, NULL, NULL); Заметим, что здесь используется именно функция WinCreateWindow , а не функция WinCreateStdWindow , при помощи которой мы создаем главное окно приложения. Эта функция может быть использована для создания дочернего окна на базе зарегистрированного вами класса. Функция WinCreateWindowПриведем прототип функции WinCreateWindow , предназначенной для создания окон (и, в частности, окон органов управления): HWND WinCreateWindow ( HWND hwndParent, // родительское окно PSZ pszClass, // имя класса PSZ pszName, // заголовок окна ULONG flStyle, // стиль класса окна LONG x, // координата по оси X LONG y, // координата по оси Y LONG cx, // ширина LONG cy, // высота HWND hwndOwner, // окно-владелец HWND hwndInsertBehind, // окно-брат, за которым // отображается окно ULONG id, // идентификатор окна PVOID pCtlData, // управляющие данные PVOID pPresParams); // параметры отображения В качестве параметра hwndParent вы должны указать идентификатор дочернего окна. Параметр pszClass определяет имя класса, на базе которого создается окно. Для кнопки здесь необходимо указать имя WC_BUTTON . Параметр pszName задает текст для окна. Если создается кнопка, то это тот самый текст, который будет написан на кнопке. С помощью параметра flStyle можно указать стиль класса окна, определяющий поведение и внешний вид окон, создаваемых на базе этого класса. Этот параметр мы опишем немного позже. Расположение окна и его размеры определяется параметрами x (координата по оси X), y (координата по оси Y), cx (ширина), cy (высота). Параметр hwndOwner определяет идентификатор окна-владельца, которое будет получать извещающие сообщения от создаваемого дочернего окна. Если вы создаете кнопку, то сообщения, возникающие при ее нажатии, будут передаваться именно в это окно. Через параметр hwndInsertBehind передается идентификатор братского (или сестринского, что одно и то же) окна, за которым будет нарисовано создаваемое окно. Вы можете также указать константы HWND_TOP или HWND_BOTTOM . В первом случае создаваемое окно окажется наверху, во втором - за всеми остальными братскими окнами. Идентификатор, передаваемый через параметр id, играет важную роль при обработке сообщений, поступающих в окно, владеющее создаваемым дочерним окном. Анализируя этот идентификатор, функция окна может определить, от какого окна поступило сообщение. Поэтому если окно создает несколько дочерних окон, каждое из них должно иметь свой идентификатор. При помощи параметра pCtlData (указатель) вы можете передать данные функции создаваемого дочернего окна. Этот указатель будет передан в параметре mp1 сообщения WM_CREATE , поступающего в функцию дочернего окна при его создании. Аналогично, данные, передаваемые через параметр pPresParams, также попадают в функцию дочернего окна через параметр mp2 сообщения WM_CREATE . Для того чтобы понять, как использовать параметр pPresParams, опишем подробнее параметры сообщения WM_CREATE. Сообщение WM_CREATEКак вы уже знаете, сообщение WM_CREATE передается функции окна при его создании. Параметр mp1 этого сообщения содержит значение параметра pCtlData, переданного в функцию WinCreateWindow . В параметр mp2 при этом записывается указатель на следующую структуру: typedef struct _CREATESTRUCT { PVOID pPresParams; // параметры отображения PVOID pCtlData; // управляющие данные ULONG id; // идентификатор окна HWND hwndInsertBehind; // окно-брат, за которым // отображается окно HWND hwndOwner; // окно-владелец LONG cy; // высота окна LONG cx; // ширина окна LONG y; // координата по оси Y LONG x; // координата по оси X ULONG flStyle; // стиль окна PSZ pszText; // заголовок окна PSZ pszClassName; // имя класса HWND hwndParent; // родительское окно } CREATESTRUCT; typedef CREATESTRUCT *PCREATESTRUCT; Нетрудно заметить, что поля этой структуры повторяют аналогичные параметры функции WinCreateWindow . Анализируя поля структуры CREATESTRUCT, обработчик сообщения WM_CREATE может проверить параметры создаваемого окна. Если эти параметры верны, обработчик может вернуть значение FALSE, что разрешает создание окна. Если же один или несколько параметров имеют неправильное знчение, функция окна может вернуть значение TRUE. Окно при этом создано не будет, а функция WinCreateWindow вернет значение NULLHANDLE. Стили кнопокПараметр flStyle определяет стиль класса окна,
влияющий на поведение и внешний вид окон,
создаваемых на базе этого класса. Для кнопок и
переключателей помимо стилей с префиксом WS_,
описанных в начале нашей книги, можно указывать
следующие стили (некоторые стили можно
комбинировать при помощи логической операции
ИЛИ, о чем будет сказано дополнительно):
Установка размеров и расположения кнопкиНачальные размеры и расположение кнопки задаются при ее создании функцией WinCreateWindow . Однако если кнопка расположена не в диалоговой панели, а на поверхности обычного окна приложения, размещение кнопок следует выполнять при обработке сообщения WM_SIZE , например, так: case WM_SIZE : { WinSetWindowPos (hWndButton, HWND_TOP , 10, 10, 200, 50, SWP _SIZE | SWP_MOVE | SWP_ZORDER ); WinInvalidateRect (hWnd, NULL, TRUE); return 0; } Пользователь может изменять размеры окна, при этом, если не заботиться о стирании содержимого окна, он увидит в нем несколько одинаковых кнопок. Функция WinInvalidateRect в приведенном выше фрагменте кода вызывает перерисовку окна hWnd приложения, создавшего в этом окне кнопку hWndButton. Извещение от кнопкиКогда пользователь нажмает на кнопку (или изменяет состояние переключателя), окно-владелец кнопки (идентификатор которого был указан в параметрах функции WinCreateWindow ) получает извещающее сообщение. Код этого сообщения зависит от стиля кнопки. Если не указаны стили BS_SYSCOMMAND или BS_HELP, извещение посылается в виде сообщения WM_COMMAND . Если же указаны перечисленные выше стили, вместо сообщения WM_COMMAND посылаются, соответственно, сообщения WM_SYSCOMMAND или WM_HELP . Что же касается переключателей, то они посылают извещение в форме сообщения WM_CONTROL , которое мы рассмотрим в разделе "Переключатели". Через параметр mp1 сообщения WM_COMMAND передается идентификатор органа управления. Однако вспомним, что сообщение WM_COMMAND посылает также меню приложения. Для того чтобы различить источник извещающего сообщения WM_COMMAND, необходимо проанализировать параметр mp2. Младшее слово параметра mp2 содержит искомый
идентификатор источника сообщения и может
принимать одно из перечисленных ниже значений:
Старшее слово параметра mp2 сообщения WM_COMMAND может содержать значение TRUE или FALSE. В первом случае извещение появилось в результате работы с органом управления при помощи мыши, во втором - при помощи клавиатуры. Для того чтобы было удобнее разбирать параметры сообщения WM_COMMAND , в файле pmwin.h определена структура CMDMSG, указатель на нее PCMDMSG и макрокоманда COMMANDMSG: typedef struct _COMMANDMSG { USHORT cmd; // идентификатор органа управления USHORT unused; // не используется USHORT source; // источник извещающего сообщения USHORT fMouse; // признак использования мыши } CMDMSG; typedef CMDMSG *PCMDMSG; #define COMMANDMSG(pmsg) \ ((PCMDMSG)((PBYTE)pmsg + sizeof(MPARAM))) Обработчик сообщения WM_COMMAND обычно имеет такой вид: case WM_COMMAND : { switch (COMMANDMSG(&msg) -> cmd) { case BTN1_ID: { // Обработка извещения от кнопки BTN1_ID . . . break; } case BTN2_ID: { // Обработка извещения от кнопки BTN2_ID . . . break; } default: break; } return 0; } Если сообщение WM_COMMAND может поступать как от меню, так и от кнопок (или других органов управления), необходимо дополнительно анализировать источник сообщения, например, следующим способом: if(COMMANDMSG (&msg) -> source == CMDSRC_PUSHBUTTON) { // Сообщение от кнопки . . . } else if(COMMANDMSG(&msg) -> source == CMDSRC_MENU) { // Сообщение от меню . . . } Для извлечения параметров кнопки вы можете также использовать макрокоманды SHORT1FROMMP и SHORT2FROMMP : cmd = SHORT1FROMMP (mp1); source = SHORT1FROMMP (mp2); fMouse = SHORT1FROMMP (mp2); Сообщения WM_SYSCOMMAND и WM_HELPРодительское окно может получать извещения от органов управления в форме сообщений WM_SYSCOMMAND или WM_HELP . Первое из этих сообщений приходит, например, когда пользователь нажимает комбинацию клавиш, соответствующую акселератору меню. Сообщение WM_HELP используется приложениями для работы со справочной системой, которую мы опишем в одной из следующих книг "Библиотеки системного программиста", посвященной программированию для IBM OS/2. Что же касается параметров этих сообщений, то они полностью идентичны параметрам сообщения WM_COMMAND . Поэтому для извлечения этих параметров вы можете использовать описанную ранее макрокоманду COMMANDMSG . Управление кнопкамиПриложение при необходимости может управлять состоянием кнопок, блокируя или разблокируя их, а также изменяя состояние кнопок. Для блокировки кнопки необходимо использовать функцию WinEnableWindow, которая имеет следующий прототип: BOOL WinEnableWindow( HWND hwnd, // идентификатор окна BOOL fNewEnabled); // новое состояние Через параметр hwnd вы должны передать этой функции идентификатор окна кнопки. Обращаем внимание, что это идентификатор окна кнопки, который возвращается функцией WinCreateWindow при создании кнопки, а не идентификатор кнопки, передаваемый этой же функции в качестве одного из параметров. Параметр fNewEnabled определяет новое состояние кнопки. Если он равен TRUE, кнопка разблокируется, а если FALSE - блокируется. Заблокированную кнопку нельзя нажать ни мышью, ни при помощи клавиатуры (если такая кнопка имеет фокус ввода). Надпись на заблокированной кнопке отображается серым цветом. Когда состояние кнопки меняется, родительское окно получает сообщение WM_ENABLE. Параметр mp1 этого сообщения указывает новое состояние кнопки и может принимать те же значения, что и описанный только что параметр fNewEnabled функции WinEnableWindow. Параметр mp2 не используется. Сообщение WM_ENABLE - это извещение родительского окна об изменении состояния кнопки. В ответ на это извещение родительское окно может выполнить какие-либо действия, связанные с тем, что данная кнопка оказалась заблокированной или наоборот, разблокированной. |