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

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

Тема роботи: Робота з мишею.

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

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

У драйвері дисплея містяться кілька визначених курсорів миші, що можуть використовуватися в програмах. Найбільш типовим курсором є похила стрілка, що називається IDC_ARROW (вершина курсору - вістря стрілки). Курсор IDC_WAIT у виді піскового годинника звичайно використовується для індикації того, що програма чимось зайнята.

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

wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);

Повідомлення миші, зв'язані з робочою областю вікна.

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

У Windows для миші визначений набір з 21 повідомлення. Однак 11 з цих повідомлень не відносяться до робочої області, і програми для Windows звичайно ігнорують їх.

Якщо миша переміщається по робочій області вікна, віконна процедура одержує повідомлення WM_MOUSEMOVE.

Якщо кнопка миші натискається чи відпускається усередині робочої області вікна, віконна процедура одержує наступні повідомлення:

  • про натискання - WM_LBUTTONDOWN, WM_RBUTTONDOWN, WM_MBUTTONDOWN;

  • про відпускання - WM_LBUTTONUP, WM_RBUTTONUP, WM_MBUTTONUP;

  • про подвійного щиглика - WM_LBUTTONDBLCLK, WM_RBUTTONDBLCLK, WM_MBUTTONDBLCLK.

Для всіх повідомлень, зв'язаних з робочою областю, значення параметра lParam містить положення миші. Молодше слово - це координата Х, а старше - координата Y щодо верхнього лівого кута робочої області вікна.

Координати X і Y можна витягти з параметра lParam за допомогою макросів LOWORD і HIWORD.

Значення параметра wParam показує стан кнопок миші і клавіш <Shift> і <Ctrl>. Можна перевірити параметр wParam за допомогою бітових масок, визначених у заголовних файлах:

MK_LBUTTON - ліва кнопка натиснута.

MK_RBUTTON - права кнопка натиснута.

MK_MBUTTON - середня кнопка натиснута.

MK_SHIFT - клавіша <Shift> натиснута.

MK_CONTROL - клавіша <Ctrl> натиснута.

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

case WM_MOUSEMOVE:

{

// стан кнопок миші

UINT fwKeys = wParam;

// горизонтальна позиція курсору

int xPos = LOWORD(lParam);

// вертикальна позиція курсору

int yPos = HIWORD(lParam);

if(fwKeys & MK_LBUTTON)

{

HDC hDC=GetDC(hWnd);

SetPixel(hDC,xPos,yPos,0l);

ReleaseDC(hWnd,hDC);

}

};

return 0;

При русі миші по робочій області вікна, Windows не виробляє повідомлення WM_MOUSEMOVE для всіх можливих положень миші.

Кількість повідомлень WM_MOUSEMOVE залежить від пристрою миші і швидкості, з яким віконна процедура може обробляти повідомлення про рух миші.

Якщо користувач клацне кнопкою миші в робочій області неактивного вікна, Windows зробить активним вікно, у якому був зроблений щелчок, і потім передасть віконній процедурі повідомлення WM_LBUTTONDOWN.

Якщо додаток одержує повідомлення WM_LBUTTONDOWN, то воно може упевнено вважати, що в даний момент його вікно активне.

Однак, віконна процедура може одержати повідомлення WM_LBUTTONUP, не одержавши спочатку повідомлення WM_LBUTTONDOWN. Це може случитися, якщо кнопка миші натискається в одному вікні, миша переміщається в інше вікно, і кнопка відпускається.

Аналогічно, віконна процедура може одержати повідомлення WM_LBUTTONDOWN без відповідного йому повідомлення WM_LBUTTONUP, якщо кнопка миші відпускається під час перебування миші в іншім вікні.

У цих правилах є виключення:

  • Віконна процедура може захопити мишу (capture the mouse) і продовжувати одержувати повідомлення миші, навіть якщо вона знаходиться поза робочою областю вікна.

  • Якщо системне модальне вікно повідомлень чи системне модальне вікно діалогу знаходиться на екрані, ніяка інша програма не може одержувати повідомлення від миші.

Обробка натискання клавіш <Shift> і <Ctrl> і кнопок миші.

При одержанні повідомлень миші, зв'язаних з робочою областю вікна, через параметр wParam передається значення, що дозволяє визначити, чи були одночасно з цим натиснуті кнопки миші чи клавіші <Shift> і <Ctrl> клавіатури.

