MFC开发软件.docx
- 文档编号:29034940
- 上传时间:2023-07-20
- 格式:DOCX
- 页数:71
- 大小:965.83KB
MFC开发软件.docx
《MFC开发软件.docx》由会员分享,可在线阅读,更多相关《MFC开发软件.docx(71页珍藏版)》请在冰豆网上搜索。
MFC开发软件
是16位编码,因此可以包含世界各地的书写系统的字符和技术符号(如中文也在unicode中),从而克服了ASCII码在表示多语言文本上的不足之处,扩大了ASCII码7位编码方案的好处。
Unicode同等的对待所有的字符,并且在表示各种语言和任何字符时既不需要换码序列也不需要控制代码。
因为C++支持两种字符串,即常规的ANSI编码和Unicode编码,这样对应的就有了两套字符串字符串处理函数,比如:
strlen和wcslen,分别用于处理两种字符串。
微软将这两套字符集及其操作进行了统一,通过条件编译(通过_UNICODE和UNICODE宏)控制实际使用的字符集,这样就有了_T("")这样的字符串(通过键盘输入的数据都是ANSI码数据,VS是编译环境为UNICODE,要用TCHAR.h将ASCII码转为UNICODE码),对应的就有了_tcslen这样的函数。
为了存储这样的通用字符,就有了TCHAR:
当没有定义_UNICODE宏时,TCHAR=char,_tcslen=strlen;当定义了_UNICODE宏时,TCHAR=wchar_t,_tcslen=wcslen。
当我们定义了UNICODE宏,就相当于告诉了编译器:
我准备采用UNICODE版本。
这个时候,TCHAR就会变成了wchar_t。
而未定义UNICODE宏时,TCHAR变成了unsignedchar。
这样就可以很好的切换宽窄字符集
VisualC++6.0恢复界面设置:
点击上面菜单栏的视图view→工作区workspace
或者在工具栏上直接有workspace
在MSDN中查信息,如要查到TEXTMETRIC,需在筛选依据中选择PlatformSDK。
而不是选择visualC++。
visualC++为筛选依据时,可查找MFC中常用到的类。
获取控件与消息映射函数的对应关系可通过ClassWizard中选择好控件的ID,并左键点击Messages栏中的COMMAND即可在MemberFunction栏中显示对应的消息映射函数
MFC体系结构
MFC主要组成部分:
类、宏和全局函数。
类是MFC中最主要的内容。
MFC类是以层次结构方式组织起来的。
MFC中的类分成两部分,除了一些辅助类,大多数的MFC类是直接或间接从根类CObject派生而来。
几乎每一个派生层次都与一具体的Windows实例相对应,如文档类、窗口类和视图类等。
MFC宏主要功能:
消息映射、运行时对象类型服务、诊断服务、异常处理。
MFC约定:
全局函数以“Afx”为前缀,全局变量以“afx”为前缀。
MFC应用程序生成的过程为:
MFC消息管理
MFC应用程序消息处理的方式与SDK应用程序有所不同。
MFC应用程序框架截取了Windows向应用程序发出的消息,再确定将消息发送给哪一个对象,可以根据需要利用函数重载对消息进行处理,但不需要处理的消息将由应用程序框架自动处理。
消息管理包括消息的发送和处理。
对于消息发送,MFC提供了类似于API函数功能的消息发送函数,而MFC消息处理的内部机制则相对复杂一些。
从编程的角度出发,我们只需了解其大致的原理。
1、MFC消息分类
(1)输入消息:
包括鼠标消息、键盘消息和窗口消息。
通常以WM_前缀(但不包括WM_COMMAND)开始的消息,如WM_MOVE、WM_PAINT等。
这类消息首先放到消息队列中,然后由Windows将它们送入应用程序消息队列中,由应用程序来处理消息
(2)控制消息:
对控件操作引起的消息,是控件和子窗口向其父窗口发出的WM_COMMAND通知消息。
这类消息一般不经过应用程序消息队列,而是直接发送到控制对象上去。
例如,当用户修改了编辑控件中的文本后,编辑控件向其父窗口发送WM_COMMAND通知消息。
(3)系统消息:
对程序化的事件或系统时钟中断作出反应。
一些系统消息,如动态数据交换(DDE)要通过系统的消息队列,而有些则不通过系统消息队列直接送入应用程序的消息队列,如创建窗口消息。
(4)自定义消息:
这是程序员自己定义并在应用程序中主动发出的,一般由应用程序的某一部分内部处理
typedefstructtagMSG{
HWNDhWnd;//目标窗口句柄
UINTmessage;//消息标识
WPARAMwParam;//消息参数1(附加信息,16位)
LPARAMlParam;//消息参数2(附加信息,32位)
DWORDtime;//消息发送时间
POINTpt;//消息发送时鼠标的屏幕坐标
}MSG;
wParam和lParam的具体含义与message成员的值有关
第一个成员变量hwnd即代表消息所属的窗口,一个消息一般都是与某个窗口相联系的,如在某个活动窗口中按下键盘,该键盘消息就是发给该窗口的,在VC中,用HWND变量类型来标识窗口。
第二个成员变量message代表消息代号,无论是键盘按下,还是鼠标移动,都是用一个数字来表示的,不同的数值对应不同的消息。
由于数值不便于记忆,在VC中将消息对应的数值定义为WM_xxx宏的形式,xxx对应某种消息的英文拼写的大写,如鼠标移动消息为WM_MOUSEMOVE,键盘按下消息为WM_KEYDOWN,输入一个字符消息为WM_CHAR等等。
我们在程序中一般以WM_xxx宏的形式来使用消息。
提示:
如果想知道WM_xxx消息对应的具体数值,请在程序中选中WM_xxx,单击右键,在弹出菜单中选择gotodefinition即可看到该宏的具体定义。
跟踪,查看某个变量的定义,使用此方法非常有效。
第三个,四个成员变量分别为wParam、lParam,用于对消息进行补充说明,如message成员表示字符消息,但没有说明输入的是哪个字符,这就需要用其他变量对其进行补充说明。
wParam,lParam代表的意义是随消息的不同而异。
最后两个变量分别代表发出消息的时间和鼠标的当前位置
2、消息的发送
发送消息到一个窗口可以采用传送(Send)或寄送(Post)方式,这两种方式之间的主要区别是消息被接收对象收到后是否立即被处理。
Windows提供了三个API函数用于消息的发送。
(1)函数SendMessage()用于向一个或多个窗口传送消息,该函数将调用目标窗口的窗口函数,直到目标窗口处理完收到的消息,该函数才返回
(2)函数PostMessage()用于向一个或多个窗口寄送消息,它把消息放在指定窗口创建的线程的消息队列中,然后不等消息处理完就返回
(3)函数SendDlgItemMessage()函数用于向对话框中指定的控件发送消息,直到目标控件处理完收到的消息,该函数才返回
MFC将这三个函数封装为CWnd窗口类的成员函数,封装了目标窗口句柄,它们将向调用它的窗口对象发送或寄送消息,如pMyView->SendMessage()的调用形式表示向pMyView所指对象发送消息。
与用户输入相关的消息(如鼠标消息和键盘消息)通常是以寄送(Post)的方式发送,以便这些用户输入可以由运行较缓慢的系统进行缓冲处理。
而其它消息通常是以传送(Send)的方式发送。
3、手工处理消息映射
创建自己的消息映射的具体过程:
(1)定义自己的消息ID:
MFC允许用户自定义消息,常量WM_USER(为0x0400)与第一个自定义消息值相对应,用户必须为自己的消息定义相对于WM_USER的偏移值。
利用#define语句定义自己的消息,例如:
#defineWM_USER1WM_USER+0
#defineWM_USER2WM_USER+1
(2)定义消息映射:
在BEGIN_MESSAGE_MAP()之后,END_MESSAGE_MAP()之前加入消息映射语句:
ON_MESSAGE(message,memberFxn)
其中,message是消息名标识,memberFxn是对应的消息处理函数。
(3)在cpp文件中定义消息处理函数,对消息进行响应:
自定义消息处理函数的声明:
必须在函数返回类型前面加上afx_msg标识,如:
afx_msgLRESULTmemberFxn(WPARAMwParam,
LPARAMlParam);
其中,参数wParam、lParam用于传递消息的两个附加信息。
(4)在需要发送消息的地方发送消息:
可用CWnd:
:
SendMessage()函数或CWnd:
:
PostMessage()函数发送消息。
第一章windows应用程序设计的特点
在三种视图中,要删除一个类,要在FileView视图下,先删除头文件(.h),然后删除应用程序(.cpp)
获得帮助:
菜单help|contents进入帮助系统。
或在文本编辑窗口中把光标定位到一个需要查询的关键字处,按F1可进入帮助系统。
传统的DOS程序主要采用顺序的、关联的、过程驱动的程序设计方法,一个程序是一系列预先定义好的操作序列的组合,它具有一定的开头,中间过程和结束。
程序直接控制程序事件和过程的顺序。
这样的设计方法是面向程序的而不是面向用户的,交互性差,它强迫用户按照某种不可更改的模式进行工作。
事件驱动程序设计不是由事件的顺序来控制,而是由事件的发生来控制,这种事件的发生是随机的,不确定的,并没有预定的顺序,这样就允许用户用各种合理的顺序来安排程序的流程。
事件驱动围绕着消息的产生与处理展开,事件驱动是靠消息循环机制实现的。
消息是一种报告有关事件发生的通知。
Windows应用程序的消息来源有四种:
(1)输入消息:
包括键盘和鼠标的输入。
这一类消息首先是放在系统队列中,然后由windows将他们送入应用程序消息队列中,由应用程序处理消息。
(2)控制消息:
用来与windows的控制对象,如列表框,按钮,检查框等进行双向通信。
当用户在列表框中改动当前选择或改变了检查框的状态时发出此类消息。
这类消息一般不经过应用程序消息队列,而是直接发送到控制对象上去。
(3)系统消息:
对程序化的事件或系统时钟中断做出相应。
一些系统消息,如DDE消息(动态数据交换消息)要通过windows的系统消息队列,而有的则不通过系统消息队列而直接送入应用程序的消息队列,如创建窗口消息。
(4)用户消息:
它是程序员自己定义并在应用程序中主动发出的,一把由应用程序的某一部分内部处理。
Windows操作系统包括3各内核基本元件:
GDI,KERNEL,USER。
其中GDI(图形设备接口)负责在屏幕上绘制像素、打印硬拷贝设备输出,绘制用户界面包括窗口,菜单,对话框等。
GDI的图形输出时面向窗口的,绘图仅对于本窗口有效,图形在窗口边界会被自动裁剪,即窗口中的每一个图形都不会越出边界。
系统内核KERNEL支持与操作系统密切相关的功能:
如进程加载,文本切换,文件I|O,以及内存管理,线程管理等。
USER为所有的用户界面对象提供支持,它用于接收和管理所有输入消息、系统消息并把它们发给相应的窗口消息队列。
消息队列是系统定义的内存块、用于临时存储消息;或是直接把消息发送给窗口过程。
每个窗口维护自己的消息队列,并从中取出消息,利用窗口函数进行处理。
Windows编程中的资源共享:
Windows是一个多任务的操作系统,各应用程序共享系统提供的资源。
常见的资源包括:
设备上下文、画笔、画刷、字体、对话框控制、图标、定时器、通信端口等。
应用程序使用资源的基本模式:
(1)向Windows系统申请资源
(2)使用该资源(3)释放资源。
应用程序一般不直接访问内存或硬件设备,可通过windows提供的函数来安全访问
第二章生成应用软件的框架
一、使用程序向导生成窗口
生成应用软件的窗口是利用可视化编程工具AppWizard来完成的。
这是填空式的编程方法。
首先生成要开发的应用程序框架,然后根据软件的要求,做进一步的修改也就是往里填写程序代码完成程序功能。
在MFCAppWizard-step1中,可指定生成框架的类型,包括singledocument(单文档),multipledocuments(多文档),dialogbased(基于对话框)3种。
单文档的应用程序每次只能读写一个文档,如Notepad(记事本);多文档应用程序每次可读写多个文档,可以同时对多个文档进行操作,可以有多个子窗口,如word;基于对话框的应用程序一般是不读写文档的小程序,如windows中的计算器。
在MFCAppWizard-step4中用于指定应用程序的外观,包括是否使用工具条,状态栏,是否让文档支持打印和打印预览功能,是否使用3D控制外观,以及是否支持在线帮助等。
在MFCAppWizard-step5中有两个选项,分别是让用户设置生成源代码的选项和编译选项。
第一个选项是wouldyouliketogeneratesourcefilecomments?
询问MFCAppWizard是否为源代码添加必要的注释说明。
故选yes。
第二个选项是howwouldyouliketousetheMFCLibrary?
询问MFC如何使用MFC库。
用户可以选择asasharedDll(使用共享动态链接库)或asastaticlinkedlibrary(静态链接库)。
使用DLL时,所有MFC的类存放在动态链接库中,可使应用程序小一些,但是发布应用程序可执行文件时必须把这些必要的动态链接库一起提供。
使用静态库时,应用程序所用到MFC类都编译进了可执行文件之中。
因此,可执行文件要比使用DLL的方式要大,但可以单独发行。
在最后一步中,让用户选择MFCAppWizard将要创建的类的属性,包括制定存放类的文件名以及这些类的基类。
如果窗口需要滚动条就应将视图基类有CView类改为CScrollView类。
二、编译链接TypingTest程序
正常情况下应该是先编译后运行。
也可以直接运行(ctrl+F5),系统会弹出如下对话框以提示是否要编译,选yes,将自动编译链接并运行程序。
注意:
由于编译链接过程中会产生大量的中间文件和目标文件,会占用大量硬盘空间。
故在build菜单里提供了Clean用于清除这些中间文件。
用户在完成一个工程后,应及时清理。
三、程序向导所创建的文件
(1)工作区、项目文件
(2)应用程序源文件和头文件
(3)资源文件:
TypingTest.RC,resource.h
(4)预编译头文件:
stdafx.cpp和stdafx.h
这两个文件用于建立一个预编译的头文件Typingtest.pch和一个预定义的类型文件stdafx.obj。
由于MFC体系庞大,包含许多头文件,如果每次都编译的话比较费时。
因此把常用的头文件都放在stdafx.h,如afxwin.h,afxext.h,afxdisp.h,afxcmn.h等,然后让stdafx.cpp包含这个stdafx.h文件。
这样,由于编译器可以识别那些文件已经编译过,所以stdafx.cpp就只编译一次,并生成所谓的预编译头文件(因为它存放的是头文件编译后信息)。
如果以后再编程时不想让有些MFC头文件每次都编译,也可放入stdafx.h中。
采用预编译头文件可以加速编译过程。
四、程序向导所创建的类
1、视图类
视图是框架窗口的子窗口,能多个视图共用一个框架窗口。
视图类、框架窗口类、和文档类之间的联系通过CDocTemplate类来建立。
当用户打开一个窗口或将现有窗口分割为多个时,框架会创建一个新视图并将它连接到文档对象上。
一个视图只能连接到一个文档,但一个文档可以有多个视图与之相连接,如在分割窗口或多文档界面(MDI)应用程序的多重子窗口中显示的文档就是如此。
视图可以响应几种类型的输入,如键盘输入,鼠标输入,或拖放输入,还有菜单、工具条、和滚动条产生的命令输入。
视图接收框架窗口发送给他的命令,如果视图不接受一个给定的命令,它就将这个命令发送给相连接的文档。
当文档的数据发生变化时,视图类响应这种变化,通过调用文档的CDocument:
:
UpdataAllViews函数,通知所有其他的视图调用OnUpdate函数。
通过CWnd:
:
OnHScroll和CWnd:
:
OnVScroll成员函数处理滚动条信息。
2、框架类
CFrameWnd只是MFC窗口类的一种,CFrameWnd能提供SDI,Overlapped,Pop-up风格的窗口。
但是MFC的窗口种类远不止这些,有FrameWindow、DialogBoxes、Views、Controls。
而能作为主窗口的窗口类也不止一种,实际上DialogBoxes作为主窗口的情况更常见。
CFrameWnd的主要作用是创建一个窗体对象,并通过自身的消息映射表(MessageMap),将消息映射到相应的消息处理函数中进行处理。
这里CFrameWnd充当了SDK中回调函数(过程函数)的职责
有3种方法可以构造一个框架窗口。
用creat直接构造,用loadFrame直接构造,用文档模板间接构造。
当一个CFrameWindow对象包含视图和文档时,他们由框架间接构造而不是直接构造。
CDocTemplate对象将框架构造,包含视图的构造、视图与文档连接在一起。
CDocTemplate构造函数的参数指定了3种类(文档、视图、框架)的CRuntimeClass
CRuntimeClass没有基类。
每个由CObject派生的类都与一个CRuntimeClass结构相联系,用户可以使用该结构获取一个对象及其基类的运行时信息。
当需要额外的函数参数检查时,或当用户必须根据一个对象的类编写特殊目的代码时,在运行时确定该对象的类就非常有用。
C++并不直接支持运行时类的信息。
一个从CFrameWnd中派生出的框架窗口类,必须由DECLARE_DYNCREATE声明以使RUNTIME_CLASS机制运行正确。
在MainFrame.h中如下代码:
classCMainFrame:
publicCFrameWnd
{
protected:
//createfromserializationonly
CMainFrame();
DECLARE_DYNCREATE(CMainFrame)
框架类中有一个非常重要的函数Create,其参数rect(全名rectangle矩形)定义窗口的大小和位置。
3、单文档类CSingleDocTemplate
CSingleDocTemplate定义了一个文档模板用于实现单文档界面(SDI)。
文档模板包括文档类型(如菜单,图标,资源加速符号表)使用的资源ID,还含有文档类型的更多信息,包括文档类型名称(如worksheet),文件扩展名(如xls)
可以认为View类窗口是CMainFram类窗口的子窗口。
DOCument类是文档类。
DOC-VIEW结构将数据本身与它的显示分离开。
文档类用于数据的存储,加载;视类用于数据的显示,修改。
CTypingTestApp:
:
InitInstance()函数中通过文档模板将文档类,视类,框架类的有机组织一起。
语句如下:
CSingleDocTemplate*pDocTemplate;
pDocTemplate=newCSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CTypingTestDoc),
RUNTIME_CLASS(CMainFrame),//mainSDIframewindow
RUNTIME_CLASS(CTypingTestView));
AddDocTemplate(pDocTemplate);//增加到模板
4、应用程序类
在名为TypingTest的MFC中,在类视图中,双击CTypingTestApp,会转到如下语句:
classCTypingTestApp:
publicCWinApp,选中CWinApp然后转到其定义处,可见如下代码:
classCWinApp:
publicCWinThread
{
DECLARE_DYNAMIC(CWinApp)
public:
//Constructor
CWinApp(LPCTSTRlpszAppName=NULL);//appnamedefaultstoEXEname
//Attributes
//Startupargs(donotchange)
HINSTANCEm_hInstance;
HINSTANCEm_hPrevInstance;
LPTSTRm_lpCmdLine;
intm_nCmdShow;
//Runningargs(canbechangedinInitInstance)
LPCTSTRm_pszAppName;//humanreadablename
CWinApp保存了一些传递给WinMain函数的参数,这些参数包括m_hInstance,m_hPrevInstance,m_lpCmdLine,m_nCmdShow。
CWinApp在m_pszAppName中保存了应用程序名字的拷贝
CWinApp中保存了指向可执行文件名字的指针m_pszExeName,指向应用程序帮助文件路径的指针m_pszHelpFilePath,以及指向其应用程序配置文件名字的指针m_pszProfileName。
CWinApp还用了一个叫做CCommandLineInfo的类来保存命令行参数,其定义在AFXWIN.H中
在CWinApp还会有如下代码:
virtualBOOLInitInstance();
virtualintExitInstance();//returnappexitcode
virtualintRun();
virtualBOOLOnIdle(LONGlCount);//returnTRUEifmoreidle
每个应用程序都需要进行针对实例的初始化。
在MFC中,此部分功能由CWinApp:
:
InitInstance();完成。
这个函数是虚函数,在派生类中必须重写这个函数,一般会在这个函数里面显示主窗口。
通过CWinApp:
:
ExitInstance();来完成关闭应用程序时的资源清理工作,这个也是虚函数。
在MFC中,消息是CWinApp的一部分,调用CWinApp:
:
Run();会启动标准的GetMessage()和DispatchMessage()循环。
CWinApp的消息循环还支持后台处理。
由于Windows使用事件驱动机制,所以应用程序运行期间队列中可能没有任何消息。
每当消息队列为空时,MFC会调用OnIdle()函数。
保存主窗口句柄的成员变量m_pMainWnd,在很久以前的MFC版本中m_pMainWnd安排在CWinApp,但是后来放到CWinApp的父类CWinThread。
CWinThread源代码也放在AFXWIN.H中
要获取CWinApp类的信息,除了使用CWinApp的成员函数,MFC还提供了一些全局函数。
如
AfxGetApp:
返回指向应用程序CWinApp对象的指针
AfxGetInstanceHandle:
获得当前应用程序CWinApp对象的实例句柄
AfxGetResourceHandle:
获得包含资源的模块句柄(一般资源句柄就是模块句柄)
AfxGetAppName:
5、theApp----唯一的应用
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- MFC 开发软件