Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекції_ІЗВП_укр.doc
Скачиваний:
0
Добавлен:
01.04.2025
Размер:
6.39 Mб
Скачать

Введення за допомогою миші

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

Таблиця 1 - Повідомлення Windows для миші

Імена повідомлень починаються із префікса WM (Windows Message), що вказує, що це повідомлення Windows.

Використання методів ClassWizard для роботи з мишею Створіть проект SDI-програми з ім'ям mouser. Наділіть її тими ж функціями роботи з клавіатурою, що і попередню програму carets; інакше кажучи, що вводяться користувачем символи повинні зберігатися в об'єкті документа St ringData.

Крім того, додайте методи OnKillFocus () і OnSetFocus () і включіть в них виклики HideCaret () і ShowCaret (), як це було зроблено в попередній програмі (можна скопіювати необхідні фрагменти коду). Перейдемо до відображення даних, що вводяться користувачем.

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

ClassWizard і додати метод для обробки повідомлення Windows WM_LBUTT0ND0WN;

ClassWizard присвоює йому ім'я OnLButtonDown ().

Запустіть ClassWizard (рис. 4.3).

Простежте, щоб у списку Class name був обраний клас виду CMouserView, і знайдіть у списку Messages повідомлення WM_LBUTT0ND0WN. Двічі клацніть на його імені; при цьому створюється і виводиться в списку Member functions метод OnLButtonDown ().

Двічі клацніть на рядку з eFO ім'ям OnLButtonDown (), щоб перейти до коду:

void CMouserView :: OnLButtonDown (UINT nFlags, CPoint point)

{

/ / TODO: додайте код обробки повідомлення

/ / І / або викличте обробник за умовчанням

CView: :0nl_ButtonDown(nFlags, point);

}

Крім методу OnLButtonDown (), можна використовувати й інші методи для роботи з мишею - OnLButtonUp (), що відповідає за обробку відпускання лівої кнопки миші, OnRButtonDownO, відповідний натискання правої кнопки миші, OnLButtonDblClick (), що обробляє подвійне клацання лівою кнопкою, і т. д .

Методи для роботи з мишею перераховані в табл. 2.

Методом OnLButtonDown () передаються два параметри, nFlags і point. Перший містить інформацію про стан різних службових клавіш і може приймати наступні значення:

MK_C0NTR0L Натиснуто клавіша Ctrl

MK_LBUTTON Натиснуто ліва кнопка миші

MK_MBUTTON Натиснуто середня кнопка миші

MK_RBUTTON Натиснуто права кнопка миші

MK_SHIFT Натиснуто клавіша Shift

Параметр point, об'єкт класу CPoint, містить поточні координати покажчика миші.

Отже, кнопка миші натиснута. Першою справою необхідно зберегти поточне положення вказівника. Ми скористаємося змінними х і в і присвоїмо їм значення, отримані зі змінних х і у об'єкту point:

void CMouserView :: OnLButtonDown (UINT nFlags, CPoint point)

{

/ / TODO: додайте код обробки повідомлення

/ / І / або викличте обробник за умовчанням

х = point.х;

у = point.у;

...

}

Змінні для зберігання координат оголошуються в заголовному файлі виду

mouserView.h:

/ / MouserView.h: інтерфейс класу CMouserView

...

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

CMouserViewO;

DECLARE_DYNCREATE (CMouserView)

CPoint CaretPosition;

boolean CaretCreated;

int x, у;

...

Клацання мишею означає, що текст буде виводитися в новому положенні, - для очищення строкового об'єкта ми скористаємося методом Empty () класу CString:

void CMouserView :: OnLButtonDown (UINT nFlags, CPoint point)

{

/ / TODO: додайте код обробки повідомлення

/ / І / або викличте обробник за умовчанням

х = point.х;

у = point.у;

CMouserDoc * pDoc = GetDocument ();

ASSERT__VALID (pDoc);

pDoc-> StringData.Empty ();

}

Залишається лише оголосити поточний стан виду недійсним, щоб

перемалювати його і відобразити курсор в новому місці (відповідний код був доданий в метод OnDraw ()):

void CMouserView :: OnLButtonDown (UINT nFlags, CPoint point)

{

/ / TODO: додайте код обробки повідомлення

/ / І / або викличте обробник за умовчанням

х = point.х;

у = point.у;

CMouserDoc * pDoc = GetDocument ();

ASSERT_VALID (pDoc);

pDoc-> StringData.Empty ();

Invalidate ();

CView :: 0nl_ButtonDown (nFlags, point);

}

Координати покажчика миші збережені. Наступний крок - виведення в місці, обраному користувачем.

Обробка повідомлень

 Давайте тепер зробимо так, що б наша програма, створена на попередній лекції, звертала увагу на наші дії.

Відкриємо проект, створений і збережений на минулому занятті. File-> Open Workspace ... -> ім'я файла.dsw

Створимо, наприклад, щоб при клацанні мишкою вискакував MessageBox (вікно повідомлення).

Для цього в наш клас вставте наступний строчки:

class CMyMainWnd : public CFrameWnd

{

public:

CMyMainWnd()

{

Create(NULL,"My title");

}

afx_msg void OnLButtonDown(UINT, CPoint);

DECLARE_MESSAGE_MAP()

};

