Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Практическая работа № 3.doc
Скачиваний:
4
Добавлен:
04.12.2018
Размер:
206.34 Кб
Скачать
    1. Робота з мишею

1.2.1 Створення курсору у вікні

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

Створіть додаток з одним документом Kursor. Тепер у загловочному файлі створіть об’єкт StringData для збереження тексту. Що буде вводитися:

class CKursorDoc : public CDocument

{

protected: // create from serialization only

CKursorDoc();

DECLARE_DYNCREATE(CKursorDoc)

// Implementation

public:

virtual ~CKursorDoc();

CString StringData;

У конструкторі необхідно ініціалізувати цей об’єкт:

CKursorDoc::CKursorDoc()

{

// TODO: add one-time construction code here

StringData="";

}

Використовуючи ClassWizard зв’яжіть повідомлення Windows WM_CHAR з методом OnChar(). Для збереження символів введемо наступний фрагмент коду:

void CKursorView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)

{

// TODO: Add your message handler code here and/or call default

CKursorDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

pDoc->StringData+=nChar;

Invalidate();

CView::OnChar(nChar, nRepCnt, nFlags);

}

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

1.2.1 Визначення параметрів шрифта

Для визначення висоти і ширини шрифту необхідно використати метод GetTextMetrics() класу CDC.

Курсор буде створений в методі OnDraw(). На сам перед необхідно створити логічну змінну з ім’ям KursorCreated, за якою можна буде визначити чи був курсор створений раніше.

class CKursorView : public CView