Наприклад, якщо обробка повинна залежати від стану клавіш <Shift> і <Ctrl>, той додаток міг би скористатися наступною логікою:

UINT fwKeys = wParam; // стан кнопок миші

if(MK_SHIFT & fwKeys)

{

if(MK_CONTROL & fwKeys)

{ /* натиснуті клавіші <Shift> і <Ctrl> */ }

else

{ /* натиснута клавіша <Shift> */ }

}

else

{

if(MK_CONTROL & fwKeys)

{ /* натиснута клавіша <Ctrl> */ }

else

{ /* клавіші <Shift> і <Ctrl> не натиснуті */ }

}

Функція GetKeyState також може повертати стан кнопок миші чи клавіш <Shift> і <Ctrl>, використовуючи віртуальні коди клавіш VK_LBUTTON, VK_RBUTTON, VK_MBUTTON, VK_SHIFT і VK_CONTROL. При натиснутій кнопці чи клавіші значення функції, що повертається, GetKeyState негативне.

Функція GetKeyState повертає стан кнопки миші і клавіші в зв'язку з оброблюваним у даний момент повідомленням, тобто інформація про стан належним чином синхронізується з повідомленням.

Як приклад, розробимо програму MOUSE, що демонструє кілька простих тестів улучення. Програма поділяє робочу область на 25 прямокутників, одержуючи в такий спосіб масив розміром 5 на 5. Якщо ви клацаєте мишею на одному з прямокутників, то в прямокутнику малюється символ X. При повторному щелчку символ Х знищується. Зовнішній вигляд програми буде наступним:

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

Створення додатка, що демонструє роботу з мишею:

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

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

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

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

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,

PSTR szCmdLine, int iCmdShow)

{ static char szAppName[] = "Mouse";

HWND hWnd ;

RegisterClass (&wndclass) ;

hWnd = CreateWindow (szAppName, "Checker Mouse Hit-Test Demo",

WS_OVERLAPPEDWINDOW,

CW_USEDEFAULT, CW_USEDEFAULT,

  1. Функція WndProc, крім WM_PAINT і WM_DESTROY буде обробляти повідомлення WM_SIZE і WM_LBUTTONDOWN. Саму функцію модифікуйте так:

#include <windows.h>

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

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 ;

RECT rect ;

switch (iMsg)

{

case WM_SIZE :

case WM_LBUTTONDOWN :

case WM_PAINT :

case WM_DESTROY :

  1. У всіх 25 прямокутників буде однакова висота і ширина. Значення ширини і висоти будуть зберігатися в cxBlock і cyBlock, і перераховуватися при зміні розмірів робочої області:

#include <windows.h>

#define DIVISIONS 5

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,

PSTR szCmdLine, int iCmdShow)

{

}

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

{

static int cxBlock, cyBlock ;

HDC hdc ;

PAINTSTRUCT ps ;

switch (iMsg)

{

case WM_SIZE :

cxBlock = LOWORD (lParam) / DIVISIONS ;

cyBlock = HIWORD (lParam) / DIVISIONS ;

return 0 ;

case WM_LBUTTONDOWN :

  1. У логіку обробки повідомлень WM_LBUTTONDOWN для визначення прямокутника, на якому був зроблений щиглик, використовуються координати миші. Цей оброблювач буде встановлювати поточний стан прямокутника в масиві fState, і робити відповідний прямокутник недійсним для вироблення повідомлення WM_PAINT. Якщо ширина чи висота робочої області не поділяється без залишку на п'ять, вузька смуга праворуч чи унизу робочої області не буде зарисована прямокутниками. У відповідь на щелчок миші в цій області, програма MOUSE, викликаючи функцію MessageBeep, повідомить про помилку.

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

{

static BOOL fState[DIVISIONS][DIVISIONS] ;

static int cxBlock, cyBlock ;

HDC hdc ;

PAINTSTRUCT ps ;

RECT rect ;

int x, y ;

switch (iMsg)

{case WM_SIZE :

case WM_LBUTTONDOWN :

x = LOWORD (lParam) / cxBlock ;

y = HIWORD (lParam) / cyBlock ;

if (x < DIVISIONS && y < DIVISIONS)

{ fState [x][y] ^= 1 ;

rect.left = x * cxBlock ;

rect.top = y * cyBlock ;

rect.right = (x + 1) * cxBlock ;

rect.bottom = (y + 1) * cyBlock ;

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