Далі після класу напишіть

BEGIN_MESSAGE_MAP (CMyMainWnd, CFrameWnd) ON_WM_LBUTTONDOWN () END_MESSAGE_MAP ()

І, нарешті, в кінці файлу додайте рядки

CMyApp theApp; void CMyMainWnd :: OnLButtonDown (UINT, CPoint)

{

AfxMessageBox ("Ліва кнопка миші");

}

Відкомпілюйте додаток (Ctrl + F5). При натисненні лівої кнопки миші у вікні повинен вискочити MessageBox з написом "Ліва кнопка миші".

Давайте тепер обговоримо код. Для того, щоб наш клас звертав увагу на наші дії, ми повинні зробити наступні дії.

Перше. Ми повинні вставити в кінець нашого класу макрос DECLARE_MESSAGE_MAP (). Це досить зробити один раз. Цей макрос в класі і означає, що цей клас буде реагувати на деякі повідомлення.

Друге. Ми повинні десь після класу додати два макроси BEGIN_MESSAGE_MAP () і END_MESSAGE_MAP (). Це теж досить зробити тільки один раз. Це так звана карта повідомлень. У перший макрос першим параметром ви повинні вставити ім'я вашого класу, другим - ім'я батьківського класу. Перший параметр показує, для якого класу ми пишемо нашу карту повідомлень, а другий - хто повинен обробляти те або інше повідомлення, якщо наш клас не може.

Тепер ми повинні написати код для конкретного повідомлення. Для цього робимо наступний кроки.

Третій крок. У класі пишемо метод для обробки конкретного повідомлення. Для стандартних повідомлень імена методів стандартні. Утворюються вони так: пишемо новий префікс On, після якого пишемо потрібне повідомлення Windows без префікса WM_, причому в ньому великими літерами пишемо тільки перші літери в кожному слові. Наприклад, повідомлення WM_ONLBUTTONDOWN перетвориться на OnLButtonDown. Параметри і повернене значення беремо з підказок. Перед назвою методу не забудемо написати afx_msg. У нашому прикладі це

afx_msg void OnLButtonDown (UINT, CPoint);

Четвертий крок. В карту повідомлень пишемо макрос для нашого повідомлення. У нашому прикладі це рядок ON_WM_LBUTTONDOWN ()

BEGIN_MESSAGE_MAP (CMyMainWnd, CFrameWnd) ON_WM_LBUTTONDOWN () END_MESSAGE_MAP ()

Його ім'я - це ON_ плюс ім'я повідомлення.

П'ятий крок. Пишемо, що ж конкретно робить наш метод. Тут ми для прикладу написали

void CMyMainWnd :: OnLButtonDown (UINT, CPoint)

{

AfxMessageBox ("Ліва кнопка миші");

}

Функції з префіксом Afx визначені в MFC глобально. Вони не належать конкретного класу.

Малювання простих елементів у вікні

Давайте тепер подивимося, як можна в нашому вікні небудь намалювати. У Windows все малювання відбувається на так званому контексті пристрою (Device context по-англійськи). При цьому малювання відбувається однаково і для екрану, і для принтера, і для плоттера і т. п. Ви можете думати, що контекст пристрою - це як би полотно. На ньому ви малюєте, застосовуючи кисті, пір'я, шрифти та інші об'єкти.

Коли вікна треба небудь перемалювати, воно отримує повідомлення WM_PAINT. Для малювання нам треба написати обробник для цієї події. Для цього ми повинні зробити кроки 3-5 з попереднього питання. Нагадаємо їх.

Отже, вносимо оголошення функції в клас:

class CMyMainWnd:

public CFrameWnd

{

...

afx_msg void OnLButtonDown (UINT, CPoint);

afx_msg void OnPaint ();

DECLARE_MESSAGE_MAP ()

};

Потім додаємо макрос в карту повідомлень:

BEGIN_MESSAGE_MAP (CMyMainWnd, CFrameWnd) ... ON_WM_PAINT () END_MESSAGE_MAP ()

І, нарешті, пишемо реалізацію нашої функції:

void CMyMainWnd :: OnPaint ()

{

CPaintDC * pDC = new CPaintDC (this);

pDC-> Rectangle (10,10,500,500);

pDC-> Ellipse (10,130,500,500);

pDC-> MoveTo (500,300);

pDC-> LineTo (800,130);

}

У реалізації ми робимо наступне - заводимо контекст пристрою для малювання в рядку

CPaintDC * pDC = new CPaintDC (this);

Тут контест пристрої ми створюємо динамічно. Слово this означає, що ми його тут же прикріплюємо до нашого вікна (так як зараз ми знаходимося в класі CMyMainWnd). У контексту пристрою багато різних методів. Один з них - це малювання прямокутника, який ми і використовуємо. Його параметри - це координати верхнього лівого і правого нижнього кутів. Є й безліч інших методів - для малювання кола і еліпса

pDC-> Rectangle (10,10,500,500); / / малювання прямокутника

pDC-> Ellipse (10,130,500,500); / / малювання еліпса

pDC-> MoveTo (500,300); / / перенесення початкової точки

pDC-> LineTo (800,130); / / малювання лінії

Запускаємо програму. У лівому кутку повинен з'явиться квадратик, еліпс, лінія.