2.2 Windows Object

2.2 Windows Object

SDKWin32 API编写各种Windows应用程序,有其共同的规律:首先是编写WinMain函数,编写处理消息和事件的窗口过程WndProc,在WinMain里头注册窗口(Register Window),创建窗口,然后开始应用程序的消息循环。

MFC应用程序也不例外,因为MFC是一个建立在SDK API基础上的编程框架。对程序员来说所不同的是:一般情况下,MFC框架自动完成了Windows登记、创建等工作。

下面,简要介绍MFC WindowWindows Window的封装。

2.2.1 Windows注册

一个应用程序在创建某个类型的窗口前,必须首先注册该“窗口类”(Windows Class)。注意,这里不是C++类的类。Register Window把窗口过程、窗口类型以及其他类型信息和要登记的窗口类关联起来。

(1)       “窗口类”的数据结构

“窗口类”是Windows系统的数据结构,可以把它理解为Windows系统的类型定义,而Windows窗口则是相应“窗口类”的实例。Windows使用一个结构来描述“窗口类”,其定义如下:

typedef struct _WNDCLASSEX {  

    UINT    cbSize; //该结构的字节数

    UINT    style;  //窗口类的风格

    WNDPROC lpfnWndProc; //窗口过程

    int     cbClsExtra;

    int     cbWndExtra;

    HANDLE  hInstance; //该窗口类的窗口过程所属的应用实例

    HICON   hIcon; //该窗口类所用的像标

    HCURSOR hCursor; //该窗口类所用的光标

    HBRUSH  hbrBackground; //该窗口类所用的背景刷

    LPCTSTR lpszMenuName; //该窗口类所用的菜单资源

    LPCTSTR lpszClassName; //该窗口类的名称

    HICON   hIconSm; //该窗口类所用的小像标

} WNDCLASSEX;

从“窗口类”的定义可以看出,它包含了一个窗口的重要信息,如窗口风格、窗口过程、显示和绘制窗口所需要的信息,等等。关于窗口过程,将在后面消息映射等有关章节作详细论述。

Windows系统在初始化时,会注册(Register)一些全局的“窗口类”,例如通用控制窗口类。应用程序在创建自己的窗口时,首先必须注册自己的窗口类。在MFC环境下,有几种方法可以用来注册“窗口类”,下面分别予以讨论。

(2)       调用AfxRegisterClass注册

AfxRegisterClass函数是MFC全局函数。AfxRegisterClass的函数原型:

BOOL AFXAPI AfxRegisterClass(WNDCLASS *lpWndClass);

参数lpWndClass是指向WNDCLASS结构的指针,表示一个“窗口类”。

首先,AfxRegisterClass检查希望注册的“窗口类”是否已经注册,如果是则表示已注册,返回TRUE,否则,继续处理。

接着,调用::RegisterClass(lpWndClass)注册窗口类;

然后,如果当前模块是DLL模块,则把注册“窗口类”的名字加入到模块状态的域m_szUnregisterList中。该域是一个固定长度的缓冲区,依次存放模块注册的“窗口类”的名字(每个名字是以“\n\0”结尾的字符串)。之所以这样做,是为了DLL退出时能自动取消(Unregister)它注册的窗口类。至于模块状态将在后面第9章详细的讨论。

最后,返回TRUE表示成功注册。

(3)       调用AfxRegisterWndClass注册

AfxRegisterWndClass函数也是MFC全局函数。AfxRegisterWndClass的函数原型:

LPCTSTR AFXAPI AfxRegisterWndClass(UINT nClassStyle,

HCURSOR hCursor, HBRUSH hbrBackground, HICON hIcon)

参数1指定窗口类风格;

参数234分别指定该窗口类使用的光标、背景刷、像标的句柄,缺省值是0

此函数根据窗口类属性动态地产生窗口类的名字,然后,判断是否该类已经注册,是则返回窗口类名;否则用指定窗口类的属性(窗口过程指定为缺省窗口过程),调用AfxRegisterCalss注册窗口类,返回类名。

动态产生的窗口类名字由以下几部分组成(包括冒号分隔符):

如果参数234全部为NULL,则由三部分组成。

Afx+:+模块实例句柄”+:+“窗口类风格”

否则,由六部分组成:

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内部使用了函数

BOOL AFXAPI AfxEndDeferRegisterClass(short fClass)

来帮助注册上述原MFC版本的预定义“窗口类”。参数fClass区分了那些预定义窗口的类型。根据不同的类型,使用不同的窗口类风格、窗口类名字等填充WndClass的域,然后调用AfxRegisterClass注册窗口类。并且注册成功之后,通过模块状态的m_fRegisteredClasses记录该窗口类已经注册,这样该模块在再次需要注册这些窗口类之前可以查一下m_fRegisteredClasses,如果已经注册就不必浪费时间了。为此,MFC内部使用宏

AfxDeferRegisterClass(short fClass)

来注册“窗口类”,如果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)一个“窗口类”,可自动地得到它的“窗口类”属性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值