MFC和win32文档格式.docx
- 文档编号:16504586
- 上传时间:2022-11-24
- 格式:DOCX
- 页数:20
- 大小:46.66KB
MFC和win32文档格式.docx
《MFC和win32文档格式.docx》由会员分享,可在线阅读,更多相关《MFC和win32文档格式.docx(20页珍藏版)》请在冰豆网上搜索。
可以从一个MFCObject得到对应的WindowsObject的句柄;
一般使用MFCObject的成员函数GetSafeHandle得到对应的句柄。
可以从一个已存在的WindowsObject创建一个对应的MFCObject;
一般使用MFCObject的成员函数Attach或者FromHandle来创建,前者得到一个永久性对象,后者得到的可能是一个临时对象。
5.从使用范围上比较
MFCObject对系统的其他进程来说是不可见、不可用的;
而WindowsObject一旦创建,其句柄是整个Windows系统全局的。
一些句柄可以被其他进程使用。
典型地,一个进程可以获得另一进程的窗口句柄,并给该窗口发送消息。
对同一个进程的线程来说,只可以使用本线程创建的MFCObject,不能使用其他线程的MFCObject。
6.从销毁上比较
MFCObject随着析构函数的调用而消失;
但WindowsObject必须由相应的Windows系统函数销毁。
设备描述表CDC类的对象有所不同,它对应的HDC句柄对象可能不是被销毁,而是被释放。
当然,可以在MFCObject的析构函数中完成WindowsObject的销毁,MFCObject的GDI类等就是如此实现的,但是,应该看到:
两者的销毁是不同的。
每类WindowsObject都有对应的MFCObject,下面用表格的形式列出它们之间的对应关系,如表2-1所示:
表2-1MFCObject和WindowsObject的对应关系
描述
Windows句柄
MFCObject
窗口
HWND
CWndandCWnd-derivedclasses
设备上下文
HDC
CDCandCDC-derivedclasses
菜单
HMENU
CMenu
笔
HPEN
CGdiObject类,CPen和CPen-derivedclasses
刷子
HBRUSH
CGdiObject类,CBrush和CBrush-derivedclasses
字体
HFONT
CGdiObject类,CFont和CFont-derivedclasses
位图
HBITMAP
CGdiObject类,CBitmap和CBitmap-derivedclasses
调色板
HPALETTE
CGdiObject类,CPalette和CPalette-derivedclasses
区域
HRGN
CGdiObject类,CRgn和CRgn-derivedclasses
图像列表
HimageLIST
CimageList和CimageList-derivedclasses
套接字
SOCKET
CSocket,CAsynSocket及其派生类
表2-1中的OBJECT分以下几类:
Windows对象,
设备上下文对象,
GDI对象(BITMAP,BRUSH,FONT,PALETTE,PEN,RGN),
菜单,
图像列表,
网络套接字接口。
从广义上来看,文档对象和文件可以看作一对MFCObject和WindowsObject,分别用CDocument类和文件句柄描述。
后续几节分别对前四类作一个简明扼要的论述。
1.WindowsObject
用SDK的Win32API编写各种Windows应用程序,有其共同的规律:
首先是编写WinMain函数,编写处理消息和事件的窗口过程WndProc,在WinMain里头注册窗口(RegisterWindow),创建窗口,然后开始应用程序的消息循环。
MFC应用程序也不例外,因为MFC是一个建立在SDKAPI基础上的编程框架。
对程序员来说所不同的是:
一般情况下,MFC框架自动完成了Windows登记、创建等工作。
下面,简要介绍MFCWindow对WindowsWindow的封装。
1.Windows的注册
一个应用程序在创建某个类型的窗口前,必须首先注册该“窗口类”(WindowsClass)。
注意,这里不是C++类的类。
RegisterWindow把窗口过程、窗口类型以及其他类型信息和要登记的窗口类关联起来。
1.“窗口类”的数据结构
“窗口类”是Windows系统的数据结构,可以把它理解为Windows系统的类型定义,而Windows窗口则是相应“窗口类”的实例。
Windows使用一个结构来描述“窗口类”,其定义如下:
typedefstruct_WNDCLASSEX{
UINTcbSize;
//该结构的字节数
UINTstyle;
//窗口类的风格
WNDPROClpfnWndProc;
//窗口过程
intcbClsExtra;
intcbWndExtra;
HANDLEhInstance;
//该窗口类的窗口过程所属的应用实例
HICONhIcon;
//该窗口类所用的像标
HCURSORhCursor;
//该窗口类所用的光标
HBRUSHhbrBackground;
//该窗口类所用的背景刷
LPCTSTRlpszMenuName;
//该窗口类所用的菜单资源
LPCTSTRlpszClassName;
//该窗口类的名称
HICONhIconSm;
//该窗口类所用的小像标
}WNDCLASSEX;
从“窗口类”的定义可以看出,它包含了一个窗口的重要信息,如窗口风格、窗口过程、显示和绘制窗口所需要的信息,等等。
关于窗口过程,将在后面消息映射等有关章节作详细论述。
Windows系统在初始化时,会注册(Register)一些全局的“窗口类”,例如通用控制窗口类。
应用程序在创建自己的窗口时,首先必须注册自己的窗口类。
在MFC环境下,有几种方法可以用来注册“窗口类”,下面分别予以讨论。
2.调用AfxRegisterClass注册
AfxRegisterClass函数是MFC全局函数。
AfxRegisterClass的函数原型:
BOOLAFXAPIAfxRegisterClass(WNDCLASS*lpWndClass);
参数lpWndClass是指向WNDCLASS结构的指针,表示一个“窗口类”。
首先,AfxRegisterClass检查希望注册的“窗口类”是否已经注册,如果是则表示已注册,返回TRUE,否则,继续处理。
接着,调用:
:
RegisterClass(lpWndClass)注册窗口类;
然后,如果当前模块是DLL模块,则把注册“窗口类”的名字加入到模块状态的域m_szUnregisterList中。
该域是一个固定长度的缓冲区,依次存放模块注册的“窗口类”的名字(每个名字是以“\n\0”结尾的字符串)。
之所以这样做,是为了DLL退出时能自动取消(Unregister)它注册的窗口类。
至于模块状态将在后面第9章详细的讨论。
最后,返回TRUE表示成功注册。
3.调用AfxRegisterWndClass注册
AfxRegisterWndClass函数也是MFC全局函数。
AfxRegisterWndClass的函数原型:
LPCTSTRAFXAPIAfxRegisterWndClass(UINTnClassStyle,
HCURSORhCursor,HBRUSHhbrBackground,HICONhIcon)
参数1指定窗口类风格;
参数2、3、4分别指定该窗口类使用的光标、背景刷、像标的句柄,缺省值是0。
此函数根据窗口类属性动态地产生窗口类的名字,然后,判断是否该类已经注册,是则返回窗口类名;
否则用指定窗口类的属性(窗口过程指定为缺省窗口过程),调用AfxRegisterCalss注册窗口类,返回类名。
动态产生的窗口类名字由以下几部分组成(包括冒号分隔符):
如果参数2、3、4全部为NULL,则由三部分组成。
“Afx”+“:
”+模块实例句柄”+“:
”+“窗口类风格”
否则,由六部分组成:
”+模块实例句柄+“:
”+“窗口类风格”+“:
”+光标句柄+“:
”+背景刷句柄+“:
”+像标句柄。
比如:
“Afx:
400000:
b:
13de:
6:
32cf”。
该函数在MFC注册主边框或者文档边框“窗口类”时被调用。
具体怎样用在5.3.3.3节会指出。
4.隐含的使用MFC预定义的的窗口类
MFC4.0以前的版本提供了一些预定义的窗口类,4.0以后不再预定义这些窗口类。
但是,MFC仍然沿用了这些窗口类,例如:
用于子窗口的“AfxWnd”;
用于边框窗口(SDI主窗口或MDI子窗口)或视的“AfxFrameOrView”;
用于MDI主窗口的“AfxMDIFrame”;
用于标准控制条的“AfxControlBar”。
这些类的名字就是“AfxWnd”、“AfxFrameOrView”、“AfxMdiFrame”、“AfxControlBar”加上前缀和后缀(用来标识版本号或是否调试版等)。
它们使用标准应用程序像标、标准文档像标、标准光标等标准资源。
为了使用这些“窗口类”,MFC会在适当的时候注册这些类:
或者要创建该类的窗口时,或者创建应用程序的主窗口时,等等。
MFC内部使用了函数
BOOLAFXAPIAfxEndDeferRegisterClass(shortfClass)
来帮助注册上述原MFC版本的预定义“窗口类”。
参数fClass区分了那些预定义窗口的类型。
根据不同的类型,使用不同的窗口类风格、窗口类名字等填充WndClass的域,然后调用AfxRegisterClass注册窗口类。
并且注册成功之后,通过模块状态的m_fRegisteredClasses记录该窗口类已经注册,这样该模块在再次需要注册这些窗口类之前可以查一下m_fRegisteredClasses,如果已经注册就不必浪费时间了。
为此,MFC内部使用宏
AfxDeferRegisterClass(shortfClass)
来注册“窗口类”,如果m_fRegisteredClasses记录了注册的窗口类,返回TRUE,否则,调用AfxEndDeferRegisterClass注册。
注册这些窗口类的例子:
MFC在加载边框窗口时,会自动地注册“AfxFrameOrView”窗口类。
在创建视时,就会使用该“窗口类”创建视窗口。
当然,如果创建视窗口时,该“窗口类”还没有注册,MFC将先注册它然后使用它创建视窗口。
不过,MFC并不使用”AfxMDIFrame”来创建MDI主窗口,因为在加载主窗口时一般都指定了主窗口的资源,MFC使用指定的像标注册新的MDI主窗口类(通过函数AfxRegisterWndClass完成,因此“窗口类”的名字是动态产生的)。
MDI子窗口类似于上述MDI主窗口的处理。
在MFC创建控制窗口时,如工具栏窗口,如果“AfxControlBar”类还没有注册,则注册它。
注册过程很简单,就是调用:
InitCommonControl加载通用控制动态连接库。
5.调用:
RegisterWndClass。
直接调用Win32的窗口注册函数:
RegisterWndClass注册“窗口类”,这样做有一个缺点:
如果是DLL模块,这样注册的“窗口类”在程序退出时不会自动的被取消注册(Unregister)。
所以必须记得在DLL模块退出时取消它所注册的窗口类。
6.子类化
子类化(Subclass)一个“窗口类”,可自动地得到它的“窗口类”属性。
1.MFC窗口类CWnd
在Windows系统里,一个窗口的属性分两个地方存放:
一部分放在“窗口类”里头,如上所述的在注册窗口时指定;
另一部分放在WindowsObject本身,如:
窗口的尺寸,窗口的位置(X,Y轴),窗口的Z轴顺序,窗口的状态(ACTIVE,MINIMIZED,MAXMIZED,RESTORED…),和其他窗口的关系(父窗口,子窗口…),窗口是否可以接收键盘或鼠标消息,等等。
为了表达所有这些窗口的共性,MFC设计了一个窗口基类CWnd。
有一点非常重要,那就是CWnd提供了一个标准而通用的MFC窗口过程,MFC下所有的窗口都使用这个窗口过程。
至于通用的窗口过程却能为各个窗口实现不同的操作,那就是MFC消息映射机制的奥秘和作用了。
这些,将在后面有关章节详细论述。
CWnd提供了一系列成员函数,或者是对Win32相关函数的封装,或者是CWnd新设计的一些函数。
这些函数大致如下。
(1)窗口创建函数
这里主要讨论函数Create和CreateEx。
它们封装了Win32窗口创建函数:
CreateWindowEx。
Create的原型如下:
BOOLCWnd:
Create(LPCTSTRlpszClassName,
LPCTSTRlpszWindowName,DWORDdwStyle,
constRECT&
rect,
CWnd*pParentWnd,UINTnID,
CCreateContext*pContext)
Create是一个虚拟函数,用来创建子窗口(不能创建桌面窗口和POPUP窗口)。
CWnd的基类可以覆盖该函数,例如边框窗口类等覆盖了该函数以实现边框窗口的创建,视类则使用它来创建视窗口。
Create调用了成员函数CreateEx。
CWnd:
CreateEx的原型如下:
CreateEx(DWORDdwExStyle,LPCTSTRlpszClassName,
intx,inty,intnWidth,intnHeight,
HWNDhWndParent,HMENUnIDorHMenu,LPVOIDlpParam)
CreateEx有11个参数,它将调用:
CreateWindowEx完成窗口的创建,这11个参数对应地传递给:
参数指定了窗口扩展风格、“窗口类”、窗口名、窗口大小和位置、父窗口句柄、窗口菜单和窗口创建参数。
CreateEx的处理流程将在后面4.4.1节讨论窗口过程时分析。
窗口创建时发送WM_CREATE消息,消息参数lParam指向一个CreateStruct结构的变量,该结构有11个域,其描述见后面4.4.1节对窗口过程的分析,Windows使用和CreateEx参数一样的内容填充该变量。
(2)窗口销毁函数
例如:
DestroyWindow函数销毁窗口
PostNcDestroy(),销毁窗口后调用,虚拟函数
(3)用于设定、获取、改变窗口属性的函数,例如:
SetWindowText(CStringtiltle)设置窗口标题
GetWindowText()得到窗口标题
SetIcon(HICONhIcon,BOOLbBigIcon);
设置窗口像标
GetIcon(BOOLbBigIcon);
得到窗口像标
GetDlgItem(intnID);
得到窗口类指定ID的控制子窗口
GetDC();
得到窗口的设备上下文
SetMenu(CMenu*pMenu);
设置窗口菜单
GetMenu();
得到窗口菜单
…
(4)用于完成窗口动作的函数
用于更新窗口,滚动窗口,等等。
一部分成员函数设计成或可重载(Overloaded)函数,或虚拟(Overridden)函数,或MFC消息处理函数。
这些函数或者实现了一部分功能,或者仅仅是一个空函数。
如:
∙有关消息发送的函数:
SendMessage(UINTmessage,WPARAMwParam=0,LPARAMlParam=0);
给窗口发送发送消息,立即调用方式
PostMessage((UINTmessage,WPARAMwParam=0,LPARAMlParam=0);
给窗口发送消息,放进消息队列
∙有关改变窗口状态的函数
MoveWindow(LPCRECTlpRect,BOOLbRepaint=TRUE);
移动窗口到指定位置
ShowWindow(BOOL);
显示窗口,使之可见或不可见
….
∙实现MFC消息处理机制的函数:
virtualLRESULTWindowProc(UINTmessage,WPARAMwParam,LPARAMlParam);
窗口过程,虚拟函数
virtualBOOLOnCommand(WPARAMwParam,LPARAMlParam);
处理命令消息
∙消息处理函数:
OnCreate(LPCREATESTRUCTlpCreateStruct);
MFC窗口消息处理函数,窗口创建时由MFC框架调用
OnClose();
∙其他功能的函数
CWnd的导出类是类型更具体、功能更完善的窗口类,它们继承了CWnd的属性和方法,并提供了新的成员函数(消息处理函数、虚拟函数、等等)。
常用的窗口类及其层次关系见图1-1。
1.在MFC下创建一个窗口对象
MFC下创建一个窗口对象分两步,首先创建MFC窗口对象,然后创建对应的Windows窗口。
在内存使用上,MFC窗口对象可以在栈或者堆(使用new创建)中创建。
具体表述如下:
∙创建MFC窗口对象。
通过定义一个CWnd或其派生类的实例变量或者动态创建一个MFC窗口的实例,前者在栈空间创建一个MFC窗口对象,后者在堆空间创建一个MFC窗口对象。
∙调用相应的窗口创建函数,创建Windows窗口对象。
在前面提到的AppWizard产生的源码中,有CMainFrame(派生于CMDIFrame(SDI)或者CMDIFrameWnd(MDI))类。
它有两个成员变量定义如下:
CToolBarm_wndToolBar;
CStatusBarm_wndStatusBar;
当创建CMainFrame类对象时,上面两个MFCObject也被构造。
CMainFrame还有一个成员函数
OnCreate(LPCREATESTRUCTlpCreateStruct),
它的实现包含如下一段代码,调用CToolBar和CStatusBar的成员函数Create来创建上述两个MFC对象对应的工具栏HWND窗口和状态栏HWND窗口:
intCMainFrame:
OnCreate(LPCREATESTRUCTlpCreateStruct)
{
if(!
m_wndToolBar.Create(this)||
!
m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
TRACE0("
Failedtocreatetoolbar\n"
);
return-1;
//failtocreate
}
m_wndStatusBar.Create(this)||
m_wndStatusBar.SetIndicators(indicators,
sizeof(indicators)/sizeof(UINT)))
Failedtocreatestatusbar\n"
关于工具栏、状态栏将在后续有关章节作详细讨论。
在MFC中,还提供了一种动态创建技术。
动态创建的过程实际上也如上所述分两步,只不过MFC使用这个技术是由框架自动地完成整个过程的。
通常框架窗口、文档框架窗口、视使用了动态创建。
介于MFC的结构,CFrameWnd和CView及其派生类的实例即使不使用动态创建,也要用new在堆中分
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- MFC win32