Программирование для IBM OS/2© Александр Фролов, Григорий ФроловТом 25, М.: Диалог-МИФИ, 1993, 286 стр. 8.8. Приложение SLIDERВ приложении SLIDER мы создаем три круглых регулятора (рис. 8.7), с помощью которых можно изменять цвет окна приложения. Каждый из этих регуляторов изменяет значение цветовой компоненты (красной, зеленой или синей) в диапазоне от 0 до 255 (максимально возможное значение). Устанавливая значения компонент, вы можете выбрать любой цвет окна.
Рис. 8.7. Главное окно приложения SLIDER с регуляторами для изменения компонент цвета окна Исходные тексты приложения приведены в листинге 8.13. Листинг 8.13. Файл slider\slider.c // ================================================= // Определения // ================================================= #define INCL_WIN #define INCL_GPI #define INCL_WINDIALOGS #include <os2.h> #include "slider.h" // Прототип функции окна приложения MRESULT EXPENTRY WndProc(HWND, ULONG, MPARAM, MPARAM); // ================================================= // Глобальные переменные // ================================================= HAB hab; HWND hWndFrame; HWND hWndClient; // Идентификаторы регуляторов HWND hWndCirc1; HWND hWndCirc2; HWND hWndCirc3; // Компоненты цвета SHORT sColorR = 255, sColorG = 255, sColorB = 255; CHAR szAppTitle[] = "Slider 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[] = "SLIDERDEMO"; 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; switch (msg) { case WM_CREATE: { // Создаем регулятор красного цвета hWndCirc1 = WinCreateWindow(hWnd, WC_CIRCULARSLIDER, "Красный", WS_VISIBLE, 0, 0, 0, 0, hWnd, HWND_TOP, CIRCSLD1_ID, NULL, NULL); // Устанавливаем диапазон изменения значений WinSendMsg(hWndCirc1, CSM_SETRANGE, MPFROMLONG(0L), MPFROMLONG(255L)); // Устанавливаем шаг для изменения позиции // и шаг размещения меток WinSendMsg(hWndCirc1, CSM_SETINCREMENT, MPFROMLONG(10L), MPFROMLONG(2L)); // Устанавливаем начальное значение WinSendMsg(hWndCirc1, CSM_SETVALUE, MPFROMLONG(255L), NULL); // Создаем регулятор зеленого цвета // и настраиваем его параметры hWndCirc2 = WinCreateWindow(hWnd, WC_CIRCULARSLIDER, "Зеленый", WS_VISIBLE, 0, 0, 0, 0, hWnd, HWND_TOP, CIRCSLD2_ID, NULL, NULL); WinSendMsg(hWndCirc2, CSM_SETRANGE, MPFROMLONG(0L), MPFROMLONG(255L)); WinSendMsg(hWndCirc2, CSM_SETINCREMENT, MPFROMLONG(10L), MPFROMLONG(2L)); WinSendMsg(hWndCirc2, CSM_SETVALUE, MPFROMLONG(255L), NULL); // Создаем регулятор синего цвета // и настраиваем его параметры hWndCirc3 = WinCreateWindow(hWnd, WC_CIRCULARSLIDER, "Синий", WS_VISIBLE, 0, 0, 0, 0, hWnd, HWND_TOP, CIRCSLD3_ID, NULL, NULL); WinSendMsg(hWndCirc3, CSM_SETRANGE, MPFROMLONG(0L), MPFROMLONG(255L)); WinSendMsg(hWndCirc3, CSM_SETINCREMENT, MPFROMLONG(10L), MPFROMLONG(2L)); WinSendMsg(hWndCirc3, CSM_SETVALUE, MPFROMLONG(255L), NULL); return FALSE; } // Изменяем размер и расположение регуляторов case WM_SIZE: { WinSetWindowPos(hWndCirc1, HWND_TOP, 0, 0, 150, 150, SWP_SIZE | SWP_MOVE | SWP_ZORDER); WinSetWindowPos(hWndCirc2, HWND_TOP, 150, 0, 150, 150, SWP_SIZE | SWP_MOVE | SWP_ZORDER); WinSetWindowPos(hWndCirc3, HWND_TOP, 300, 0, 150, 150, SWP_SIZE | SWP_MOVE | SWP_ZORDER); // Перерисовываем окно приложения WinInvalidateRect(hWnd, NULL, TRUE); return 0; } case WM_PAINT: { // Получаем пространство отображения hps = WinBeginPaint(hWnd, NULLHANDLE, &rec); // Переключаем таблицу цветов в режим RGB GpiCreateLogColorTable(hps, LCOL_RESET, LCOLF_RGB, 0L, 0L, NULL); // Закрашиваем область, требующую обновление WinFillRect(hps, &rec, (ULONG)sColorR << 16 | (ULONG)sColorG << 8 | (ULONG)sColorB); // Возвращаем пространство отображения WinEndPaint(hps); return 0; } case WM_ERASEBACKGROUND: return(MRFROMLONG(1L)); case WM_CONTROL: { // Сообщение пришло от красного регулятора if(SHORT1FROMMP(mp1) == CIRCSLD1_ID) { // Выделяем код извещения if(SHORT2FROMMP(mp1) == CSN_CHANGED) { // Устанавливаем новое значение цвета sColorR = (SHORT)mp2; // Перерисовываем окно WinInvalidateRect(hWnd, NULL, TRUE); } } // Сообщение от зеленого регулятора else if(SHORT1FROMMP(mp1) == CIRCSLD2_ID) { if(SHORT2FROMMP(mp1) == CSN_CHANGED) { sColorG = (SHORT)mp2; WinInvalidateRect(hWnd, NULL, TRUE); } } // Сообщение от синего регулятора else if(SHORT1FROMMP(mp1) == CIRCSLD3_ID) { if(SHORT2FROMMP(mp1) == CSN_CHANGED) { sColorB = (SHORT)mp2; WinInvalidateRect(hWnd, NULL, TRUE); } } return 0; } default: return(WinDefWindowProc(hWnd, msg, mp1, mp2)); } } Глобальные переменныеВ глобальных переменных hWndCirc1, hWndCirc2 и hWndCirc3 хранятся идентификаторы регуляторов цвета, создаваемых при обработке сообщения WM_CREATE. Текущие значения отдельных цветовых компонент записываются в переменные sColorR (красный цвет), sColorG (зеленый цвет) и sColorB (синий цвет). Функция mainВ функции main создается очередь сообщений, регистрируется класс для главного окна приложения, создается это окно и запускается цикл обработки сообщений. Функция WndProcЭта функция выполняет обработку сообщений, поступающих в главное окно приложения. Наибольший интерес для нас представляют сообщения WM_CREATE, обработчик которого создает круглые регуляторы, и WM_CONTROL, посредством которого в окно приложения поступают извещения от этих регуляторов. Сообщение WM_CREATEОбработчик сообщения WM_CREATE создает три одинаковых регулятора, предназначенных для установки красной, зеленой и синей компоненты цвета фона окна Client Window. Все эти регуляторы создаются функцией WinCreateWindow на базе предопределенного класса окна WC_CIRCULARSLIDER. Для каждого регулятора устанавливается диапазон изменения значений от 0 до 255. Последнее значение соответствует наиболее насыщенному цвету. Установка диапазона изменения значений выполняется при помощи сообщения CSM_SETRANGE, которое посылается по очереди окнам всех трех регуляторов. Аналогично при помощи сообщения CSM_SETINCREMENT устанавливается шаг изменения позиции, равный 10, и шаг размещения меток, равный 2. Начальное значение всех регуляторов устанавливается равным 255, для чего окнам регуляторов посылается сообщение CSM_SETVALUE. При этом цвет окна будет белым, так как компоненты цвета имеют максимальную насыщенность и смешиваются в равной пропорции. Сообщение WM_SIZEПри обработке сообщения WM_SIZE устанавливаются расположение и размеры регуляторов, для чего используется функция WinSetWindowPos. Все регуляторы будут расположены рядом в нижней части окна Client Window. Перед тем как возвратить управление, обработчик сообщения WM_SIZE вызывает функцию WinInvalidateRect для перерисовки окна приложения. Сообщение WM_PAINTПри обработке сообщения WM_PAINT выполняется переключение таблицы цветов, установленной для пространства отображения, в режим RGB , когда цвет определяется тремя цветовыми компонентами. Для этого вызывается функция GpiCreateLogColorTable , которая будет описана в одном из следующих томов "Библиотеки системного программиста" в разделе, посвященном графическому интерфейсу Presentation Manager. GpiCreateLogColorTable(hps, LCOL_RESET, LCOLF_RGB, 0L, 0L, NULL); Далее внутренняя область окна закрашивается функцией WinFillRect: WinFillRect(hps, &rec, (ULONG)sColorR << 16 | (ULONG)sColorG << 8 | (ULONG)sColorB); При этом цвет образуется из компонент, хранящихся в глобальных переменных sColorR, sColorG и sColorB. Когда пользователь вращает ручки регуляторов, в функцию окна поступает сообщение WM_CONTROL. Обработчик этого сообщения изменяет соответствующим образом содержимое указанных глобальных переменных и перерисовывает окно приложения. Сообщение WM_CONTROLОбработчик сообщения WM_CONTROL прежде всего анализирует младшее слово параметра mp1, через который передается идентификатор органа управления (в нашем случае, идентификатор одного из трех регуляторов). Далее из старшего слова параметра mp1 выделяется код извещения, и если он равен SLN_CHANGE, сохраняется новое значение позиции регулятора, передаваемое через параметр mp2: if(SHORT1FROMMP(mp1) == CIRCSLD1_ID) { if(SHORT2FROMMP(mp1) == CSN_CHANGED) { sColorR = (SHORT)mp2; WinInvalidateRect(hWnd, NULL, TRUE); } } После изменения значения глобальной переменной, в которой хранится компонента цвета, вызывается функция WinInvalidateRect, что приводит к перерисовке окна приложения. Файл slider.hФайл slider.h (листинг 8.14) содержит определения константы ID_APP_FRAMEWND, а также идентификаторов круглых регуляторов цвета CIRCSLD1_ID, CIRCSLD2_ID и CIRCSLD3_ID. Листинг 8.14. Файл slider\slider.h #define ID_APP_FRAMEWND 1 #define CIRCSLD1_ID 100 #define CIRCSLD2_ID 101 #define CIRCSLD3_ID 102 Файл slider.rcФайл описания ресурсов приложения slider.rc представлен в листинге 8.15. Листинг 8.15. Файл slider\slider.rc #include <os2.h> #include "slider.h" ICON ID_APP_FRAMEWND SLIDER.ICO Файл slider.defФайл определения модуля приложения slider.def приведен в листинге 8.16. Листинг 8.16. Файл slider\slider.def NAME SLIDER WINDOWAPI DESCRIPTION 'Slider Application (C) Frolov A., 1996' HEAPSIZE 4096 STACKSIZE 32768 EXPORTS WndProc |