При создании программ в диалоговом приложении испльзуются инструменты (рис. 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. Результат работы программы