15.13  Создание программ в диалоговом приложении

При создании программ в диалоговом приложении испльзуются инструменты (рис. 15.10).

Рис. 15.10. Инструменты

Создадим программу, с помощью которой можно рисовать путем передвижения мыши при нажатой ее левой кнопке (рис. 15.11).

Рис. 15.11. Диалоговая панель для рисования

Static Text (см. рис. 15.10) – это элемент текста, он вставляется как обычный элемент управления, но не выполняет никаких функций, так как служит для показа текста, который будет задан в Captions. Свойства статического текста можноустановить с помощью панелей (рис. 15.12).

Рис. 15.12. Панели свойств

При нажатии на кнопку Exit (см. рис. 15.11) программа должна завершиться. Чтобы связать код с событием BN_CLICKED кнопки Exit, выполняем следующие действия:

View – ClassWizard:

Выбираем на панели Message Maps (рис. 15.13) следующие опции:

· Class name: CRGZDlg;

· Object ID: IDC_EXIT_BUTTON;

· Messages: BN_CLICKED.

Добавляем функцию OnExitButton и нажимаем кнопку Ок.

Рис. 15.13. Закладка Message Maps функция OnExitButton

Нажимаем кнопку Edit Code  и записываем следующий код в функцию OnExitButton() (рис. 15.13):

void CDrawDlg::OnExitButton()

{          // TODO: Add your control notification handler code here

OnOK();

}

Функция OnOk завершает работу при нажатии Exit (рис. 15.14).

Связываем код с WM_MOUSEMOVE диалоговой панели (рис. 15.14), нажимаем кнопку Edit Code  и записываем следующий код в функцию OnMouseMove():

void CRGZDlg::OnMouseMove(UINT nFlags, CPoint point)

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

if((nFlags & MK_LBUTTON)==MK_LBUTTON)

{         CClientDC dc(this);

dc.SetPixel(point.x, point.y, RGB(0,0,0));

}

CDialog::OnMouseMove(nFlags, point);

}

Рис. 15.14. Закладка Message Maps функция OnMouseMove

Оператор if содержит в себе функции, которые будут выполняться, если условие оператора if верно. Условие таково: если левая кнопка мыши нажата и произошло перемещение, то функции внутри оператора if выполняются.

Функция OnMouseMove выполняется при любом передвижении мыши, ее параметр nFlags показывает, была ли нажата какая-нибудь клавиша клавиатуры и кнопка мыши. Операция & проверяет, прижата ли левая кнопка мыши при ее перемещении. Если прижата, то выполняется код ниже оператора if.

Код в блоке оператора IF CClientDC dc(this); создает объект контекстного устройства. С его помощью вы сможете рисовать. Его можно назвать воображаемым экраном в памяти компьютера. Научно говоря,  dc(this) – экземпляр класса CClientDC с параметром конструктора this. С помощью экземпляра класс вы можете обращаться к функциям этого класса.

Следующий оператор рисует точку в заданном месте (место щелчка мыши), используя параметры point.x и point.y, которые ему передает функция  OnMouseMove, и заданного цвета, с помощью функции RGB().Чтобы установить красный, синий или зеленый, надо установить параметры функции RGB() соответственно 255, 0, 0; 0, 255, 0; 0, 0, 255.

Программу можно запустить, но точки будут рисоваться не совсем слитно друг с другом. Поэтому нам надо модифицировать программу, чтобы соединить их линиями.

Чтобы соединить точки линиями функция OnMouseMove должна знать предыдущие координаты мыши. Для этого нам нужно объявить две переменные m_PrevX и  m_PrevY для хранения координат по x и y. Для этого откроем заголовочный файл RGZDlg.h:

// RGZDlg.h : header file

//

#if !defined(AFX_RGZDLG_H__BB95F967_01BA_42F6_A3AA_3484DF0950E6__INCLUDED_)

#define AFX_RGZDLG_H__BB95F967_01BA_42F6_A3AA_3484DF0950E6__INCLUDED_

