logo资料库

小型绘图系统课程设计.doc

第1页 / 共12页
第2页 / 共12页
第3页 / 共12页
第4页 / 共12页
第5页 / 共12页
第6页 / 共12页
第7页 / 共12页
第8页 / 共12页
资料共12页,剩余部分请下载后查看
1设计目的
2 总体设计 设计图如图6
3详细设计
3.1点、直线、矩形、椭圆,画笔绘制
3.2设置对话框
void CDrawView::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;
}
}3.3颜色
void CDrawView::OnColor()
{
// TODO: Add your command handler code here
CColorDialog dlg;
dlg.m_cc.Flags|=CC_RGBINIT;
dlg.m_cc.rgbResult=m_clr;
if(IDOK==dlg.DoModal())
{
m_clr=dlg.m_cc.rgbResult;
}
}
3.3.6打开与保存
1 设计目的 设计一个单文档类型的 MFC AppWizard (exe)工程,工程取名为:Draw。此 程序将实现简单的绘图功能,包括点、直线、矩形、椭圆、连续线的绘制。并且 能实现绘图的控制,包括线宽、线型和颜色的设置,图形的保存和打开的使用。 2 总体设计 设计图如图 6 简易画图板 文件 打开 保存 绘图 点 直线 矩形 椭圆 画笔 设置 颜色 画刷 线宽 线型 3 详细设计 首 先 , 新 建 一 个 单 文 档 类 型 的 MFC AppWizard (exe) 工 程 , 工 程 取 名 为:Graphic。为此程序添加一个子菜单,菜单名称为“绘图”,并为其添加六个菜 单项,分别用来控制不同图形的绘制。当用户选择其中的一个菜单项后,程序将 按照当前的选择进行相应图形的绘制。添加的六个菜单项的 ID 及名称如表 1 所 示。然后分别为这六个菜单项添加命令响应,本程序让视类(CGraphicView)对这
些菜单命令进行响应,这六个响应函数的名称分别如表 1 所示。 表 1 添加的菜单项 菜单项 ID IDM_DOT IDM_LINE IDM-RECTANGLE IDM_ELLIPSE IDM_PEN IDM_COLOR 菜单项名称 点 直线 矩形 椭圆 画笔 颜色 菜单项命令响应函数 OnDot OnLine OnRectangle OnEllipse OnPen OnColor 在程序运行以后,当用户单击某个菜单项时,应该把用户的选择保存起来, 以 便 随 后 的 绘 图 操 作 使 用 。 因 此 在 CDrawView 类 中 添 加 一 个 私 有 变 量 m_nDrawType;用来保存用户的选择,该变量的定义如下所述: UINT m_nDrawType; private: 接着,在视类的构造函数中将此变量初始化为 0,程序代码如下: CDrawView::CDrawView() { // TODO: add construction code here m_nDrawType=0; } 利用 switch/case 语句,来分别完成相应图形的绘制。当用户选择【绘图】菜 单下的不同子菜单项时,将变量 m_nDrawType 设置为不同的值。程序代码如下: void CDrawView::OnDot() { // TODO: Add your command handler code here m_nDrawType=1; } } } void CDrawView::OnEllipse() { // TODO: Add your command handler code here m_nDrawType=4; void CDrawView::OnLine() { // TODO: Add your command handler code here m_nDrawType=2;
void CDrawView::OnRectangle() { // TODO: Add your command handler code here m_nDrawType=3; } 3.1 点、直线、矩形、椭圆,画笔绘制 对于直线、矩形和椭圆,在绘制时都可有两点来确定其图形。当鼠标左击时 得到一个点,当鼠标左键松开时得到另外一个点。为视类 CDrawView 分别捕获 鼠标左键按下和弹起这两个消息。另外当鼠标左键按下时,需要将鼠标当前按下 点保存,因此我们为 CDrawView 再增加一个 CPoint 类型的私有成员变量: m_ptOrigin,在视类的构造函数中将此变量初始化为 0。在鼠标按下消息响应函 数中,保存该点,代码如下: void CDrawView::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default m_ptOrigin=point; //保存鼠标按下得到点,也是绘制一个点 CView::OnLButtonDown(nFlags, point); } 在鼠标左键弹起消息响应函数中实现绘图,代码如下: void CDrawView::OnLButtonUp(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default //创建并获得设备描述 CClientDC dc(this); CPen pen(m_nLineStyle,m_nLineWidth,m_clr); CPen *oldPen=m_dcMetaFile.SelectObject(&pen); dc.SelectObject(&pen); OnPrepareDC(&dc); dc.DPtoLP(&m_ptOrigin); dc.DPtoLP(&point);
switch(m_nDrawType) { case 1: m_dcMetaFile.SetPixel(point,m_clr);点以及颜色 break; case 2: m_dcMetaFile.MoveTo(m_ptOrigin); m_dcMetaFile.LineTo(point); dc.MoveTo(m_ptOrigin); dc.LineTo(point); break; case 3: m_dcMetaFile.Rectangle(CRect(m_ptOrigin,point)); dc.Rectangle(CRect(m_ptOrigin,point)); break; case 4: m_dcMetaFile.Ellipse(CRect(m_ptOrigin,point)); dc.Ellipse(CRect(m_ptOrigin,point)); break; } CGraph*pGraph=new CGraph(m_clr,point,m_ptOrigin,m_nDrawType,m_nLineStyle,m_nLineWidth); m_ptrArray.Add(pGraph); CScrollView::OnLButtonUp(nFlags,point); } void CDrawView::OnPen() { // TODO: Add your command handler code here m_nDrawType=5; } 在上述程序中,设置一个点,用到的函数是 SetPixel,这也是 CDC 类的一个 成员方法,该函数的生命形式 如下:COLORREF SetPixel (POINT point ,
COLORREF crColor);该函数是在指定的点设置一个像素。其中第一个参数 (point)是指定的点,第二个参数(crColor)是指定的颜色。在程序中设定的颜 色在系统颜色表中可能不存在,但系统会选择一种和这个颜色最接近的颜色。 RGB 是一个宏,它有三个参数,分别代表红、绿、蓝三种颜色的值。这三个参 数 BYTE 类型,取值范围为 0~255。RGB(0,0,0)是黑色,RGB(255,255,255) 是白色,将这三个分量设置成为 0~255 之间的任意值,从而得到各种不同的颜色。 这里的 RGB(255,0,0)是红色。 绘制直线时,首先调用 MoveTo 函数移动到原点,然后调用 LineTo 函数绘制 到终点。 绘 制 矩 形 时 使 用 Rectangle 函 数 , 该 函 数 声 明 形 式 为 :BOOL Rectangle (LPCRECT lpRect); 该函数有一个指向 Crect 对象的参数,后者可以利用两个点来构造。需要注意的 是该函数需要的是指向 Crect 对象的指针,而上述代码中传递的却是 Crect 对象, 但运行编译时也能成功通过,运行时也不会报错,这是为什么呢?我们知道 C 系列的语言都是强类型语言,如果类型不匹配的话,需要进行强制类型转换。但 这里为什么没有进行这样的强制类型转换程序也可以通过呢?实际上,Crect 类 提供了这样一个成员函数:重载 LPCRECT 操作符,其作用是将 Crect 转换为 LPCRECT 类型。因此,当在程序中给 Rectangle 函数的参数赋值时,如果它发 现该参数是一个 Crect 对象,它就会隐式地调用 LPCRECT 操作符,将 Crect 类 型的对象转换为 LPRECT 类型。因此,在给函数传递参数时,如果我们看到的 传递的数值类型和所需要的类型不匹配,但编译和运行都正确的情况时,就要想 想这其中的缘由了。当然,有的情况下可能是这些类型之间本来就可以互相转换, 例如 short 类型和 int 类型。但是参数是对象类的话,就要考虑了,它选择的对象 的构造方法进行的隐式转换,还是有其他重载的操作符。 当用户选择椭圆菜单项时,调用 Ellipes 函数绘制一个椭圆。Windows 系统 为我们提供了一个画图程序,在该程序中,利用画笔可以绘制连续的线条,下面 我们设计绘制连续线和扇形。 为了绘制连续的线条,首先要得到线条的起点,这在前面已经实现。然后需 要 捕 获 鼠 标 移 动 过 程 中 的 每 一 个 点 , 这 可 以 通 过 捕 获 鼠 标 移 动 消 息 (WM_MOUSEMOVE)来实现。在此消息响应函数中,在依次捕获的各个点之 间绘制一条条非常短的线段,从而就可以绘制出一条连续的线条。 遵照这一思路,我们开始增加程序的功能。首先为视类增加鼠标移动消息 (WM_MOUSEMOVE)的响应函数(OnMouseMove)。这样,只要鼠标在应用 程序窗口中移动时都会进入到这个消息响应函数中。但这并不是我们所期望的,
我们希望在鼠标左键按下后开始绘图。因此,我们需要有一个变量来表示鼠标左 键是否按下这一状态,然后在鼠标移动消息响应函数中对这一变量进行判断。当 此变量为真,即鼠标左键已经按下去,我们开始绘图。于是,为视类添加一个 BOOL 型的私有变量 m_bDraw,当鼠标左键按下去时,此变量为真;当鼠标左 键弹起时,此变量为假,这时,我们就不再绘制线条了。该变量在视类头文件中 的定义代码如下: Private: BOOL m_bDraw; 接下来在视类的构造函数中,将此变量初始化为 FALSE。 m_bDraw=FALSE; 当鼠标左键按下去时,在视类的 OnLButtonDown 函数中将此变量初始化为 TRUE。 m_bDraw=TRUE; 当鼠标左键弹起时,在视类的 OnLButton 函数中将此变量初始化为假。 m_bDraw=FALSE; 然后在 OnMouseMove 函数中首先对 m_bdraw 变量进行判断,如果其值为真, 说明鼠标左键已经按下去了,这时就可开始进行画线操作。还有一点需要注意, 因为每绘制一条线段后,下次应该从这条线段的终点开始继续绘制。因此,绘制 完当前线段后,应该修改线段的起点,将当前线段的终点作为下一条线段的起点, 程序代码如下: void CDrawcView::OnMouseMove(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default //创建并获得设备描述 CClientDC dc(this); //创建宽度为 1 的实线红色画笔 CPen pen (PS_SOLID, 1, RGB(255,0,0)); //把创建的画笔选入设备描述 CPen *pOldpen=dc.SelectObject(&pen); if(m_bDraw==true) { dc.MoveTo(m_ptOrigin); dc.LineTo(point);
//修改线段的起点 m_ptOrigin=point; } //恢复设备描述 dc.SelectObject(pOldpen); CView::OnMouseMove(nFlags, point); } 如果在上面绘制连续线条的程序中,保持每段小直线的起点不变,即以鼠标 左键按下时的起点为起点不变,分别绘制到鼠标移动点的直线,这时就会出现扇 形的效果。也就是去掉上述代码 OnMouseMove 函数中修改线段起点的代码。程 序代码如下: void CDrawView::OnMouseMove(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default { //创建并获得设备描述 CClientDC dc(this); //创建宽度为 1 的实线红色画笔 CPen pen (PS_SOLID, 1, RGB(255,0,0)); //把创建的画笔选入设备描述 CPen *pOldpen=dc.SelectObject(&pen); if(m_bDraw==true) { dc.MoveTo(m_ptOrigin); dc.LineTo(point); } //恢复设备描述 dc.SelectObject(pOldpen); CView::OnMouseMove(nFlags, point); } 3.2 设置对话框 为程序添加一个设置对话框,允许用户指定画笔的类型、线宽,并让随后的 绘图操作就使用用户指定的新设置值来进行绘制。
为了实现这一功能,首先需要为程序添加一个对话框资源,并按下表修改属 性。 属性 ID Caption Font 值 ID_SETTING Setting 宋体 设置线型、线宽对话框的代码如下: void CDrawView::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; } }3.3 颜色 颜 色 对 话 框 看 起 来 比 较 复 杂 。 实 际 上 ,MFC 为 我 们 提 供 了 一 个 类 : CColorDialog,可以很方便的创建这样的一个颜色对话框。 void CDrawView::OnColor() { // TODO: Add your command handler code here CColorDialog dlg; dlg.m_cc.Flags|=CC_RGBINIT; dlg.m_cc.rgbResult=m_clr; if(IDOK==dlg.DoModal()) {
分享到:
收藏