Предмет:
Тип роботи:
Лабораторна робота
К-сть сторінок:
18
Мова:
Українська
iMsg, wParam, lParam) ;
}
Форматування виведеного тексту програми KEYLOOK по стовпцях було б важко при використанні пропорційного шрифту, що задається по умовчанню. Для того, щоб одержати вирівняне зображення, код для висновку кожного рядка довелося б розбити на дев'ять секцій. Щоб уникнути всіх цих труднощів, набагато легше просто використати фіксований шрифт. Для цього потрібні дві функції, що тут будуть об'єднані в одну інструкцію:
SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;
Програма KEYLOOK викликає ці дві функції скрізь, де вона одержує контекст пристрою. Це відбувається при обробці повідомлення WM_CREATE і при обробці повідомлення WM_PAINT. Функція GetStockObject одержує дескриптор стандартного графічного об'єкта, яким є фіксований шрифт, використовуваний у ранніх версіях Windows, що передували Windows 3. 0. Виклик функції SelectObject вибирає цей об'єкт у контекст пристрою. Завдяки цьому виклику, весь текст буде виводитися на екран фіксованим шрифтом. Повернутися назад до пропорційного шрифту можна за допомогою функції:
SelectObject (hdc, GetStockObject (SYSTEM_FONT)) ;
Додатки можуть використовувати не тільки об'єкти GDI, створені безпосередньо самим додатком, але користатися визначеними системою об'єктами за допомогою функції GetStockObject, яку можна використовувати для одержання дескриптора різних системних пір’їв, кистей, шрифтів і палітр.
Розміри символу можна одержати за допомогою функції GetTextMetrics. Для цієї функції потрібен дескриптор контексту пристрою, оскільки її значенням, що повертається, є інформація про шрифт, обраний тепер у контексті пристрою. Функція копіює різні значення метричних параметрів тексту в структуру типу TEXTMETRIC.
Структура TEXTMETRIC забезпечує повну інформацію про шрифт, обраний в даний момент у контексті пристрою. Вертикальний розмір шрифту визначається п'ятьма величинами. Два поля описують ширину символу: tmAveCharWidth (усереднена ширина символів рядка) і tmMaxCharWidth (ширина самого широкого символу шрифту). Для фіксованого шрифту ці дві величини однакові.
Тому обробка повідомлення WM_CREATE повинна виглядати так:
#include <windows. h>
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int cxChar, cyChar;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
…
LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{ HDC hdc;
PAINTSTRUCT ps;
TEXTMETRIC tm;
switch (iMsg)
{
case WM_CREATE:
hdc = GetDC (hwnd) ; //одержуємо дескриптор пристрою
SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;
GetTextMetrics (hdc, &tm) ;
cxChar = tm. tmAveCharWidth;
cyChar = tm. tmHeight;
ReleaseDC (hwnd, hdc) ;
return 0;
…
Угорі робочої області програма KEYLOOK малює заголовок таблиці і, таким чином, ідентифікує дев'ять стовпців. Хоча можна створити шрифт, у якому символи будуть підкреслені, тут застосовується трохи інший підхід. Визначено два змінні типу рядка символів, що називаються szTop (у ній міститься текст) і szUnd (у ній містяться символи підкреслення) і при обробці повідомлення WM_PAINT вони виводяться в ту саму позицію у верхній частині вікна. Звичайно Windows виводить текст у режимі «opaque», що означає, що Windows обновляє область фону символу при його виводу на екран. Використання цього режиму фону може призвести до того, що другий символьний рядок (szUnd) зітре перший (szTop). Щоб запобігти цьому, переключіть контекст пристрою в режим «transparent» (режим без заповнення тла символів) :
SetBkMode (hdc, TRANSPARENT) ;
рограма KEYLOOK не зберігає отримані апаратні повідомлення клавіатури, тому після одержання повідомлення WM_PAINT вона не може перемалювати вікно. З цієї причини KEYLOOK просто виводить заголовок таблиці у верхній частині робочої області при обробці повідомлення WM_PAINT. Перед викликом функції BeginPaint, при обробці повідомлення WM_PAINT, KEYLOOK робить недійсним усе вікно. Це дозволяє стерти усе вікно, замість того, щоб стирати недійсний прямокутник.
Тому внесіть у функцію WndProc такий код:
LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{ HDC hdc;
PAINTSTRUCT ps;
static char szTop[] = «Message Key Char Repeat Scan Ext ALT Prev Tran»;
static char szUnd[] = «_______ ___ ____ ______ ____ ___ ___ ____ ____»;
TEXTMETRIC tm;
switch (iMsg)
{
…
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;
SetBkMode (hdc, TRANSPARENT) ;
TextOut (hdc, cxChar, cyChar / 2, szTop, (sizeof szTop) – 1) ; //виводимо заголовок
TextOut (hdc, cxChar, cyChar / 2, szUnd, (sizeof szUnd) – 1) ;
EndPaint (hwnd, &ps) ;
return 0;
case WM_DESTROY:
…
Два верхні рядки повинні залишатися постійно в клієнтській області, а інформація про повідомлення буде прокручуватися, тому нам необхідно знати розміри прямокутника, у якому буде здійснюватися прокручування. Розміри прямокутника будемо зберігати в структурі rect типу RECT. При зміні розмірів робочої області (повідомлення WM_SIZE) необхідно заново одержувати ширину і висоту прямокутника. Верхня границя залишається незмінної і визначається при обробці повідомлення WM_CREATE.
Додайте до програми наступний код:
#include <windows. h>
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
RECT rect;
int cxChar, cyChar;
…
TextOut (hdc, cxChar, cyChar / 2, szUnd, (sizeof szUnd) – 1) ;
EndPaint (hwnd, &ps) ;
return 0;
case WM_SIZE:
rect. right = LOWORD (lParam) ;
rect. bottom = HIWORD (lParam) ;
UpdateWindow (hwnd) ;
return 0;
…
case WM_CREATE:
…
cyChar = tm. tmHeight;
ReleaseDC (hwnd, hdc) ;
rect. top = 3 * cyChar / 2;
return 0;
Дисплей у програмі KEYLOOK буде використовуватися так само, як застарілий пристрій виводу інформації – телетайп. Коли KEYLOOK одержує апаратні повідомлення клавіатури, вони усі обслуговуються однаково: викликається функція ScrollWindow для прокручування умісту всієї робочої області вікна так, щоб цей уміст змістився нагору на висоту одного символу. Функція TextOut використовується для виводу рядка нової інформації на екран, починаючи з висоти одного символу від нижнього краю робочої області. Це майже також просто, як може відбуватися вивод інформації на телетайпі. У першому стовпці показані повідомлення клавіатури, у другому – коди віртуальних клавіш для апаратних повідомлень клавіатури, у третьому – коди символів (і самі символи) для символьних повідомлень і, нарешті, у шести стовпцях, що залишилися, показаний стан шести полів параметра повідомлення lParam. Тому варто створити функцію, що буде займатися виводом у вікно. Це функція ShowKey. Функція ShowKey викликає ScrollWindow для прокручування нагору попередніх рядків перед висновком нового рядка. Звичайно це приводить до того, що частина вікна стає недійсної, і отже генерується повідомлення WM_PAINT. Для того, щоб цього уникнути, у функцію ShowKey включений виклик функції ValidateRect. Занесіть у програму наступний код:
…
}//кінець WinMain
void ShowKey (HWND hwnd, int iType, char *szMessage, WPARAM wParam, LPARAM lParam)
{ static char *szFormat[2] = { «% -14s% 3d% c% 6u% 4d% 3s% 3s% 4s% 4s»,
«% -14s% 3d% c% 6u% 4d% 3s% 3s% 4s% 4s» };
char szBuffer[80];
HDC hdc;
ScrollWindow (hwnd, 0, -cyChar, &rect, &rect) ;
hdc = GetDC (hwnd) ;
SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;
TextOut (hdc, cxChar, rect. bottom – cyChar, szBuffer,
wsprintf (szBuffer, szFormat [iType],
szMessage, wParam,
(BYTE) (iType? wParam: ' '),
LOWORD (lParam),
HIWORD (lParam) & 0xFF,
(PSTR) (0x01000000 & lParam?»Yes»: «No»),
(PSTR) (0x20000000 & lParam?»Yes»: «No»),
(PSTR) (0x40000000 & lParam?»Down»: «Up»),
(PSTR) (0x80000000 & lParam?»Up»: «Down»))) ;
ReleaseDC (hwnd, hdc) ;
ValidateRect (hwnd, NULL) ;
}
…
У приведеному фрагменті коду, останнім параметром функції TextOut () є функція wsprintf (). Ця функція є повним аналогом функції sprintf (), але працює в Windows. У загальному вигляді ця функція виглядає в такий спосіб:
int wsprintf (
LPTSTR lpOut, // покажчик на буфер виводу
LPCTSTR lpFmt, // покажчик на рядок формату
... // аргументи для форматування
) ;
Працює ця функція в такий спосіб: аргументи для форматування форматуются у відповідності з рядком формату lpFmt і заносяться в lpOut.
І, нарешті, додайте код, що використовує тільки що написану функцію ShowKey:
LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
…
case WM_KEYDOWN:
ShowKey (hwnd, 0, «WM_KEYDOWN», wParam, lParam) ;
return 0;
case WM_KEYUP:
ShowKey (hwnd, 0, «WM_KEYUP», wParam, lParam) ;
return 0;
case WM_CHAR:
ShowKey (hwnd, 1, «WM_CHAR», wParam, lParam) ;
return 0;
case WM_DEADCHAR:
ShowKey (hwnd, 1, «WM_DEADCHAR», wParam, lParam) ;
return 0;
case WM_SYSKEYDOWN:
ShowKey (hwnd, 0, «WM_SYSKEYDOWN», wParam, lParam) ;
break; // виклик DefWindowProc
case WM_SYSKEYUP:
ShowKey (hwnd, 0, «WM_SYSKEYUP», wParam, lParam) ;
break; // виклик DefWindowProcghvfbrtu6k 6g vg
case WM_SYSCHAR:
ShowKey (hwnd, 1, «WM_SYSCHAR», wParam, lParam) ;
break; // виклик DefWindowProc
case WM_SYSDEADCHAR:
ShowKey (hwnd, 1, «WM_SYSDEADCHAR», wParam, lParam) ;
break; // виклик DefWindowProc
Програма готова. Запустіть її на виконання.
ПРАКТИЧНА ЧАСТИНА
Створити програму keylook, описану в лабораторній роботі.
Написати програму, що виконує наступні дії: при натисканні символьних клавіш відповідний символ з'являється в рядку, починаючи з лівого верхнього кута.
Контрольні питання
- Що відбувається, коли користувач натискає чи відпускає клавішу на клавіатурі?
- Що таке фокус уведення? Як він зв'язаний з поняттям активного вікна?
- Чи може додаток, що обробляє повідомлення WM_SETFOCUS і WM_KILLFOCUS уплинути на придбання чи утрату фокуса уведення вікном?
- Коли у вікно надходять апаратні повідомлення клавіатури, які типи апаратних повідомлень існують?
- Які повідомлення Windows є апаратними клавіатурними повідомленнями?
- У чому специфіка обробки системних апаратних клавіатурних повідомлень?
- Що таке віртуальний код клавіші? Що він ідентифікує? Чи залежить цей код від апаратної реалізації клавіатури?
- Чому найчастіше додаток обробляє не апаратні повідомлення, а символьні? Що таке символьні повідомлення, як вони формуються?
- Як варто модифікувати цикл обробки повідомлень для того, щоб додаток міг одержувати символьні повідомлення?
- Яке повідомлення є символьним клавіатурним повідомленням і яку додаткову інформацію воно несе із собою?
- Які набори символів використовує Windows, чим вони відрізняються і де застосовуються?