#if _MSC_VER > 1000

#pragma once

#endif // _MSC_VER > 1000

/////////////////////////////////////////////////////////////////////////////

// CRGZDlg dialog

class CRGZDlg : public CDialog

{

// Construction

public:

CRGZDlg(CWnd* pParent = NULL);         // standard constructor

int m_PrevX;

int m_PrevY;

// Dialog Data

// {{AFX_DATA(CRGZDlg)

enum { IDD = IDD_RGZ_DIALOG };

     // NOTE: the ClassWizard will add data members here

// }}AFX_DATA

// ClassWizard generated virtual function overrides

// {{AFX_VIRTUAL(CRGZDlg)

protected:

virtual void DoDataExchange(CDataExchange* pDX);         // DDX/DDV support

// }}AFX_VIRTUAL

// Implementation

protected:

HICON m_hIcon;

// Generated message map functions

// {{AFX_MSG(CRGZDlg)

virtual BOOL OnInitDialog();

afx_msg void OnSysCommand(UINT nID, LPARAM lParam);

afx_msg void OnPaint();

afx_msg HCURSOR OnQueryDragIcon();

afx_msg void OnExitButton();

afx_msg void OnMouseMove(UINT nFlags, CPoint point);

// }}AFX_MSG

DECLARE_MESSAGE_MAP()

};

// {{AFX_INSERT_LOCATION}}

// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_RGZDLG_H__BB95F967_01BA_42F6_A3AA_3484DF0950E6__INCLUDED_)

Теперь модифицируем функцию OnMouseMove в файле RGZDlg.cpp:

void CRGZDlg::OnMouseMove(UINT nFlags, CPoint point)

{

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

if((nFlags & MK_LBUTTON)==MK_LBUTTON)

{

CClientDC dc(this);

// dc.SetPixel(point.x, point.y, RGB(123,211,98));

CPen NewPen(PS_SOLID,10,RGB(255,0,0));

dc.SelectObject(&NewPen);

dc.MoveTo(m_PrevX,m_PrevY);

dc.LineTo(point.x,point.y);

m_PrevX=point.x;

m_PrevY=point.y;

}

CDialog::OnMouseMove(nFlags, point);

}

Код вызова функции SetPixel() поставлен в комментарий, так как он нам больше не понадобится. Следующий код CPen NewPen(PS_SOLID,10,RGB(255,0,0)) создает новое перо с именем NewPen класса CPen с заданным размером шрифта 10 и красным цветом. Параметр PS_SOLID говорит, что будет рисоваться сплошная линия.

После этого выполняется функция SelectObject, выбирающая новое перо:

dc.SelectObject(&NewPen);

Рис. 15.15. Закладка Message Maps функция OnLButtonDown

Этой функцией включается в работу перо.

Следующие два оператора:

dc.MoveTo(m_PrevX,m_PrevY);

dc.LineTo(point.x,point.y);

рисуют линию, используя координаты начала (определяет функция MoveTo()) и конца (определяет функция LineTo()).

А операторы:

m_PrevX=point.x;

m_PrevY=point.y;

сохраняют в переменных m_PrevX и m_PrevY, текущие координаты, которые в следующий раз будут использоваться, как предыдущие.

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

Для решения этой проблемы мы должны связать код событием WM_LBUTTONDOWN, которое происходит при нажатии на левую кнопку мыши.

Нажимаем кнопку Edit Code (см. рис. 15.15) и записываем следующий код в функцию OnLBUTTONDOWN():

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

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

m_PrevX=point.x;

m_PrevY=point.y;

CDialog::OnLButtonDown(nFlags, point);

}

Этот код обновляет значения m_PrevX и m_PrevY тем местоположением мыши, где был совершен щелчок по ее левой кнопке. Соответственно при первом и последующих нажатиях кнопки, линия будет начинаться из данной точки нажатия.

Выполнение программы (рис. 15.16).

Рис. 15.16. Результат работы программы