Программирование для IBM OS2

         

Приложение KBDMSG


Изучение параметров сообщения WM_CHAR удобно выполнять с помощью приложения KBDMSG, которое отображает эти параметры в своем окне (рис. 5.1).

Рис. 5.1. Просмотр клавиатурных сообщений в окне приложения KBDMSG

В столбце VKEY отображается виртуальный код нажатой клавиши, в столбце SCAN - аппаратный скан-код, в столбце FS - флаги. Далее в столбце REPT отображается счетчик повторений и в столбце CHAR - символ (только для символьных клавиш).

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

Исходные тексты приложения приведены в листинге 5.1.

Листинг 5.1. Файл kbdmsg\kbdmsg.c

// ================================================= // Определения // =================================================

#define INCL_WIN #define INCL_GPI #define INCL_WINDIALOGS #include <os2.h> #include <stdio.h> #include <string.h> #include "kbdmsg.h"

// Прототип функции окна приложения MRESULT EXPENTRY WndProc(HWND, ULONG, MPARAM, MPARAM);

// ================================================= // Глобальные переменные // =================================================

HAB hab; HWND hWndFrame; HWND hWndClient;

CHAR szAppTitle[] = "Keyboard Messages";

// Размеры окна Client Window SHORT cxClient; SHORT cyClient;

// Размеры символов выбранного шрифта SHORT cxChar, cyChar, cyDesc;

// Заголовок столбцов CHAR szTitle[] = "VKEY SCAN FS REPT CHAR";



// ================================================= // Главная функция приложения 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[] = "KBDMSG";

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) { CHAR szMsg[100]; int nMsgSize; HPS hps; POINTL ptl; RECTL rec;

CHRMSG cm; FONTMETRICS fm;

switch (msg) { // При создании главного окна приложения // определяем и сохраняем метрики шрифта // с фиксированной шириной символов case WM_CREATE : { // Получаем пространство отображения hps = WinGetPS (hWnd);

// Выбираем в пространство отображения шрифт // с фиксированной шириной символов SetCourierFont(hps);

// Определяем метрики шрифта GpiQueryFontMetrics(hps, (LONG)sizeof(fm), &fm);

cxChar = fm.lAveCharWidth; cyChar = fm.lMaxBaselineExt; cyDesc = fm.lMaxDescender;

// Устанавливаем шрифт, выбранный в пространство // отображения по умолчанию ResetFont(hps);



// Возвращаем пространство отображения WinReleasePS (hps); return FALSE; }

// Во время перерисовки стираем содержимое // окна и выводим строку заголовка таблицы case WM_PAINT : { // Получаем пространство отображения hps = WinBeginPaint (hWnd, NULLHANDLE, &rec);

// Закрашиваем область, требующую обновление WinFillRect (hps, &rec, CLR_WHITE);

// Выбираем в пространство отображения шрифт // с фиксированной шириной символов SetCourierFont(hps);

// Рисуем заголовок таблицы в нижней части окна ptl.x = cxChar; ptl.y = cyDesc + cyChar; GpiCharString At (hps, &ptl, strlen(szTitle), szTitle);

// Устанавливаем шрифт, выбранный в пространство // отображения по умолчанию ResetFont(hps);

// Возвращаем пространство отображения WinEndPaint (hps); return 0; }

case WM_ERASEBACKGROUND : return(MRFROMLONG(1L));

// При изменении размеров окна сохраняем новые // размеры и перерисовываем окно case WM_SIZE : { cxClient = SHORT1FROMMP (mp2); cyClient = SHORT2FROMMP (mp2);

// Все окно требует перерисовки WinInvalidateRect (hWnd, NULL, TRUE); return 0; }

// Это сообщение появляется, когда пользователь // нажимает или отжимает клавишу case WM_CHAR : { // Получаем пространство отображения hps = WinGetPS (hWnd);

// Выбираем в пространство отображения шрифт // с фиксированной шириной символов SetCourierFont(hps);

// Выделяем параметры клавиатурного сообщения // и сохраняем их в структуре cm cm.chr = CHARMSG(&msg) ->chr; cm.vkey = CHARMSG(&msg) ->vkey; cm.scancode = CHARMSG(&msg) ->scancode; cm.cRepeat = CHARMSG(&msg) ->cRepeat; cm.fs = CHARMSG(&msg) ->fs;

// Готовим строку для отображения параметров // клавиатурного сообщения sprintf (szMsg, "%04x %04x %04x %d %c", cm.vkey, cm.scancode, cm.fs, cm.cRepeat, cm.fs & KC_CHAR ? cm.chr : ' ');

// Отображаем строку над заголовком таблицы // в нижней части окна ptl.x = cxChar; ptl.y = 2 * cyChar + cyDesc;

nMsgSize = strlen(szMsg); GpiCharString At (hps, &ptl, nMsgSize, szMsg);



// Устанавливаем шрифт, выбранный в пространство // отображения по умолчанию ResetFont(hps);

// Возвращаем пространство отображения WinReleasePS (hps);

// Устанавливаем границы сдвигаемой области окна WinSetRect (hab, &rec, 0, 2 * cyChar, cxClient, cyClient);

// Выполняем сдвиг верхней части окна WinScrollWindow (hWnd, 0, cyChar + cyDesc, &rec, NULL, NULLHANDLE, NULL, SW_INVALIDATERGN );

return 0; }

default: return(WinDefWindowProc (hWnd, msg, mp1, mp2)); } }

// ================================================= // Выбор шрифта с фиксированной шириной символов // =================================================

void SetCourierFont(HPS hps) { FATTRS fat;

// Заполняем структуру описанием нужного // нам шрифта

// Размер структуры fat.usRecordLength = sizeof(FATTRS);

// Название шрифта strcpy(fat.szFacename ,"Courier");

// Используем нормальный шрифт без выделений // наклоном, подчеркиванием и т. п. fat.fsSelection = 0;

// Указываем, что система Presentation Manager должна // подобрать шрифт, подходящий к нашему описанию fat.lMatch = 0L;

// Регистрационный номер, должен быть равен 0 fat.idRegistry = 0;

// Кодовая страница fat.usCodePage = 850;

// Высота шрифта fat.lMaxBaselineExt = 12L;

// Ширина шрифта fat.lAveCharWidth = 12L;

// Тип шрифта - обычный без использования кернинга, // двухбайтовых символов и т. д. fat.fsType = 0;

// Использование шрифта - шрифт, который отображается // без смешивания с графикой fat.fsFontUse = FATTR_FONTUSE_NOMIX;

// Создаем логический шрифт, имеющий идентификатор 1L GpiCreateLogFont(hps, NULL, 1L, &fat);

// Выбираем созданный шрифт в пространство // отображения GpiSetCharSet (hps, 1L); }

// ================================================= // Установка шрифта, выбранного в пространство // отображения по умолчанию // ================================================= void ResetFont(HPS hps) { // Выбираем шрифт по умолчанию GpiSetCharSet (hps, LCID_DEFAULT);

// Удаляем созданный ранее шрифт // с идентификатором 1L GpiDeleteSetId(hps, 1L); }


Содержание раздела