Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Lab_progr_Win / Lab2.doc
Скачиваний:
11
Добавлен:
23.03.2015
Размер:
445.44 Кб
Скачать

Лабораторна робота №2.

Тема роботи: Робота з клавіатурою.

Ціль роботи: Придбання досвіду створення прикладного програмного забезпечення для Windows, взаємодіючого з клавіатурою, із використанням алгоритмічної мови Сі++.

Теоретична частина

Хоча Windows підтримує як пристрій уведення інформації миша, робота з клавіатурою як і раніше превалює. При створенні додатків рекомендується реалізувати усі функціональні можливості програми не тільки за допомогою миші, але і за допомогою клавіатури.

Синхронізація подій клавіатури

Заснована на повідомленнях архітектура Windows ідеальна для роботи з клавіатурою.

Додаток узнає про натискання клавіш за допомогою повідомлень, що посилаються віконній процедурі. Коли користувач натискає і відпускає клавіші:

  • Драйвер клавіатури передає інформацію про натискання клавіш у Windows.

  • Windows зберігає цю інформацію (у виді повідомлень) у системній черзі повідомлень.

  • Потім вона передає повідомлення клавіатури, по одному за раз, у чергу повідомлень програми, що містить вікно та має фокус уведення (input focus).

  • Потім програма відправляє повідомлення відповідній віконній процедурі (за допомогою функції DispatchMessage).

Зміст цього двоступінчастого процесу - збереження повідомлень у системній черзі повідомлень і подальша їхня передача в чергу повідомлень додатка - у синхронізації.

Якщо користувач друкує на клавіатурі швидше, ніж програма може обробляти інформацію, що надходить, Windows зберігає інформацію про додаткові натискання клавіш у системній черзі повідомлень, оскільки одне з додаткових натискань може бути переключенням фокуса введення на іншу програму. Інформацію про наступні натискання варто потім направляти в іншу програму. Таким чином, Windows коректно синхронізує такі події клавіатури.

Для відображення різних подій клавіатури, Windows посилає програмам вісім різних повідомлень. Програми цілком можуть ігнорувати багато яки з них; крім того, у більшості випадків, у цих повідомленнях від клавіатури міститься значно більше закодованої інформації, ніж потрібно додатку.

Зауваження. Застава успішної роботи з клавіатурою - це знання того, які повідомлення важливі для додатка, а які ні.

Апаратні повідомлення.

Коли користувач натискає клавішу, Windows поміщає або повідомлення WM_KEYDOWN, або повідомлення WM_SYSKEYDOWN у чергу повідомлень вікна, що має фокус уведення. Коли клавіша відпускається, Windows поміщає в чергу повідомлень або повідомлення WM_KEYUP, або повідомлення WM_SYSKEYUP.

Отже,

  • Несистемні апаратні повідомлення - це повідомлення WM_KEYDOWN і WM_KEYUP, а системні - WM_SYSKEYDOWN і WM_SYSKEYUP.

  • Системні апаратні повідомлення WM_SYSKEYDOWN і WM_SYSKEYUP більш важливі для Windows, чим для додатків. Ці повідомлення звичайно виробляються при натисканні клавіш у сполученні з клавішею <Alt>. Ці повідомлення викликають опції меню чи програми системного меню, чи використовуються для системних функцій, таких як зміна активного додатка (<Alt+Tab>).

Програми звичайно ігнорують повідомлення WM_SYSKEYDOWN і WM_SYSKEYUP і передають їх у функцію DefWindowProc. Віконна процедура, зрештою, одержує інші повідомлення, що є результатом цих апаратних повідомлень клавіатури (наприклад, вибір меню).

Несистемні повідомлення WM_KEYDOWN і WM_KEYUP звичайно виробляються для клавіш, що натискаються і відпускаються без участі клавіші <Alt>. Додаток може використовувати чи не використовувати ці повідомлення клавіатури. Сама Windows їх проігнорує.

Звичайно повідомлення про натискання і відпускання з'являються парами. Однак якщо користувач залишить клавішу натиснутої так, щоб уключилося автоповторення, то Windows посилає віконній процедурі серію повідомлень WM_KEYDOWN (або WM_SYSKEYDOWN) і одне повідомлення WM_KEYUP (чи WM_SYSKEYUP), коли, зрештою, клавіша буде відпущена.

Також як і всі синхронні повідомлення, апаратні повідомлення клавіатури також стають у чергу. Додаток за допомогою функції GetMessageTime одержує час натискання і відпускання клавіші щодо старту системи.

