C++简单画图程序课设.docx
《C++简单画图程序课设.docx》由会员分享,可在线阅读,更多相关《C++简单画图程序课设.docx(33页珍藏版)》请在冰豆网上搜索。
C++简单画图程序课设
简单画图程序
1.基本功能描述
1)设计一个程序可完成绘制直线,矩形和椭圆的功能。
要求:
线条样式(实线、虚线、点线等)和宽度可以改变。
图形的线条颜色和内部填充颜色可以用颜色对话框进行改变。
各个选择对象都具有默认值。
2)通过菜单栏和工具栏的使用,使得程序的操作表的人性化,当鼠标移动到菜单栏上面时,可以动态显示按钮作用,菜单栏和工具栏有相应的快捷方式来操作,并且有相关提示,和系统给定的菜单栏工具栏相似。
3)对于一般的绘图程序,最好能够有橡皮擦和清屏的功能,在这个程序中可以给与添加,即能够对图形用橡皮擦进行修改,也可全部删除以前的图形,要和平时的使用习惯相符合。
4)这个程序的画图是使用鼠标操作,鼠标的左键按下同时拖动进行绘图,并且要求能及时显示出来,如在电脑桌面上按下鼠标右键拖动时的情形,橡皮筋技术就要得以使用,这个技术第一次接触,要好好掌握。
5)用户会从实用性出发,要求界面干净,简洁,实用,能一目了然。
不能太繁琐,太花哨。
用户能通过界面快速了解软件的功能,对于快捷键等隐含的内容可以给与提示,人机交互性强。
2.设计思路
1)首先,对所要用到的各个变量进行初始化,即对线宽、线的样式、线的颜色、填充颜色,图形选择进行初始化。
2)新建菜单资源和工具栏资源,对它们进行编辑,尽量可表示出它们的功能,利用类向导建立响应函数。
3)然后,通过初始化的对象对画笔颜色、样式和宽度进行设置并返回,再对画图的图形进行编号,通过form的赋值进行选择,从而确定具体的画图图形函数。
4)由c的设置创建画笔、画刷,根据颜色对话框对颜色进行选择,颜色对话框是
系统给定的。
5)当鼠标左键按下、鼠标左键按下移动和鼠标左键标弹起各个状态来得到鼠标的坐标,将坐标返回到绘图函数中,根据form的值用switch()函数进行选择,然后进行绘图显示。
程序的操作流程图如图1所示。
开始
定义初始化变量:
线色lcolor线的样式nPenStyle,填充色fcolor,画笔Pen,画刷Brush
线的宽度width
用width改变画笔宽度
默认值(width=1)
width=1
否(默认为实线)
是
选择线的类型(实线、虚线、点线、点划线、双点划线等)默认为实线
选择颜色
默认值(黑色)
改变画笔颜色(使用颜色对话框)
选择颜色填充
默认值(黑色)
改变画刷颜色(使用颜色对话框)
橡皮擦
清屏
直线
矩形
椭圆
form=3
form=2
form=1
form=0
form=4
鼠标左键按下响应函数OnLButtonDown()
初始坐标startpoint=point
鼠标移动响应函数OnMouseMove()endpoint=point
响应OnPaint(),绘制图形
使用橡皮筋技术使得绘制的图形有预显示*重难点*
鼠标左键弹起响应函数OnLButtonUp()
刷新,得到图形
结束
图1程序操作流程图
3.软件设计
3.1设计步骤
1)创建新工程
打开VC++软件,按文件->新建->工程操作,选择MFCAppWizard(.exe)工程后缀。
在工程名一栏中填入lisansi工程名,存储位置自选。
点击确定按钮即可。
创建新工程如图2所示。
图2创建新工程
2)创建一个新的单文档
该程序是建立在单文档基础上,因此要先建立单文档,在如图3所示的对话框中选择单文档,其它均为默认设置,点击确认即可建立单文档程序。
注意,保存时,要点击确定按钮。
如图3所示。
图3创建单文档应用程序
3)建立新的菜单栏
选择ResourseView,单击Menu栏,双击IDR_MAINFRAME,则在工作区显示系统给
定的的菜单项。
编辑这菜单并给与各自的ID号和标明项。
对于有弹出功能的菜单项,在属性中选择弹出多选框即可。
在属性中,在提示框内输
入操作提示,例如“直线\n直线”前一个“直线”是在提示栏中显示的,后一个“直线”是当鼠标移动到该按钮上时,给与功能提示作用。
设置菜单栏项目的属性对话框如图4所示.
对于快捷键的提示符,例如“直线(&L)\tCtrl+L”,其中&L使得L下有下划线,\t
表示空格功能,Ctrl+L是提示符,按照这个操作,使得新建的菜单项和系统自定义的菜单项在格式上相同。
图4设置菜单栏项目的属性对话框
按照建立直线菜单项的方法,建立其它菜单项,要尽量与系统给定的菜单项样式一致。
立好菜单栏后得到菜单栏样式如图5所示。
图5菜单栏样式
4)建立类向导
由于类时间在View中,因此类名Classname应选择CLisansiView,这一点要特别注
意,系统默认的是CMainFrame,必须要调整。
然后选择要添加的对象的ID号,添加对应的命令函数。
添加完成后不要像对属性设置那样直接关闭,应该点击确定按钮,否则设置会没有保存,这是刚接触MFC时容易犯的错误。
COMMAND是添加添加命令的,而UPDATE_COMMAND_UI是用来标识选择的,可以提高人机交互性。
要添加类向导的函数有:
ID_CLEAR//加清屏函数
ID_ERASER//加橡皮擦函数
ID_LINE//加画直线函数
ID_ELLIPSE//加画椭圆函数
ID_RECTANGLE//加画矩形函数
ID_FILLCOLOR//加填色函数
ID_LINECOLOR//加线条颜色函数
ID_LS1//线条样式1
ID_LS2//线条样式2
ID_LS3//线条样式3
ID_LS4//线条样式4
ID_LS5//线条样式5
ID_LS6//线条样式6
ID_LS7//线条样式7
ID_W1//线宽1
ID_W2//线宽2
ID_W3//线宽3
ID_W4//线宽4
ID_W5//线宽5
对他们添加COMMAND或UPDATE_COMMAND_UI函数。
添加类向导的对话框如图6所示。
特别注意不要模仿属性设置的确定,直接退出。
而是应该点击确定按钮来确定指令。
图6通过类向导添加函数
5)创建新的工具栏
有了菜单栏的基础,工具栏的创建比较简单。
工具栏图标要求最好能够清楚显示对应响应函数的作用,图标要求清楚明了。
既可以
用汉字书写,也可以用图标来显示。
提示符的动态显示与菜单栏的基本相同,修改属性来的提示即可。
由于工具栏是菜单栏部分功能的快捷操作,可设置ID号与菜单栏对应的键的ID号一
致即可。
工具栏按钮的属性的提示栏中的设置与菜单栏的设置类似。
添加工具栏操作界面如图7所示,工具栏属性对话框如图8所示。
图7添加工具栏操作
图8工具栏属性对话框
工具栏的多余项不是用Del键删除,而是直接拖出工具栏即可删除,这一点初学者特
别容易忽视。
6)在ClisansiView.cpp文件中加入程序代码,有的代码是重复的,可以通用。
3.2界面设计
构成界面的控件、属性和对应的变量如表1所示。
表1构成界面的控件、属性和对应的变量
控件名称
属性
对应的变量
直线
ID_LINE
intform=1
矩形
ID_RECTANGLE
intform=2
椭圆
ID_ELLIPSE
intform=3
橡皮擦
ID_ERASER
intform=0
清屏
ID_CLEAR
intform=4
线宽
ID_W1~ID_W6
intwidth
线色
ID_LINECOLOR
COLORREFlColor;
填充色
ID_FILLCOLOR
COLORREFfColor
线的样式
ID_LS1~ID_LS7
intnPenStyle
3.3关键功能的实现
1)选择宽度
宽度使用变量来实现的,将所要的宽度赋给w,保存在画图时,Onpaint()函数中的设置画笔属性语句pen.CreatePen(PS_SOLID,width,lColor),这个函数中的width就是线条的宽度,若没有该语句,则默认宽度为1,再加以利用。
2)选择线条的颜色,和填充的颜色
创建系统给定的颜色对话框,点击确定时,获取对话框命令,将值返回到lColor和fColor中等待调用,Onpaint()函数中的设置画笔属性语句pen.CreatePen(PS_SOLID,width,lColor),lColor就是设置颜色,如果没有设置lColor的值,则颜色默认为黑色。
同理,画刷的颜色设置也是如此。
3)选择图形
当点击菜单栏或工具栏中对应的图形命令时,调用对应的函数,函数中给每个图形以对应的编号,返回到form中,在画图函数中去调用。
4)画图函数
每一个图形都有对应的form值,调用线条颜色,填充颜色等,设置图形属性,画图时根据switch()函数的form值,调用对应的系统给定的画图函数,即可完成对图形的绘制。
5)橡皮筋技术
橡皮筋技术是指以基本定位方法确定起始点后,当前点的位置随当前的鼠标的位置动态、连续地移动,并实时在起始点和当前点之间形成动态线的技术。
不仅如此,此技术汉可以控制动态线的样式等。
以画矩形为例,绘制需要记录鼠标左击和移动以及释放的消息,绘制方法其实就是响应各种状态消息,将画直线类实例化的过程。
用startpoint和endpoint记录起始点和终止点坐标。
利用ClassWizard在ClisansiView类生成WM_LBUTTONDOWN、WM_MOUSEMOVE、WM_LBUTTONUP相对应的消息函数OnLButtonDown、OnMouseMove和OnLButtonUp。
然后添加相对应的代码即可。
4.结论与心得体会
这次的课程设计完成的比较顺利,与谢颂华老师的帮助密不可分。
由于刚上完《面向对象程序设计》这门课程,课程设计的主要内容已经被充分掌握,
只要静下心来,慢慢琢磨,对于不清楚的可以问老师或者上网查资料,问题可以得到很好地解决。
在课设第一天,谢老师的讲解十分重要,对课设的各种要求以及报告的具体要求作了
说明,详细说出了程序设计过程中的重难点,这对后续的工作十分有帮助。
设计最重要的是构思,也就是程序流程图的设计,这直接关系到程序的的好坏难易,
也决定了后续的工作。
以此,我在程序的构思上花费了大量的时间,并上网查阅了很多资料,最终才确定方案。
时间虽然用了很多,但最终证明这是有必要的。
在程序的具体设计中,充分利用已经学到的知识和网络资源,遇到问题尽量先自己思考,若还是得不到解决,可以和同学或老师讨论。
只要自己有耐性,总会的待解决。
刚开始时,我对加的代码总是找不到位置,后来帮同组的同学处理一些简单问题时,
自己也在其中学到了不少东西,后来在处理自己的问题时,发现只是自己没有发现问题的的所在,而同组的同学用其他的方法可以解决。
我们相互帮助,解决了不少问题。
总之,对问题的出现并不可怕,最让人难以解决的问题是没有错误提示,却达不到实
验要求。
在程序能够达到课设要求后,我对程序进行了一些完善,加入了一些其他功能,使得
画图更加方便、使用。
对于其他的小地方的完善使的,页面更加人性化,更易被读懂。
最后是课程报告的书写工作,以前的课设,实验报告是最难的一部分,每次都由于各
种原因被重新书写。
我这次严格按照报告格式书写,争取一次通过检查。
这次课设使我明白“看花容易,绣花难”,平时在课堂上听老师的讲解,觉得十分简
单,可一到自己动手写程序才知道其中要注意的问题,那些平时根本不当回事的操作,自己做时也会出错,看来平时的训练十分重要,在这方面要多下功夫。
再次衷心感谢谢颂华老师的帮助和指导。
5.参考文献
[1]揣锦华.面向对象程序设计与VC++实践[M].西安电子科技大学出版社,2004.
[2]蔺华,唐菁,王宇灵.面向对象设计与框架[M].电子工业出版社,2011.
[3]宋金珂.VC++程序设计基础教程[M].清华大学出版社,2010.
[4]侯俊杰.深入浅出MFC[M].华中科技大学出版社,2000.
[5]任哲.MFCWindows应用程序[M].清华大学出版社,2007.
6.思考题
1)说明直线、椭圆、矩形绘制使用的函数,及其参数含义?
答:
直线、椭圆、矩形绘制使用的函数是voidCLisansiView:
:
OnPaint(),先设置了画图环境,获取设备指针CPaintDCdc(this),然后设置鼠标的图标格式IDC_CROSS
再建立矩形对象rc,以获得窗口的大小返回后,在清屏时使用。
其中xx,yy是窗口的右下端的坐标。
然后,创建画笔pen、画刷brush,由shape的值来确定下一步执行的操作。
(1)shape=0时,执行橡皮擦作用;
(2)shape=1时,执行画直线的功能;(3)shape=2执行画矩形操作;(3)shape=3时,执行画椭圆操作;(4)shape=4时,执行清屏操作。
其中操作(0)和(4)的本质是相同的,都是画矩形,只是矩形的大小有变化。
2)如何控制菜单项的状态,使用的消息类型?
答:
菜单项的状态是调用CLisansiView:
:
OnUpdateLine(CCmdUI*pCmdUI)函数实现的,该函数可以通过类向导直接添加。
函数代码为pCmdUI->SetCheck(shape==1);即当shape为1时,直线选项前打上勾,SetCheck可换为SetRadio在选项前打原点。
其他的项OnUpdateRectangle,OnUpdateEllipse以及线宽OnUpdateW1等都是使用这种方法控制状态的。
3)如何设置菜单和工具栏按钮的快捷键操作?
答:
加速键通常用来激活某个菜单命令或工具栏命令。
1.将项目工作区切换到资源视图,选择Accelerator资源类型,双击IDR_MAINFRAME加速键资源,打开加速键编辑窗口。
2.编辑加速键资源。
要删除加速键,可以直接按Del键;要增加加速键,可以按Ins键,将弹出加速键属性对话框。
在ID下拉列表框中选择菜单命令或工具栏命令的ID号,如直线ID_LINE,在Key一栏中输入L,选择Ctrl复选框和VirtKey单选按钮,已完成加速键设置,如图所示。
同理,可以定义其他菜单命令或工具栏命令的加速键。
3.关闭加速键编辑窗口。
最后编译运行程序,测试加速键,发现能够完成于和菜单命令或工具栏命令相同的操作。
7.附录
7.1调试报告
1)在画好工具栏后,对工具栏添加显示代码,最开始添加的代码只是让它显示出来,后来为了更加完善,有加入了可以使它浮动显示的代码,但原来的代码并没有删除,调试时发现出现对话框提示程序出现错误,无法运行。
但没有错误提示,经检查以及反复查看系统自定义工具栏,只有浮动显示,最终发现时,应该删除原来的显示代码,删除后,调试、运行一切正常。
2)刚开始时没有设置默认颜色和默认线宽,结果程序运行很不稳定,每次都在变化,有时画不出来,加入默认后,调试、运行正常。
3)OnLButtonDown、OnMouseMove和OnLButtonUp函数添加,刚开始不知道在哪添加,只是在(.cpp)内加入自己定义的函数,运行时,程序出错,提示OnMouseMove等函数没有定义,最后发现是在ClisansiView中加入函数,这些函数是系统自己添加的,不需要自己定义。
7.2测试结果
在程序编写完成,运行程序,得到如图9,图10、图11和图12所示结果。
图9颜色选择对话框
图10程序运行后的结果
图11对程序进行操作的结果
图12对程序进行操作的结果
7.3关键源代码
1)变量初始化
在lisansiView.h中的classCLisansiView:
publicCView的public类中加入如下初始变量。
intform;//图形选择控制变量
COLORREFlColor;//线条颜色返回值
COLORREFfColor;//填充颜色返回值
CPointstartpoint;//鼠标起始点坐标
CPointendpoint;//鼠标终止点坐标
BOOLm_Down;//鼠标左键按下布尔变量
intwidth;//线条宽度
intnPenStyle;//线条的样式
2)对工具栏变量进行初始化
在MainFrame.h中的classCMainFrame:
publicCFrameWnd中的protected:
添加
CToolBarm_set;//建立工具栏1的对象
CToolBarm_width;//建立宽度控制工具栏的对象
if(!
m_set.CreateEx(this,TBSTYLE_FLAT,WS_CHILD|WS_VISIBLE|CBRS_TOP
|CBRS_GRIPPER|CBRS_TOOLTIPS|CBRS_FLYBY|CBRS_SIZE_DYNAMIC)||
!
m_set.LoadToolBar(IDR_SET))
{TRACE0("Failedtocreatestatusbar\n");
return-1;//failtocreate
}//使工具栏1显示
if(!
m_width.CreateEx(this,TBSTYLE_FLAT,WS_CHILD|WS_VISIBLE|CBRS_TOP
|CBRS_GRIPPER|CBRS_TOOLTIPS|CBRS_FLYBY|CBRS_SIZE_DYNAMIC)||
!
m_width.LoadToolBar(IDR_WIDTH))
{TRACE0("Failedtocreatestatusbar\n");
return-1;//failtocreate
}//使控制宽度的工具栏显示
//TODO:
Deletethesethreelinesifyoudon'twantthetoolbarto
//bedockable
m_set.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_set,AFX_IDW_DOCKBAR_LEFT);
//使工具栏1纵向且可在任意位置停靠显示
m_width.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_width,AFX_IDW_DOCKBAR_BOTTOM);
//使控制宽度工具栏且可在任意位置停靠显示
3)线条宽度选择
线条的宽度由w的值控制,用voidCLisansiView:
:
OnW1()等函数对w进行赋值,再将w值返回到画图函数Onpaint()中的pen.CreatePen(nPenStyle,w,m_mcolor)中。
voidCLisansiView:
:
OnUpdateW1(CCmdUI*pCmdUI)函数用来对选中项做标记。
其他的宽度添加程序相同。
voidCLisansiView:
:
OnW1()
{
//TODO:
Addyourcommandhandlercodehere
width=1;//赋值,令线宽为1
}
voidCLisansiView:
:
OnUpdateW1(CCmdUI*pCmdUI)
{
//TODO:
AddyourcommandupdateUIhandlercodehere
pCmdUI->SetRadio(width==1);//当线宽为1时,此选项前标有圆点
}
voidCLisansiView:
:
OnW2()
{
//TODO:
Addyourcommandhandlercodehere
width=2;//赋值,令线宽为2
}
voidCLisansiView:
:
OnUpdateW2(CCmdUI*pCmdUI)
{
//TODO:
AddyourcommandupdateUIhandlercodehere
pCmdUI->SetRadio(width==2);//当线宽为2时,此选项前标有圆点
}
voidCLisansiView:
:
OnW3()
{
//TODO:
Addyourcommandhandlercodehere
width=3;//赋值,令线宽为3
}
voidCLisansiView:
:
OnUpdateW3(CCmdUI*pCmdUI)
{
//TODO:
AddyourcommandupdateUIhandlercodehere
pCmdUI->SetRadio(width==3);//当线宽为3时,此选项前标有圆点
}
voidCLisansiView:
:
OnW4()
{
//TODO:
Addyourcommandhandlercodehere
width=4;//赋值,令线宽为4
}
voidCLisansiView:
:
OnUpdateW4(CCmdUI*pCmdUI)
{
//TODO:
AddyourcommandupdateUIhandlercodehere
pCmdUI->SetRadio(width==4);//当线宽为4时,此选项前标有圆点
}
voidCLisansiView:
:
OnW5()
{
//TODO:
Addyourcommandhandlercodehere
width=5;//赋值,令线宽为5
}
voidCLisansiView:
:
OnUpdateW5(CCmdUI*pCmdUI)
{
//TODO:
AddyourcommandupdateUIhandlercodehere
pCmdUI->SetRadio(width==5);//当线宽为5时,此选项前标有圆点
}
voidCLisansiView:
:
OnW6()
{
//TODO:
Addyourcommandhandlercodehere
width=6;//赋值,令线宽为6
}
voidCLisansiView:
:
OnUpdateW6(CCmdUI*pCmdUI)
{
//TODO:
AddyourcommandupdateUIhandlercodehere
pCmdUI->SetRadio(width==6);//当线宽为6时,此选项前标有圆点
}
4)线条类型的选择
线条类型有实线、虚线和点划线等,用voidCLisansiView:
:
OnLs1()函数对线条类型
进行选择,注意标号与他们的固有顺序有关。
与线条定义类似,用voidCLisansiView:
:
OnUpdateLs1(CCmdUI*pCmdUI)对选择的线条类型进行标