资源描述
东南大学MFC实践设计方案报告一
MFC课程设计
——绘制电路图
姓名:
学号:
指导教师:窦建平
院系:东南大学机械工程学院
日期:2013.10.10
绘制电路图
摘要内容:本程序可用来绘制简单电路图,程序中有灯泡、电阻、电源、开关、导线、电压表、电流表等常用电路元件。程序可将完成的电路图保存,以便下次使用。
关键词:绘制、电路图、保存
Draw The Circuit Diagram
Abstract: This procedure can be used to draw a simple circuit diagram, the light bulb, resistance, power supply, switch, wire, voltmeter, ammeter and other commonly used circuit element program. The program can be completed save circuit diagram, so that next time you can use.
Keywords:Drawing, circuit diagram, preservation.
目 录
第一章 绪论 4
1.1 引言 4
1.2 编程思路 4
第二章 程序使用 5
2.1 程序界面 5
2.2 菜单栏与工具栏 6
2.3 保存与打开 6
第三章 程序代码解析 7
3.1 主要函数及说明 7
3.1.1 View类中主要函数及变量 7
3.1.2 Doc类中主要函数及变量 8
3.1.3 元件类主要函数及变量 9
3.2 编程中遇到的问题及解决办法 9
3.2.1 选择按钮后如何实现元件跟随鼠标移动 9
3.2.2 拖动和删除元件 11
第四章 程序运行测试 14
第五章 总结 17
第六章 附录——未完成的电路简化函数 18
第一章 绪论
1.1 引言
从中学时代到大学,电路图一直伴随我们走过了近十年的学习生活。而电路图的繁琐绘制也为我们学习增添了不少麻烦。我们经常遇见这样的情况,在绘制电路时,经常出现一处绘制错误而重新画整幅图的情况。而现在有了电路图绘图软件,我们可以轻松的增加、拖动、删除错误元件,为电路图的绘制提供了效率。大大减少了不必要的工作量,让我们更加轻松的学习、绘制电路图。另外,程序设计原本打算加入电路识别,使电路能够自行判断状态并实现相应的功能。但电路识别模块所需函数逻辑问题较为复杂,且包含短路、断路、并联、串联等多种模块的简化和判断,由于时间因素未能全部完成,本报告中仅将短路的简化和判断函数附在最后,以供参考。
1.2 编程思路
在本程序的编写过程中,采用将各个元件作为一个类的方法来实现。将每一个元件通过自身类来完成定义,然后通过程序的View类创建类的对象并完成Doc中的数据存储。每个元件的元素均采用中心点的方式确定,使程序的数据存储更加简化,节约了存储空间。而在删除某一个元件时,也无需改动元件的类函数,只需通过更改Doc类中存储的元件中心点的坐标,从而使View类在创建函数时所传参数不同即可实现。
元件的绘制也采用较为简单的简化画法,即用简单线条代替繁琐的元件结构,以元件中心点为基准点,在元件类中调用OnDraw函数,通过Ellipse、Rectangle、Lineto等函数进行圆、矩形、直线的简单绘制,使电脑绘制和手绘电路图基本一致,方便打印保存。
第二章 程序使用
状态栏
工具栏
标题栏
绘图区
2.1 程序界面
2.2 菜单栏与工具栏
单击工具栏按钮,如电压表,移动鼠标至绘图区,在所要绘制的地方点击鼠标左键,即可绘制出想要的图形。若想移除元件,先点击工具栏图标为D的按钮,再点击所要删除的元件,即可删除。图形拖动时,鼠标左键按住要拖动的元件,拖动至所需位置放开鼠标左键,即可完成拖动。绘制导线时,点击导线按钮,在导线起点单击,然后移动鼠标便可绘制出导线轨迹,在导线终点单击鼠标以完成导线绘制。(注:导线暂不支持删除和拖动,菜单栏与工具栏操作相同,不再赘述)
2.3 保存与打开
单击工具栏保存按钮,在弹出的如下窗口中输入文件名并保存。打开文件与此相同。
第三章 程序代码解析
3.1 主要函数及说明
3.1.1 View类中主要函数及变量
CEXView::CEXView() // 初始化函数
void CEXView::OnDraw(CDC* pDC) // 创建元件对象并完成视图显示及窗口重绘
void CEXView::OnMouseMove(UINT nFlags, CPoint point) //完成鼠标移动时元件跟随鼠标的显示
void CEXView::OnLButtonDown(UINT nFlags, CPoint point) //在鼠标拖动某一元件时对其进行标记
void CEXView::OnLButtonUp(UINT nFlags, CPoint point) //在鼠标左键抬起时将所绘制图形Doc类相应的元件中心记录为鼠标所在位置,并使Doc中记录元件个数的变量增加相应数量
void CEXView::OnRes()
void CEXView::OnKey()
void CEXView::OnLine()
void CEXView::OnVol()
void CEXView::OnAmm ()
void CEXView::OnLamp ()
void CEXView::OnPower()
void CEXView::OnDelete() //以上函数均为在点击相应工具栏按钮时,将标记其功能的变量置为True,并将其他按钮置为False
bool m_lamp,m_line,m_linec,m_power,m_key,m_res,m_amm,m_vol,m_delete;//记录各按钮是否被激活
3.1.2 Doc类中主要函数及变量
CEXDoc::CEXDoc()// 初始化函数
void CEXDoc::Serialize(CArchive& ar) // 数据的保存和打开
CPoint lampcenter[100];
CPoint powercenter[100];
CPoint keycenter[100];
CPoint rescenter[100];
CPoint volcenter[100];
CPoint ammcenter[100]; //记录各中心点的坐标
CPoint line[100][1000];//记录导线中各点的坐标
int m_lampindex,
m_keyindex,
m_powerindex,
m_volindex,
m_ammindex,
m_resindex,
m_lineindex,//记录各元件的个数
m_lpindex[100];//记录每根导线中点的个数
3.1.3 元件类主要函数及变量
这里仅选取灯泡类为例进行说明:
void CLAMP::OnDraw(CDC* pDC)//绘制灯泡元件
CPoint center;//灯泡中心
3.2 编程中遇到的问题及解决办法
3.2.1 选择按钮后如何实现元件跟随鼠标移动
在网上查得资料得知,在鼠标移动时,程序会调用OnMouseMove函数,于是在类向导中添加OnMouseMove函数如下:
void CEXView::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CClientDC dc(this);
CEXDoc* pDoc = GetDocument();
lastpoint=point;
ASSERT_VALID(pDoc);
if(m_lamp==true)
{
CLAMP lamp;
lamp.GetCenter(point);
lamp.OnDraw(&dc);
}
……
CView::OnMouseMove(nFlags, point);
}
得到如下结果,可以看出,在鼠标拖动过程中,窗口并没有刷新,加入刷新函数 Invalidate();后不能取得相应效果,从网上查到Invalidate() -- RedrawWindow() -- UpdateWindow()三个函数的异同: Invalidate()是强制系统进行重画,但是不一定就马上进行重画。因为Invalidate()只是通知系统,此 时的窗口已经变为无效。强制系统调用WM_PAINT,而这个消息只是Post就是将该消息放入消息队列。当执行到WM_PAINT消息时才会对敞口进行重绘。
UpdateWindow只向窗体发送WM_PAINT消息,在发送之前判断GetUpdateRect(hWnd,NULL,TRUE)看有无可绘制的客户区域,如果没有,则不发送WM_PAINT。
RedrawWindow()则是具有Invalidate()和UpdateWindow()的双特性。声明窗口的状态为无效,并立即更新窗口,立即调用WM_PAINT消息处理。于是改进后函数变为: CClientDC dc(this);
CEXDoc* pDoc = GetDocument();
CRect j(lastpoint.x-40,lastpoint.y+40,lastpoint.x+40,lastpoint.y-40);
lastpoint=point;
ASSERT_VALID(pDoc);
if(m_lamp==true)
{
CLAMP lamp;
lamp.GetCenter(point);
RedrawWindow(&j);
lamp.OnDraw(&dc);
}
加入CRect j;使刷新时不会出现全屏抖动现象。
3.2.2 拖动和删除元件
删除元件和拖动元件都需要进行元件定位,在鼠标摁下时,要保证其他功能按钮没有被激活。因此在void CEXView::OnLButtonDown(UINT nFlags, CPoint point)中加入如下判断if(m_lamp==false&&m_power==false&&m_key==false&&m_vol==false&&m_amm==false&&m_line==false&&m_res==false&&m_delete==false)。
下面举例说明如何进行元件拖动:
int i,j=0;
if(!j)
for(i=0;i<pDoc->m_lampindex;i++)
{
if((point.x>pDoc->lampcenter[i].x-11)&&(point.x<pDoc->lampcenter[i].x+11)&&(point.y>pDoc->lampcenter[i].y-11)&&(point.y<pDoc->lampcenter[i].y+11))//鼠标位置在灯泡中心附近即判定为选定灯泡
{
j=1;
break;
}
}其中,j表示元件类型,如j=1表示灯泡型。
通过以上代码,我们找到了想要确定的元件,下面要做的就是拖动或删除工作。
if(j)
{
switch (j)
{
case 1:
{
for(;i<pDoc->m_lampindex-1;i++)
{
pDoc->lampcenter[i]=pDoc->lampcenter[i+1];//将现有灯泡中心删除,通过后一位向前一位覆盖的方式实现
pDoc->m_lampindex--;//灯泡数量减一
m_lamp=true;激活OnMouseMove函数中灯泡绘制功能
break;
}
}
}
删除函数与此类似,只是将m_lamp=true换成刷新窗口函数即可
。
第四章 程序运行测试
测试拖动
绘制好的电路图
测试保存
测试添加多个相同元件
测试删除
成功打开
测试打开
第五章 总结
在程序编写过程中,对MFC有了更加清晰的认识,更加体会到C++类的封装性。能够随心所欲的在各个类之间完成对象的定义。学会了从网上查找所需要的相应函数,通过类向导增加想要的函数,并根据函数的功能增添代码。如在OnMouseMove函数中体会到了View函数的在整个MFC结构中的作用。通过每次刷新窗口,了解到用Doc类存储数据的重要性。
MFC编程只是一种工具,而编程的核心还是代码的实现。我们在使用MFC编程时要想学得更好就要不断练习,更具体的了解其中的各种类、函数,各种工具,MFC是一个巨大的工具箱,但是如果不知道工具箱里面的工具怎么用,那在好的工具也无用武之地。所以,我认为此次编程小实习主要是让我初步接触了MFC如何实现可视化编程。未来要想真正掌握MFC编程还要不断的深入了解各种MFC工具,真正的与代码结合起来实现高效实用的编程效果。总之,MFC就是通过各种类和对象的应用完成程序的运行。
其次,我要说,在面对自己完全陌生的领域,不要退缩,要发挥自己的聪明才智,攻克它。对于MFC,我在短学期开始之前,是完全陌生的。于是在整个项目设计过程中,我在图书馆借了相关的书籍,一开始,先照着上面的例子,修修改改,编写一下,后来慢慢懂得了其中的原理,也就简单了。虽然过程是艰苦的,但成果是美妙的,当看到它成功的运行起来的时候,那滋味,真是一个字:爽!
通过这次暑期编程实验,不仅充实了暑期生活,也让我学到了一些新的知识,在以后的学习生活要积极参加类似的活动,加强知识学习,能力提高,为未来的职业生涯逐渐打下一个坚实的基础
展开阅读全文