Для всіх апаратних повідомлень клавіатури 32-розрядна перемінна lParam, передана у віконну процедуру, складається із шести полів:

  1. лічильника повторень (число натискань клавіші),

  2. скан-кода OEM (Original Equipment Manufacturer) (код клавіші, генеруємий апаратурою комп'ютера),

  3. прапора розширеної клавіатури (1, якщо повідомлення клавіатури з'явилося в результаті роботи з додатковими клавішами розширеної клавіатури IBM),

  4. коду контексту (1, якщо натиснута клавіша <Alt>),

  5. прапора попереднього стану клавіші (0, якщо в попередньому стані клавіша була відпущена, і 1, якщо в попередньому стані вона була натиснута),

  6. прапора стану клавіші (0, якщо клавіша натискається, і 1, якщо клавіша відпускається).

Набагато більш важливим параметром апаратних повідомлень клавіатури, у порівнянні з lParam, є параметр wParam. У цьому параметрі міститься віртуальний код клавіші (virtual key code), що ідентифікує натиснуту чи відпущену клавішу.

Для всіх апаратних повідомлень клавіатури параметр wParam містить код віртуальної клавіші, що відповідає натиснутій клавіші. Саме цей параметр використовується додатком для ідентифікації клавіші. Код віртуальної клавіші не залежить від апаратної реалізації клавіатури. Коди віртуальних клавіш мають символьні позначення, визначені в заголовних файлах Windows, і мають префікс VK_.

Ідея програми, що одержує інформацію про натискання будь-якої клавіші дуже приваблива; однак, більшість програм для Windows ігнорують усі, крім декількох повідомлень про натискання і відпускання клавіш.

Повідомлення WM_SYSKEYDOWN і WM_SYSKEYUP адресовані Windows, і додатку не завжди потрібно їх відслідковувати. Якщо додаток обробляє повідомлення WM_KEYDOWN, то повідомлення WM_KEYUP воно звичайно теж ігнорує.

Повідомлення WM_KEYDOWN досить зручне для обробки повідомлень про натискання клавіш керування курсором, функціональних клавіш і спеціальних клавіш (таких як <Insert> чи <Delete>), що не генерують символьні повідомлення.

Символьні повідомлення.

Ідея самостійного перетворення апаратних повідомлень клавіатури в символьні повідомлення, шляхом обліку інформації про положення клавіш зрушення, є досить непродуктивної у силу того, що інформації про положення цих клавіш недостатньо - необхідно знати про особливості реалізації кожної окремої національної клавіатури. За програміста це робить Windows.

Раніше вже зустрічався наступний код:

while(GetMessage(&msg,NULL,0,0))

{

TranslateMessage(&msg);

DispatchMesage(&msg);

}

Це типовий цикл обробки повідомлень, що міститься в WinMain. Функція GetMessage заповнює поля структури msg даними наступного повідомлення з черги. Виклик DispatchMesage викликає відповідну віконну процедуру. Між двома цими функціями знаходиться функція TranslateMessage.

Функція TranslateMessage перетворює апаратні повідомлення клавіатури в символьні повідомлення. Якщо цим повідомленням є WM_KEYDOWN (WM_SYSKEYDOWN) і, якщо натискання клавіші в сполученні з положенням клавіші зрушення генерує символ, тоді TranslateMessage поміщає символьне повідомлення в чергу повідомлень.

Це символьне повідомлення буде наступним, після повідомлення про натискання клавіші, що функція GetMessage витягне з черги.

Існує чотири види символьних повідомлень: несистемні - WM_CHAR, WM_DEADCHAR та системні - WM_SYSCHAR, WM_SYSDEADCHAR.

Повідомлення WM_SYSCHAR і WM_SYSDEADCHAR є наслідком повідомлень WM_SYSKEYDOWN.

У більшості випадків, програми для Windows можуть ігнорувати всі повідомлення за винятком WM_CHAR.

Параметр lParam, переданий у віконну процедуру як частина символьного повідомлення, є таким же, як і параметр lParam апаратного повідомлення клавіатури, із якого сгенеровано символьне повідомлення. Параметр wParam - це код символу ASCII.

Якщо Windows-додатку необхідно обробляти символи клавіатури, то йому доведеться обробляти повідомлення WM_CHAR. Найбільш типовим кодом обробки повідомлення WM_CHAR є наступний код:

case WM_CHAR:

{ char chCharCode = (char) wParam; // ASCII-код символу

switch(chCharCode)

{

case '\b': . . .; // уведений символ Backspace

break;

case '\t': . . .; // уведений символ Tab

break;

case '\r': . . .; // уведений символ Enter

break;

case 'A': . . .; // уведений прописний символ A

break;

case 'a': . . .; // уведений рядковий символ а

break;

...

default: . . .; // введені інші символи

break;

}

}; return 0;

Зауваження. Програми звичайно можуть ігнорувати WM_DEADCHAR і WM_SYSDEADCHAR. На деяких, неамериканських клавіатури, деякі клавіші визначаються додаванням діакритичного знака до букви. Вони називаються німими клавішами (dead keys), оскільки ці клавіші самі по собі не визначають символів.

Розглянемо, з якими наборами символів працює система Windows. В операційній системі MS-DOS використовувався розширений набір символів, визначений фірмою IBM. У цей набір входять букви англійського алфавіту, знаки пунктуації і псевдографіки.

Для забезпечення можливості роботи із символами кирилиці фірма Microsoft розробила розширений набір символів з кирилицею. У термінології Windows такі таблиці кодів називаються наборами символів OEM (Original Equipment Manufacturer).

Сама ж система Windows для представлення символів використовує набір символів ANSI. У цьому наборі визначені не всі коди і відсутні символи псевдографіки.

Якщо програма MS-DOS запускається у вікні Windows, для неї вибирається набір символів OEM. Тому

  • У Windows використовуються як набір символів ANSI, так і набір символів OEM. За замовчуванням, у контекст відображення вибирається системний шрифт, для якого використовується набір символів ANSI.

  • Для однакових символів набори ANSI і OEM використовують різні коди, це приводить до необхідності перекодування символів, наприклад, при переносі текстів, підготовлених у середовищі MS-DOS, у середовище Windows. У складі програмного інтерфейсу Windows маються функції, що беруть на себе роботу з перетворення і перекодування символів.

Щоб розібратися, як Windows посилає повідомлення клавіатури в програму, розробимо програму KEYLOOK. Ця програма виводить у робочу область всю інформацію, що Windows посилає віконній процедурі для восьми різних повідомлень клавіатури. Ця інформація буде виводитися на екран у наступному виді:

Таблиця 2.1 Інформація програми KEYLOOK

Назва стовпчика

Зміст

Параметр

MessageKey

Назва повідомлення.

Віртуальний код клавіші (для апаратних повідомлень) чи ASCII – код (для символьних повідомлень)

wParam

Char

Символ (для символьних повідомлень)

wParam

Repeat

Лічильник повторень

LOWORD (lParam)

Scan

Скан – код ОЕМ

23-16 розряди lParam

Ext

Прапор розширеної клавіатури

24-й розряд lParam

Alt

Код контексту

29-й розряд lParam

Prev

Прапор попереднього стану клавіші

30-й розряд lParam

Tran

Прапор стану клавіші

31-й розряд lParam

Зовнішній вигляд програми буде наступним:

Рисунок 2.3 Зовнішній вигляд програми KEYLOOK

Створення додатка, що демонструє взаємодію програми з клавіатурою:

  1. Створіть новий проект і назвіть його KEYLOOK. Потім додайте до проекту файл типу C++ Source File за назвою keylook.cpp.

  2. Тепер цілком скопіюйте уміст файлу sample.cpp з Лабораторної роботи №1 у keylook.cpp.

  3. Крім заголовного файлу windows.h, не знадобляться ніякі інші файли.

  4. У функцію WinMain внесіть наступні незначні зміни:

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,

PSTR szCmdLine, int iCmdShow)

{ static char szAppName[] = "KeyLook" ;

HWND hWnd ;

RegisterClass (&wndclass) ;

hWnd = CreateWindow (szAppName, "Keyboard Message Looker",

WS_OVERLAPPEDWINDOW,

CW_USEDEFAULT, CW_USEDEFAULT,

  1. Крім повідомлень WM_PAINT і WM_DESTROY функція WndProc буде містити обробку наступних повідомлень: WM_CREATE, WM_SIZE, а також WM_KEYDOWN, WM_KEYUP, WM_CHAR , WM_DEADCHAR, WM_SYSKEYDOWN, WM_SYSKEYUP, WM_SYSCHAR, WM_SYSDEAD-CHAR. Отже, у функцію WndProc додайте такий код:

LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)

{ HDC hdc ;

PAINTSTRUCT ps ;

switch (iMsg)

{ case WM_CREATE :

case WM_SIZE :

case WM_PAINT :

case WM_KEYDOWN : …

case WM_KEYUP : …

case WM_CHAR : …

case WM_DEADCHAR : …

case WM_SYSKEYDOWN : …

case WM_SYSKEYUP : …

case WM_SYSCHAR : …

case WM_SYSDEADCHAR : …

case WM_DESTROY :

PostQuitMessage (0) ;

return 0 ; }

return DefWindowProc (hwnd, iMsg, wParam, lParam) ;

}

  1. Форматування виведеного тексту програми 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) ;

Соседние файлы в папке Lab_progr_Win