Программирование для IBM OS/2© Александр Фролов, Григорий ФроловТом 25, М.: Диалог-МИФИ, 1993, 286 стр. 8.4. Приложение CHECKДля демонстрации техники работы с переключателями мы подготовили исходные тексты приложения CHECK. В своем главном окне (рис. 8.3) это приложение создает кнопку и два переключателя. Первый из этих переключателей обычный, а второй - автоматический.
Рис. 8.3. Главное окно приложения CHECK При помощи мыши вы можете изменять состояние переключателей с номерами 2 и 3 (первый номер присвоен кнопке с надписью "Переключатели"). Второй переключатель - автоматический и имеет стиль BS_AUTOCHECKBOX, третий - обычный со стилем BS_CHECKBOX. Если после установки состояния переключателей нажать кнопку, расположенную в нижней части окна приложения, на экране появится диалоговая панель, отображающая текущее состояние переключателей. Эта панель показана на рис. 8.2. Исходные тексты приложения CHECK приведены в листинге 8.5. Листинг 8.5. Файл check\check.c
// =================================================
// Определения
// =================================================
#define INCL_WIN
#define INCL_GPI
#define INCL_WINDIALOGS
#include <os2.h>
#include <stdio.h>
#include "check.h"
// Прототип функции окна приложения
MRESULT EXPENTRY WndProc(HWND, ULONG, MPARAM, MPARAM);
// =================================================
// Глобальные переменные
// =================================================
HAB hab;
HWND hWndFrame;
HWND hWndClient;
// Идентификаторы кнопок
HWND hWndButton1;
HWND hWndButton2;
HWND hWndButton3;
// Состояние переключателей
BOOL fButton2Checked = FALSE;
BOOL fButton3Checked = FALSE;
CHAR szAppTitle[] = "CheckBox Demo";
// =================================================
// Главная функция приложения main
// =================================================
int main ()
{
HMQ hmq;
QMSG qmsg;
BOOL fRc;
// Флаги для создания окна Frame Window
ULONG flFrameFlags =
FCF_SYSMENU | FCF_TITLEBAR | FCF_MINMAX |
FCF_SIZEBORDER | FCF_SHELLPOSITION | FCF_TASKLIST |
FCF_ICON;
// Имя класса главного окна
CHAR szWndClass[] = "BTNDEMO";
hab = WinInitialize (0);
if(hab == NULLHANDLE)
{
WinMessageBox (HWND_DESKTOP, HWND_DESKTOP,
"Ошибка инициализации",
"Ошибка", 0, MB_ICONHAND | MB_OK);
return(-1);
}
// Создаем очередь сообщений
hmq = WinCreateMsgQueue (hab, 0);
if(hmq == NULLHANDLE)
{
WinMessageBox (HWND_DESKTOP, HWND_DESKTOP,
"Ошибка при создании очереди сообщений",
"Ошибка", 0, MB_ICONHAND | MB_OK);
WinTerminate (hab);
return(-1);
}
// Регистрация главного окна приложения
fRc = WinRegisterClass (hab, szWndClass,
(PFNWP)WndProc, 0, 0);
if(fRc == FALSE)
{
WinMessageBox (HWND_DESKTOP, HWND_DESKTOP,
"Ошибка при регистрации класса главного окна",
"Ошибка", 0, MB_ICONHAND | MB_OK);
WinDestroyMsgQueue (hmq);
WinTerminate (hab);
return(-1);
}
// Создаем главное окно приложения
hWndFrame = WinCreateStdWindow (HWND_DESKTOP,
WS_VISIBLE ,
&flFrameFlags, szWndClass, szAppTitle,
0, 0, ID_APP_FRAMEWND, &hWndClient);
if(hWndFrame == NULLHANDLE)
{
WinMessageBox (HWND_DESKTOP, HWND_DESKTOP,
"Ошибка при создании главного окна",
"Ошибка", 0, MB_ICONHAND | MB_OK);
WinDestroyMsgQueue (hmq);
WinTerminate (hab);
return(-1);
}
// Запускаем цикл обработки сообщений
while(WinGetMsg (hab, &qmsg, 0, 0, 0))
WinDispatchMsg (hab, &qmsg);
WinDestroyWindow(hWndFrame);
WinDestroyMsgQueue (hmq);
WinTerminate (hab);
return(0);
}
// =================================================
// Функция главного окна приложения
// =================================================
MRESULT EXPENTRY
WndProc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
HPS hps;
RECTL rec;
CHAR szBuf[256];
switch (msg)
{
// Создаем кнопку и два переключателя
case WM_CREATE :
{
hWndButton1 = WinCreateWindow (hWnd, WC_BUTTON ,
"Переключатели", WS_VISIBLE | BS_PUSHBUTTON,
0, 0, 0, 0,
hWnd, HWND_TOP , BTN1_ID, NULL, NULL);
// Автоматический переключатель
hWndButton2 = WinCreateWindow (hWnd, WC_BUTTON ,
"(2) AutoCheckBox",
WS_VISIBLE | BS_AUTOCHECKBOX,
0, 0, 0, 0,
hWnd, HWND_TOP , BTN2_ID, NULL, NULL);
// Обычный переключатель
hWndButton3 = WinCreateWindow (hWnd, WC_BUTTON ,
"(3) CheckBox", WS_VISIBLE | BS_CHECKBOX,
0, 0, 0, 0,
hWnd, HWND_TOP , BTN3_ID, NULL, NULL);
return FALSE;
}
// Изменяем размер и расположение органов
// управления
case WM_SIZE :
{
WinSetWindowPos (hWndButton1, HWND_TOP ,
10, 10, 200, 50,
SWP _SIZE | SWP_MOVE | SWP_ZORDER );
WinSetWindowPos (hWndButton2, HWND_TOP ,
10, 70, 200, 50,
SWP _SIZE | SWP_MOVE | SWP_ZORDER );
WinSetWindowPos (hWndButton3, HWND_TOP ,
10, 110, 200, 50,
SWP _SIZE | SWP_MOVE | SWP_ZORDER );
// Перерисовываем окно приложения
WinInvalidateRect (hWnd, NULL, TRUE);
return 0;
}
case WM_PAINT :
{
// Получаем пространство отображения
hps = WinBeginPaint (hWnd, NULLHANDLE, &rec);
// Закрашиваем область, требующую обновление
WinFillRect (hps, &rec, CLR_WHITE);
// Возвращаем пространство отображения
WinEndPaint (hps);
return 0;
}
case WM_ERASEBACKGROUND :
return(MRFROMLONG(1L));
// Это сообщение приходит при изменении
// состояния переключателей
case WM_CONTROL :
{
switch (SHORT1FROMMP (mp1))
{
// Если сообщение пришло от автоматического
// переключателя, получаем и сохраняем его
// текущее состояние
case BTN2_ID:
{
fButton2Checked = (BOOL)
WinSendMsg (hWndButton2,
BM_QUERYCHECK, MPFROMSHORT(0), NULL);
break;
}
// Если сообщение пришло от обычного
// переключателя, изменяем его состояние
// и сохраняем новое состояние
// в переменной fButton3Checked
case BTN3_ID:
{
if(fButton3Checked)
WinSendMsg (hWndButton3, BM_SETCHECK,
MPFROMSHORT(0), NULL);
else
WinSendMsg (hWndButton3, BM_SETCHECK,
MPFROMSHORT(1), NULL);
fButton3Checked = ~fButton3Checked;
break;
}
default:
break;
}
return 0;
}
// Когда пользователь нажимает кнопку,
// определяем и сохраняем состояние
// обоих переключателей
case WM_COMMAND :
{
switch (COMMANDMSG(&msg) -> cmd)
{
case BTN1_ID:
{
sprintf (szBuf, "Состояние переключаталей:\n"
"(3) третий - %d\n(2) второй - %d",
fButton3Checked ? 1 : 0,
fButton2Checked ? 1 : 0);
WinMessageBox (HWND_DESKTOP, hWnd, szBuf,
"Состояние переключателей", 0,
MB_INFORMATION | MB_APPLMODAL |
MB_MOVEABLE | MB_OK);
break;
}
default:
break;
}
return 0;
}
default:
return(WinDefWindowProc (hWnd, msg, mp1, mp2));
}
}
Глобальные переменныеВ области глобальных переменных определены переменные hWndButton1, hWndButton2 и hWndButton3, предназначенные, соответственно, для хранения идентификаторов кнопки и двух переключателей. Состояние переключателей записывается в переменные fButton2Checked и fButton3Checked. Функция mainФункция main не имеет никаких особенностей. Она создает главное окно приложения, очередь сообщений и затем запускает цикл обработки сообщений. Функция WndProcРассмотрим обработку сообщений, выполняемую функцией WndProc. Сообщение WM_CREATEОбработчик сообщения WM_CREATE создает кнопку и два переключателя. Идентификатор окна кнопки записывается в переменную hWndButton1. Идентификатор кнопки равен BTN1_ID. Первый из создаваемых переключателей имеет стиль BS_AUTOCHECKBOX и работает автоматически. Идентификатор окна автоматического переключателя хранится в переменной hWndButton2, а идентификатор переключателя равен BTN2_ID. Второй переключатель создается с использованием стиля BS_CHECKBOX. Идентификатор окна для него хранится в переменной hWndButton3, а идентификатор самого переключателя равен BTN3_ID. При создании кнопки для размеров и места расположения мы указали нулевые значения, так как размещение органов управления и определение их размеров будет выполняться при обработке сообщения WM_SIZE . Сообщение WM_SIZEОбработчик сообщения WM_SIZE располагает кнопку в нижней части окна. Выше нее размещаются переключатели. Изменение расположения и размеров органов управления выполняется функцией WinSetWindowPos . Перед возвращением управления обработчик сообщения WM_SIZE заказывает перерисовку окна, вызывая функцию WinInvalidateRect . Окно будет перерисовано при обработке сообщения WM_PAINT . Сообщение WM_CONTROLЭто сообщение поступает в функцию окна тогда, когда пользователь делает щелчок мышью по одному из двух переключателей, расположенных в окне. Внешний вид и состояние автоматического переключателя изменяется сразу после щелчка, поэтому все, что делает обработчик сообщения WM_CONTROL для автоматического переключателя - это определяет его текущее состояние. Для этого окну переключателя при помощи функции WinSendMsg посылается сообщение BM_QUERYCHECK. Полученное от этой функции состояние записывается в переменную fButton2Checked. Работа с обычным переключателем требует от программиста несколько больших усилий, так как его состояние необходимо изменять из приложения. Состояние переключателя BTN3_ID хранится в переменной fButton3Checked и сразу после инициализации приложения равно нулю. Когда пользователь делает щелчок мышью по обычному переключателю, в функцию окна приходит сообщение WM_CONTROL с идентификатором органа управления, равным BTN3_ID. Обработчик сообщения WM_CONTROL в этом случае проверяет содержимое переменной fButton3Checked и выполняет включение, либо выключение переключателя. Для управления переключателем с помощью функции WinSendMsg ему посылается сообщение BM_SETCHECK. Если переключатель необходимо включить, параметр mp1 этого сообщения равен 1, если выключить - 0. После изменения состояния переключателя обработчик сообщения WM_CONTROL соответствующим образом изменяет содержимое переменной fButton3Checked. Сообщение WM_COMMANDОкно нашего приложения создает единственную кнопку, посылающую сообщение WM_COMMAND после того как пользователь сделает по ней щелчок мышью. В ответ на это сообщение функция окна формирует текстовую строку szBuf, включая в нее состояние обоих переключателей: sprintf (szBuf, "Состояние переключаталей:\n" "(3) третий - %d\n(2) второй - %d", fButton3Checked ? 1 : 0, fButton2Checked ? 1 : 0); Эта строка будет использована для отображения в диалоговой панели, создаваемой на экране функцией WinMessageBox . Обратите внимание, что для принудительного перехода на новую строку в этой диалоговой панели мы включили в строку символы \n. Файл check.hФайл check.h (листинг 8.6) содержит определения константы ID_APP_FRAMEWND и идентификаторов органов управления BTN1_ID, BTN2_ID и BTN3_ID. Листинг 8.6. Файл check\check.h #define ID_APP_FRAMEWND 1 #define BTN1_ID 100 #define BTN2_ID 101 #define BTN3_ID 102 Файл check.rcФайл описания ресурсов приложения check.rc (листинг 8.7) содержит только описание пиктограммы. Листинг 8.7. Файл check\check.rc #include <os2.h> #include "check.h" ICON ID_APP_FRAMEWND CHECK.ICO Файл check.defФайл определения модуля прилоджения check.def приведен в листинге 8.8. Листинг 8.8. Файл check\check.def NAME CHECK WINDOWAPI DESCRIPTION 'Check Box Application (C) Frolov A., 1996' HEAPSIZE 4096 STACKSIZE 32768 EXPORTS WndProc |