{

protected: // create from serialization only

CKursorView();

DECLARE_DYNCREATE(CKursorView)

boolean KursorCreated;

Після того, як в конструкторі змінній буде присвоєно значення false, в методі OnDraw() необхідно перевірити чи був курсор створений раніше.

void CKursorView::OnDraw(CDC* pDC)

{

CKursorDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

if (!KursorCreated)

{

}

// TODO: add draw code for native data here

}

Якщо курсор ще не створений це необхідно зробити. Спочатку оберемо розмір курсору. Необхідну інформацію можна взяти зі структури TEXTMETRIC, але спочатку необхідно визвати метод GetTextMetrics(). Цей метод заповнює структуру типу TEXTMETRIC. В програмі ця структура заповнюється так:

void CKursorView::OnDraw(CDC* pDC)

{

CKursorDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

if (!KursorCreated)

{

TEXTMETRIC textmetric;

pDC->GetTextMetrics(&textmetric);

}

// TODO: add draw code for native data here

}

Все готове для створення курсору. Його висота буде рівна висоті символів (textmetric.tmHeight), а ширина 1/8 середній ширини символу (textmetric.tmAveCharWidth/8). Для Створення курсора використовується метод CreateSolidCaret():

void CKursorView::OnDraw(CDC* pDC)

{

CKursorDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

if (!KursorCreated)

{

TEXTMETRIC textmetric;

pDC->GetTextMetrics(&textmetric);

CreateSolidCaret(textmetric.tmAveCharWidth/8,textmetric.tmHeight);

}

// TODO: add draw code for native data here

}

1.2.3 Встановлення положення курсору

Попередні дії створюють курсор, але щоб працювати з ним необхідно визначити місце положення курсору за допомогою метода SetCaretPos().

Положення курсору буде зберігатися в новому об’єкті класу CPoint з ім’ям KursorPosition.

class CKursorView : public CView

{

protected: // create from serialization only

CKursorView();

DECLARE_DYNCREATE(CKursorView)

boolean KursorCreated;

CPoint KursorPosition;

Тільки-но створений курсор розташовується в точці з координатами (0,0). У методі OnDraw() це робиться так:

void CKursorView::OnDraw(CDC* pDC)

{

CKursorDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

if (!KursorCreated)

{

TEXTMETRIC textmetric;

pDC->GetTextMetrics(&textmetric);

CreateSolidCaret(textmetric.tmAveCharWidth/8,textmetric.tmHeight);

KursorPosition.x=KursorPosition.y=0;

}

// TODO: add draw code for native data here

}

Потім необхідно задати позицію курсору методом SetCaretPos(), відобразити курсор на екрані (ShowCaret()) та встановлюємо значення прапорця KursorCreated у true:

void CKursorView::OnDraw(CDC* pDC)

{

CKursorDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

if (!KursorCreated)

{

TEXTMETRIC textmetric;

pDC->GetTextMetrics(&textmetric);

CreateSolidCaret(textmetric.tmAveCharWidth/8,textmetric.tmHeight);

KursorPosition.x=KursorPosition.y=0;

SetCaretPos(KursorPosition);

ShowCaret();

KursorCreated=true;

}

// TODO: add draw code for native data here

}

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

void CKursorView::OnDraw(CDC* pDC)

{

CKursorDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

if (!KursorCreated)

{

TEXTMETRIC textmetric;

pDC->GetTextMetrics(&textmetric);

CreateSolidCaret(textmetric.tmAveCharWidth/8,textmetric.tmHeight);

KursorPosition.x=KursorPosition.y=0;

SetCaretPos(KursorPosition);

ShowCaret();

KursorCreated=true;

}

pDC->TextOut(0,0,pDoc->StringData);

// TODO: add draw code for native data here

}

Потім необхідно перемістити курсор в кінець рядка, але перед цим необхідно з’ясувати, де він закінчується. Для цього необхідно заповнити об’єкт класу CSize з ім’ям size, а для цього викликається метод GetTextExtent():

void CKursorView::OnDraw(CDC* pDC)

{

CKursorDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

pDC->TextOut(0,0,pDoc->StringData);

CSize size=pDC->GetTextExtent(pDoc->StringData);

}

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

void CKursorView::OnDraw(CDC* pDC)

{

CKursorDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

pDC->TextOut(0,0,pDoc->StringData);

CSize size=pDC->GetTextExtent(pDoc->StringData);

HideCaret();

}

Потім змінній x об’єкту KursorPosition присвоюється координата кінця текстового рядка на екрані:

void CKursorView::OnDraw(CDC* pDC)

{

CKursorDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

pDC->TextOut(0,0,pDoc->StringData);

CSize size=pDC->GetTextExtent(pDoc->StringData);

HideCaret();

KursorPosition=size.cx;

}

Нарешті курсор переміщується в нове положення і знову виводимо його на екран:

void CKursorView::OnDraw(CDC* pDC)

{

CKursorDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

pDC->TextOut(0,0,pDoc->StringData);

CSize size=pDC->GetTextExtent(pDoc->StringData);

HideCaret();

KursorPosition=size.cx;

SetCaretPos(KursorPosition);

ShowCaret();

}

1.2.4 Приховування/відображення курсору при втраті/отримані фокуса

Необхідно передбачити той факт, що коли користувач клацає мишею всередині іншого вікна і передає в нього фокус – необхідно приховати курсор.

При втраті фокусу програма отримує повідомлення WM_KILLFOCUS, а при отриманні – WM_SETFOCUS. Необхідно скористатися ClassWizard і зв’яжіть з повідомленням WM_KILLFOCUS новий обробник. ClassWizard присвоює йому ім’я OnKillFocus();

void CKursorView::OnKillFocus(CWnd* pNewWnd)

{

CView::OnKillFocus(pNewWnd);

// TODO: Add your message handler code here

}

Даний метод оброблює повідомлення про втрату фокусу тому курсор необхідно приховати.

void CKursorView::OnKillFocus(CWnd* pNewWnd)

{

CView::OnKillFocus(pNewWnd);

HideCaret();

// TODO: Add your message handler code here

}

По аналогії необхідно додати метод OnSetFocus() для обробки повідомлення WM_SETFOCUS і включити в нього код для відображення курсора при отриманні фокуса:

void CKursorView::OnSetFocus(CWnd* pOldWnd)

{

CView::OnSetFocus(pOldWnd);

ShowCaret();

// TODO: Add your message handler code here

}

1.2.5 Виведення тексту з заданої точки

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

Створіть додаток з одним документом mouser. Надайте йому ті ж самі функції для роботи з клавіатурою, що і в попередній програмі. Додайте методи приховання/відображення курсору при втраті/отриманні фокусу.

Якщо користувач клацне в деякій точці клієнтської області, він вказує, що текст повинен виводитися у вказаному місці. Для цього необхідно скористатися ClassWizard і додати метод для обробки повідомлення Windows WM_LBUTTONDOWN; майстер привласнить йому імя OnLButtonDown().

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

{

// TODO: Add your message handler code here and/or call default

CView::OnLButtonDown(nFlags, point);

}

Методу OnLButtonDown передаються два параметри nFlags та point. Перший вміщує інформацію про стан різних службових клавіш. Другий параметр – об’єкт класу CPoint, вміщує поточні координати покажчика миші. Отже кнопка миші натиснута. Перш за все необхідно зберегти поточне положення покажчика. Для цього використаємо змінні х і у:

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

{

// TODO: Add your message handler code here and/or call default

x=point.x;

y=point.y;

CView::OnLButtonDown(nFlags, point);

}

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

class CMouserView : public CView

{

protected: // create from serialization only

CMouserView();

DECLARE_DYNCREATE(CMouserView)

boolean KursorCreated;

CPoint KursorPosition;

int x,y;

….

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

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

{

// TODO: Add your message handler code here and/or call default

x=point.x;

y=point.y;

CMouserDoc* pDoc=GetDocument();

ASSERT_VALID(pDoc);

pDoc->StringData.Empty();

CView::OnLButtonDown(nFlags, point);

}

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

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

{

// TODO: Add your message handler code here and/or call default

x=point.x;

y=point.y;

CMouserDoc* pDoc=GetDocument();

ASSERT_VALID(pDoc);

pDoc->StringData.Empty();

Invalidate();

CView::OnLButtonDown(nFlags, point);

}

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

Для виводу тексту використовується метод OnDraw(). Почніть зі створення текстового курсору, як в попередній програмі:

void CMouserView::OnDraw(CDC* pDC)

{

CMouserDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

if (!KursorCreated)

{

TEXTMETRIC textmetric;

pDC->GetTextMetrics(&textmetric);

CreateSolidCaret(textmetric.tmAveCharWidth/8,textmetric.tmHeight);

KursorPosition.x=KursorPosition.y=0;

SetCaretPos(KursorPosition);

ShowCaret();

KursorCreated=true;

}

….

// TODO: add draw code for native data here

}

Потім виводимо вміст рядкового об’єкту. Координати клацання миші були збереженні у змінних х та у, тому початок буде в цій точці. Курсор повинен знаходитися в кінці виведеного рядка. Спочатку визначаємо де закінчується рядок і приховуємо курсор. Потім переводимо курсор в кінець рядка і знову відображаємо його.

void CMouserView::OnDraw(CDC* pDC)

{

CMouserDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

if (!KursorCreated)

{

TEXTMETRIC textmetric;

pDC->GetTextMetrics(&textmetric);

CreateSolidCaret(textmetric.tmAveCharWidth/8,textmetric.tmHeight);

KursorPosition.x=KursorPosition.y=0;

SetCaretPos(KursorPosition);

ShowCaret();

KursorCreated=true;

}

pDC->TextOut(x,y,pDoc->StringData);

CSize size=pDC->GetTextExtent(pDoc->StringData);

HideCaret();

KursorPosition.x=x+size.cx;

KursorPosition.y=y;

SetCaretPos(KursorPosition);

ShowCaret();

// TODO: add draw code for native data here

}

Додаток готовий.