10.1简单绘图
建立一个单文档应用程序,取名为Graphic,此程序将实现点、直线、矩形和椭圆的绘图功能。
首先添加一个子菜单,菜单名为绘图,再添加四个菜单项,来控制不同图形的绘制。然后为四个菜单项添加视类命令消息响应函数。
当用户单击某个菜单项时,应该将用户的选择保存起来,因此添加一个视类的成员变量:m_nDrawType,私有类型,并在视类的构造函数中将其初始化为0。
在四个菜单项命令消息响应函数中将m_nDrawType设置为不同值:
void CGraphicView::OnDot()
{
// TODO: Add your command handler code here
m_nDrawType=1;
}
void CGraphicView::OnLine()
{
// TODO: Add your command handler code here
m_nDrawType=2;
}
void CGraphicView::OnRectangle()
{
// TODO: Add your command handler code here
m_nDrawType=3;
}
void CGraphicView::OnEllipse()
{
// TODO: Add your command handler code here
m_nDrawType=4;
}
在绘图时,可以用两个点来确定图形。当鼠标左键按下的时候,应该将此点保存起来。因此需要为视类添加一个私有类型的CPiont类型的成员变量:m_ptOrigin。并在视类的构造函数中初始化为(0,0)。
添加鼠标左键按下的消息响应函数,并在该消息响应函数中,保存按下点的坐标:
void CGraphicView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
m_ptOrigin=point;
CView::OnLButtonDown(nFlags, point);
}
添加鼠标左键弹起消息响应函数,在鼠标左键松开时实现绘图功能:
void CGraphicView::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CClientDC dc(this);
switch(m_nDrawType)
{
case 1:
dc.SetPixel(point,RGB(255,0,0));
break;
case 2:
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
break;
case 3:
dc.Rectangle(CRect(m_ptOrigin,point));
break;
case 4:
dc.Ellipse(CRect(m_ptOrigin,point));
break;
}
CView::OnLButtonUp(nFlags, point);
}
运行,如图。
线条的颜色是由DC中的画笔决定的,为了绘制其他颜色的线条,需要构造一个画笔对象,指定一种颜色,然后将画笔选入设备描述表中。
在CClientDC dc(this);后面添加:
CPen pen(PS_SOLID,1,RGB(255,0,0));
dc.SelectObject(&pen);
如果不想用白色画刷填充,可以将画刷设置为透明的,在刚刚添加的代码下再添加:
CBrush *pBrush=CBrush::FormHandle((HBRUSH)GetStockObject
(NULL_BRUSH));
dc.SelectObject(pBrush);
FormHandle将画刷句柄转变为画刷对象指针。
运行结果如图。
10.2设置对话框
添加一个对话框,允许用户指定画笔的类型、线宽,然后按照指定的类型进行绘图操作。ID:IDD_DLG_SETTING,Caption:Setting,Font:宋体。
10.2.1设置线宽
给对话框添加一个静态文本框,Caption:线宽。设置一个编辑框,ID:IDC_LINE_WIDTH。如图。
接着为对话框资源添加对话框类:双击对话框资源,单机OK,将新的对话框名称设置为:CSettingDlg。单击OK,就创建好了关联IDD_DLG_SETTING对话框资源的对话框类。
接下来需要为编辑框控件关联一个成员变量:鼠标右键单击编辑框控件->ClassWizard->Member Variables。因为线宽不小于0,所以类型为UINT。如图。
然后在绘图子菜单下添加一个菜单项:设置,将其ID设置为IDM_SETTING,然后添加菜单项命令消息响应函数,用视类对消息进行响应,在该函数中调用DoMOdal函数显示对话框。
void CGraphicView::OnSetting()
{
// TODO: Add your command handler code here
CSettingDlg dlg;
dlg.DoModal();
}
由于会用到CSettingDlg类,需要在视类源文件中添加:
#include “SettingDlg.h”
运行如图。
在编辑框中输入线宽后,应该存起来。为视类添加一个私有成员变量:m_nLineWidth,类型也是UINT,接收对话框类中线宽值。并在构造函数中初始化为0。
void CGraphicView::OnSetting()
{
// TODO: Add your command handler code here
CSettingDlg dlg;
if(IDOK==dlg.DoModal())
{
m_nLineWidth=dlg.m_nLineWidth;
}
}
先执行dlg.DoModal(),然后判断返回是否是OK,是的话存起来线宽。
然后就将创建画笔的代码改为:
CPen pen(PS_SOLID,m_nLineWidth,RGB(255,0,0));
运行,绘图的线条就是用户设置的线宽大小了。
但是再次打开设置对话框,线宽编辑框值又变回0了。
因为dlg是一个局部变量,再次运行,dlg的m_nLineWidth初始化为0。
void CGraphicView::OnSetting()
{
// TODO: Add your command handler code here
CSettingDlg dlg;
dlg.m_nLineWidth=m_nLineWidth;
if(IDOK==dlg.DoModal())
{
m_nLineWidth=dlg.m_nLineWidth;
}
}
因为对话框虽然关闭,但是对话框类对象仍然存在,它所保存的m_nLineWidth值也一直存在。
10.2.2设置线型
添加一个组框:Caption为线型,因为组框需要操作,ID修改为IDC_LINE_STYLE。
在组框内添加三个单选按钮,将第一个按钮Group属性勾选上,这三个按钮就是一组了,同样为这组按钮关联一个成员变量:m_LineSytle,选中第一个按钮默认为0,第二个为1,没选为-1。
接着为视类添加一个int型成员变量:m_nLineStyle,在构造函数中初始化为0。与之前操作一样,然后将用户选择的线型保存下来。
void CGraphicView::OnSetting()
{
// TODO: Add your command handler code here
CSettingDlg dlg;
dlg.m_nLineWidth=m_nLineWidth;
dlg.m_nLineStyle=m_nLineStyle;
if(IDOK==dlg.DoModal())
{
m_nLineWidth=dlg.m_nLineWidth;
m_nLineStyle=dlg.m_nLineStyle;
}
}
选择之前创建画笔代码中PS_SOLID,回到定义处,发现它的值本身就是0,PS_DASH是1,PS_DOT是2。因此可以将上述代码改为:
CPen pen(m_nLineStyle,m_nLineWidth,RGB(255,0,0));
运行如图。