fc程序开发报告Word文档格式.docx
《fc程序开发报告Word文档格式.docx》由会员分享,可在线阅读,更多相关《fc程序开发报告Word文档格式.docx(17页珍藏版)》请在冰豆网上搜索。
2.模块设计及封装(给出静态关系图)11
3.设计的优、缺点11
4.本人程序风格简绍11
5.运行情况及程序使用方法11
6.实践过程中遇到哪些困难,解决方式,有什么启示14
总结15
1.收获15
2.存在的不足15
3.对自己的要求15
任务一
1.实践目的及任务描述
目的:
充分理解Windows的消息循环机制,了解Windows的API函数族的分类及大致功能,并在此基础上了解基本WindowsAPI方式开发的窗口程序的基本过程。
了解并掌握如下事实:
任何框架开发环境归根结底都是对WindowsAPI函数的封装与调用!
在利用一个框架环境开发Windows程序的过程中,应该明白所使用的框架模块调用了WindowsAPI中的那些功能函数。
任务描述:
用visualC++开发一个Win32窗口程序,并实现如下功能:
●实现菜单功能;
●点击某两个菜单可在主窗口中显示或清除文字(文字内容不做要求);
●点击某个菜单可弹出一个自定义的对话框(对话框中的元素不做要求),单击对话框中的“确定”或“取消”按钮,可结束对话框。
2.对消息循环机制的理解
Windows是一个多进程的图形窗口操作系统,Windows应用程序与DOS应用程序有很大的区别。
DOS应用程序采用顺序执行过程,而Windows是一个基于事件的消息(Message)驱动系统。
Windows应用程序是按照“事件→消息→处理”非顺序的机制运行。
当有某个事件(如单击鼠标、键盘输入和执行菜单命令等)发生时,Windows会根据具体的事件产生对应的消息,并发送到指定应用程序的消息队列;
应用程序从消息队列中取出消息,并根据不同的消息进行不同的处理。
3.学到了哪些知识
●了解了Windows应用程序的运行机制,理解了Windows的消息循环机制;
●了解了基本WindowsAPI方式开发的窗口程序的基本过程;
●了解了Windows的程序框架,如_tWinMain函数是程序入口函数,相当于c/c++中的main函数,在win32环境下为WinMain函数;
掌握了一些常用API函数,例如:
CheckMenuItem,DrawText,InvalidateRect,
GetDlgItemText等。
任务二
1.任务描述
用MFC开发一个计算器程序:
●对话框类型的程序;
●能够实现浮点数值的加减乘除运算;
●界面由一个编辑框和若干按钮组成,编辑框负责表达按钮输入及计算的结果,按钮负责输入数字、加减乘除以及等于等动作的输入;
●程序的核心功能由标准C++方式实现,并通过MFC框架代码调用其功能;
●程序中的变量及函数要规范命名,并加以适当的注释。
2.MFC消息映射的方法
MFC消息映射机制包括一组消息映射宏。
一条消息映射宏把一个Windows消息和其消息处理函数联结起来。
在类的实现源文件中用BEGIN_MESSAGE_MAP()和END_MESSAGE_MAP()宏来定义消息映射。
在类定义的结尾用DECLARE_MESSAGE_MAP()宏来声明使用消息映射。
一个基本消息映射结构如下所示:
BEGIN_MESSAGE_MAP(theclass,baseclass)
//{{AFX_MSG_MAP(theclass)
ON_......//MFC预定义的消息映射宏
ON_MESSAGE(message,memberFxn)
//用户自定义的消息映射宏
......
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
MFC约定:
全局函数以“Afx”为前缀,全局变量以“afx”为前缀。
例如,通过调用:
AfxMessageBox("
SomeMessage"
);
可直接在屏幕上弹出消息对话框。
MFC通过巧妙的宏定义把消息调用的过程封装起来,使用户能够通过ClassWizard方便的使用和处理Windowsde各种消息。
3.MFC的优点
MFC是微软为了实现在windows平台下应用程序的快速开发而开发的针对windows平台的功能强大类库。
MFC封装了Win32下的API而形成各种MFC类以实现其快速的开发。
MFC的优点很多,第一,MFC封装了以前各种底层API,提高了编程效率,简化了编程的过程,是编程人员可以脱离非常底层的编程工作;
第二,使用可以进行面向对象编程的类的编程代替了以前Win32下使用的面向过程的编程的函数的编程,增加了程序的可维护性;
第三,MFC在建立类库的时候对类中函数的命名与之前Win32体系下的函数的命名相似,形参表也相似,使用方式也相似,可以比较快的由Win32体系下转换到MFC体系下的编程;
另外,虽然是对Win32函数的高度封装,但是仍然具有较高的效率,与Win32程序相比效率相差不大。
4.自己的计算器程序设计
对于这次计算器的设计,我觉得主要的难点不是算法的问题,应为加减乘除四则运算对于我们来说确实不在话下。
关键的问题是数据转化,和对于计算器使用处理发面的一些细节设计。
对于界面设计,用MFC的对话框,在对话框中添加按钮和文本框控件,通过添加按钮点击事件将数据添加进去。
这样一来,就面临这数据转化问题,所以我将添加进来的数据用CString存储,在用CStoD函数转化为double类型,再传入Operate类(封装算法)进行计算,并返回double型计算结果,最后将计算结果转换为CString类型输出到对话框文本框中,提供给用户使用。
5.开发过程中遇到了哪些困难,如何解决
在本次的开发过程中,遇到了一些困难,多数是事件处理上的问题:
(1)用户连续几次点击运算符号按钮(如“+”),文本框里已有的数字就会消失。
解决方法是在符号按钮的处理事件里每执行完运算将第二个数据变为空,而在判断是否可以进行运算的函数JudgeOperat里数据为空就不在执行,这样就解决了这个问题。
(2)输入小数点“.”时,可能小数点之前没有数字或者是已经有小数点存在了,此时就不能在添加小数点。
解决方法是在响应小数点事件的控件里加入判断即可。
(3)连续计算的问题,就是可以连着做加减乘除运算,在一次运算完返回的数据上直接进行第二次运算。
解决方法是在处理完后返回值存入第一个数据中,这样再输入第二个数据就行。
6.关键代码介绍
//数据转化函数:
voidCTask2Dlg:
:
CStoD(CStringstr1,CStringstr2)
{
this->
num1=atof(str1);
num2=atof(str2);
}
//判断数据,进行处理
JudgeOperat()
if(this->
Operations!
=0&
&
(Msgnumber1!
="
"
||Msgnumber2!
))
{
if(this->
Operations==1)
{
CStoD(Msgnumber1,Msgnumber2);
num1=Myoperate.Add(num1,num2);
Msgnumber1.Format("
%g"
num1);
}
elseif(this->
Operations==2)
num1=Myoperate.Clear(num1,num2);
Operations==3)
if(Msgnumber1!
)
{
CStoD(Msgnumber1,Msgnumber2);
num1=Myoperate.Mul(num1,num2);
Msgnumber1.Format("
else
Msgnumber1=Msgnumber2;
Operations==4)
if(num1!
=0)
if(Msgnumber1!
{
CStoD(Msgnumber1,Msgnumber2);
num1=Myoperate.Div(num1,num2);
Msgnumber1.Format("
}
else
Msgnumber1=Msgnumber2;
}
Msgnumber1="
除数不能为零!
;
SetDlgItemText(IDC_MSG,Msgnumber1);
}
7.代码运行状况
程序运行稳定,实现了预定的所有功能。
计算结果准确,所有逻辑预算均可实现。
8.收获
●熟悉了一些API函数,如:
GetDlgItemText和一些字符串操作函数;
●熟悉了界面设计的方法,了解了许多控件的使用方法;
了解了如何添加并编写键盘响应函数。
任务三
用MFC开发一个单文档文本查看程序:
(1)不能用MFC的CRichEditView或其它标准控件实现,用Textout等API实现文本绘制功能;
(2)能够打开、保存.txt格式的文本文件;
(3)能够控制文本的大小、颜色、字体等,并实现相应的控制界面(对话框方式),设置好后,当前显示的文本均按相应属性显示。
(4)(高阶内容)实现文本的编辑、查找、替换功能。
2.自己程序的特点及关键代码简绍
1)文本字符串的管理方式
文本查看器最重要的就是对字符串的处理与管理,所以我在这里的提一下自己文本查看器的字符串管理方式。
使用vector<
CString>
类型来存储字符串,每一行是一个CString。
打开txt类型的文本文档时,用getline方法每次读取一行存储到CString中,并push_back到vector中。
用CString类型的m_sTEXT变量来存储光标所在行的字符串。
这样的存储方式使得字符串存取方便,十分有利于管理,但缺点是只能编辑光标所在行,不能实现任意一行的编辑。
并且没有实现文本随窗口的改变而自动换行,这一点还有待自己进一步的研究与实现。
2)改变文本时的窗口重绘
通过贴图方式对窗口进行重绘,编写了一个myDrawTxt()函数将存储的字符串一行行绘到bitmap上,再直接贴图到窗口中。
myDrawTxt()函数在OnDraw函数中调用。
voidCMyNotePadView:
myDrawTxt()
HideCaret();
CClientDCdc(this);
CRectrect;
GetClientRect(&
rect);
CDCmemDC;
CBitmapmemBit;
memDC.CreateCompatibleDC(&
dc);
memBit.CreateCompatibleBitmap(&
dc,rect.Width(),rect.Height());
memDC.SelectObject(&
memBit);
memDC.FillSolidRect(&
rect,RGB(255,255,255));
intindex=0;
TEXTMETRICtext;
m_font);
memDC.SetTextColor(m_color);
memDC.GetTextMetrics(&
text);
AddLine();
m_nLine=this->
m_sTEXT.GetLength();
for(autoit=m_vFILE.begin();
it!
=m_vFILE.end();
it++)
memDC.TextOutA(0,index*text.tmHeight,*it);
index++;
dc.BitBlt(0,0,rect.Width(),rect.Height(),&
memDC,0,0,SRCCOPY);
POINTpt;
pt.x=m_nLine*text.tmAveCharWidth;
pt.y=m_nRow*text.tmHeight;
CreateSolidCaret(text.tmAveCharWidth/8,text.tmHeight);
SetCaretPos(pt);
ShowCaret();
3)编辑时自动换行的处理
响应OnChar函数,当键盘键入回车时,增加一行。
而编辑时超出窗口范围的时候,可以通过判断窗口屏幕宽与当前行字符串宽度自动换行。
关节代码为:
if(rect.Width()<
=dc.GetTextExtent(m_sTEXT+t).cx)
m_nLine=1;
m_nRow+=1;
AddLine();
m_sTEXT=t;
其中rect.Width()是窗口的宽度,dc.GetTextExtent(m_sTEXT+t).cx是当前行字符串的宽度。
4)编辑时退格的处理
在文本编辑时,英文字符与汉语字符大小不同,一个汉字占两个字节,而一个英文字符占一个字节,所以这样在退格时就会出现一些问题。
当删除汉字是,要敲击两次回格键才能删除一个汉字,而且到了行首时在敲击回格键程序就会发生异常,并不能直接推到上一行。
对于这些问题我做了一些处理,关键代码为:
caseVK_BACK:
clr=dc.SetTextColor(dc.GetBkColor());
dc.TextOutA(0,m_nRow*text.tmHeight,m_sTEXT);
if(m_nLine==0&
m_nRow==0)
break;
m_nRow!
--m_nRow;
this->
clearLine();
elseif(m_sTEXT[m_sTEXT.GetLength()-1]<
0||m_sTEXT[m_sTEXT.GetLength()-1]>
127)
m_sTEXT=m_sTEXT.Left(m_sTEXT.GetLength()-2);
m_nLine-=2;
else
m_sTEXT=m_sTEXT.Left(m_sTEXT.GetLength()-1);
m_nLine-=1;
dc.SetTextColor(clr);
break;
3.程序使用及功能介绍
(1)程序运行时的界面
(2)程序读取文件后界面
(3)改变字体及颜色
(4)可以进行文本替换与查找
(5)可以实现文件的新建,保存和另存为
4.实践过程中遇到了那些问题,解决方式,有那些收获
遇到的困难和解决方式:
(1)如何判断输入的是汉字以及汉字的处理,解决方案:
汉字使用两个字节进行存储,两个字节的大小应大于127,当获得输入时,假如其数值的大小大于127则为组成汉字的字节。
(2)在界面重绘时,比如说改变字体,发现大小字体重叠了。
解决方案:
采用贴图式,将改变后的文本重新贴到才窗口上。
这样就不出现重叠问题了。
收获:
通过这次实践,我掌握了许多MFC中API函数,更加了解并掌握了MFC消息息处理机制,并且学会了自己建立消息映射。
任务四
用MFC开发一个用鼠标在屏幕上绘图的单文档程序:
1.通过鼠标左键的点击在视图中绘制不同的图形,可绘制的图形包括折线、多边形,并且折线的线宽、颜色以及线形都是可以改变的,多边形的填充方式也可以定制;
2.(高阶内容)绘制的图形可以以保存为矢量(矢量格式自定义)文件,并且可以在程序中再次打开,矢量数据的线宽、线形、颜色以及填充模式都要保存在矢量数据文件中,重新打开的矢量数据文件应该是可以再次编辑、修改的。
2.模块设计及封装(给出静态关系图)
CPaintObject对各种绘图图形进行封装,在CMyPaintBoardView类和CMyPaintBoardDoc类里生成对象。
3.设计的优、缺点
在有了任务三的基础后,在任务四的设计上就感觉灵巧了许多。
优点:
实现了基本的绘图功能,在文件存储上尝试使用自己自定的文件数据格式,有益于防止文件修改。
缺点:
在功能上比较简陋,只能实现简单的绘图工作,在窗口重绘上采用贴图方式,虽然方便但程序运算量大,不方便大规模绘图。
4.本人程序风格简绍
为了方便各种绘图工具的选择上,我建了一个CPaintObject类。
该类包括绘图图形(如直线、椭圆、多边形等)的基本属性,即将每个图形抽象为一个对象,对象包括图形的类型(直线、矩形....)、线宽、线条颜色、填充颜色、位置点等。
有了每个对象后,我用一个vector存储所有图形对象的指针。
这样的存储方式非常方便存取数据。
用一enum来存储各种图形,这样在绘图时方便了对象的选择。
5.运行情况及程序使用方法
(1)主界面
(2)菜单栏及工具栏
(3)可以设置图形的线宽,线条颜色及填充颜色
(4)绘出的效果图
(5)也可以把图像保存成文件下次再打开修改。
6.实践过程中遇到哪些困难,解决方式,有什么启示
●在绘图时,出现黑屏。
比如我画直线,左击下去拖动,这是窗口工作部分变黑,直到鼠标松开,窗口恢复正常。
几次调试后发现时贴图有问题,绘图将图像放入虚拟DC所以窗口就变黑了。
我在绘图之前先将当前的图贴一次问题就解决了。
●存储数据图形对象时,刚开始存对象的指针。
但发现绘图时只能绘一个图形,在绘就绘不上去。
解决方案是在实现对象的类里重新编辑其构造函数,这样new对象是就能成功的得到对象的地址了。
●如何在移动绘图时显示的图像为所需要的最后的图形,解决方案:
在移动中的画图,是暂时存在于屏幕上的,则在移动中的画图是在屏幕上直接进行的,当移动需要复原原图形时则将内存中位图中保存的图像的相应位置的图像贴在之前绘制的移动图形,然后再在屏幕上绘制新的移动后的图形,以实现移动绘图的效果。
启示:
在设计一个程序之前,一定要理清思路,决定好设计方案,不能盲目敲代码,这样才能事半功倍。
对于程序员来说,调试代码真的很重要,所以遇到困难不能着急,冷静调试肯定会将问题解决的。
总结
1.收获
通过对Windows桌面程序设计这门课的学习,我了解了桌面应用程序的部分特征,了解了Windows程序的部分运行机制,学习了Windows及MFC的编程,并学会了如何编写一些简单的Windows及MFC程序,也提高了自己在编程方面的能力,积累了宝贵的经验。
通过实践我还清楚地认识到在面对一些自己刚开始无从下手的课题时,一定要对自己有信心,做好知识储备工作,要学会通过各种渠道获取自己会用到的知识。
比如说这次的任务三,许多API不知道,通过网络等方式最终还是找到了解决方案。
2.存在的不足
●程序中依然有部分功能未实现,例如计算器中的科学计算器,文字编辑器中的滑动杆,中间文字的修改,画图编辑器中的撤销操作,重做操作没有实现。
这还需要更多的知识储备。
●程序的外观比较简陋,没有进行很好的界面的设计,依然使用的是MFC所提供的原始的Windows程序界面。
●就自己的代码而言,还不够规范,如命名方式。
代码的效率问题没有得到优化。
3.对自己的要求
希望自己继续努力,能进一步了解WindowsAPI程序设计,更熟悉的掌握MFC程序的运行的内部机制,储备更多的知识。
在课余时间和假期能够多多实践,跟好的提高自己的编程水平。