首页 理论教育VC++MFC视频教程:注册和创建自定义窗口

VC++MFC视频教程:注册和创建自定义窗口

【摘要】:2)所有控件创建时,都要在CWnd::Create函数中代入窗口ID、风格、位置和父窗口等。4)注册自定义窗口类型。MFC全局函数,先检测要注册的窗口类型是否存在。并将接口参数简化以方便调用,返回值是自动生成的随机窗口类型名。5)创建一个工程名为“wd”的对话框程序,用于演示自定义窗口的注册和创建。总结使用自定义窗口做主窗口的特点如下。

在本章第1节的示例中,调用了多种控件类的创建函数,例如,CStatic::Create和CEdit::Create等。

跟踪查看控件类创建函数的源代码,这些创建函数的共同特点如下。

1)所有控件类的创建函数,都通过调用基类成员函数CWnd::Create来实现。

2)所有控件创建时,都要在CWnd::Create函数中代入窗口ID、风格、位置和父窗口等。

3)所有控件创建时,都要在CWnd::Create函数的第一个参数中代入控件种类,即窗口类型名。

4)有些控件要有标题文字(如,按钮),在CWnd::Create的第二个参数中代入,否则代入NULL。

978-7-111-46378-8-Chapter11-12.jpg

978-7-111-46378-8-Chapter11-13.jpg

注册和创建自定义窗口的过程如下。

1)什么是窗口类型名。

生物的基因决定了一个新生命的特征,新生的小狗和小鸟之所以特征不同,就是因为各自的基因是不同的。窗口类型名就相当于窗口“体内的基因”,指定什么窗口类型名就能创建出什么类型的窗口。窗口类型名允许大小写不匹配,系统已注册的包括对话框、工具栏以及所有控件。系统通用窗口类型见表11-1。

表11-1 系统通用窗口类型

978-7-111-46378-8-Chapter11-14.jpg

2)CWnd::Create和CWnd::CreateEx。

窗口创建函数CWnd::Create,调用的是带扩展风格的窗口创建函数CWnd::CreateEx。

978-7-111-46378-8-Chapter11-15.jpg

3)对比CWnd::Create和CWnd::CreateEx两个函数。

①从函数格式上看,后者只多出一个参数(第一个参数),是用于指定扩展风格的。

②若要创建的窗口无需扩展风格(例如,边缘凸起或下陷等),就直接调用CWnd::Create函数。

③若要在创建窗口时指定扩展风格就调用CWnd::CreateEx函数,在第一个参数中指定扩展风格(如同在第1节中创建第2个编辑框那样)。

④CWnd::Create函数只限于创建包括所有控件在内的子窗口,不能用于创建主窗口。

⑤CWnd::CreateEx函数不但可以创建子窗口,还可以用于创建框架类型的主窗口。

4)注册自定义窗口类型。

以上是通过调用CWnd::Create和CWnd::CreateEx函数,对系统已注册的窗口类型进行创建。如果要创建一个自定义的窗口类型,首先就要注册一个新的自定义窗口类型。

注册窗口类型名有以下3种方法。

①调用RegisterClass和RegisterClassEx函数。最早期的注册API函数,主要用于Win32程序开发。

②调用AfxRegisterClass函数。MFC全局函数,先检测要注册的窗口类型是否存在。若是已经注册过的类型名则无需再次注册,内部封装的是GetClassInfo和RegisterClass函数。

③调用AfxRegisterWndClass函数。MFC全局函数,内部调用AfxRegisterClass函数。并将接口参数简化以方便调用,返回值是自动生成的随机窗口类型名。

5)创建一个工程名为“wd”的对话框程序,用于演示自定义窗口的注册和创建。

978-7-111-46378-8-Chapter11-16.jpg

6)编译并运行,测试代码,如图11-5所示。

978-7-111-46378-8-Chapter11-17.jpg

图11-5 查看运行结果

7)再次修改InitInstance函数代码,调用CWnd::CreateEx函数创建一个弹出式的全屏窗口。

978-7-111-46378-8-Chapter11-18.jpg

978-7-111-46378-8-Chapter11-19.jpg

8)编译并运行,测试代码。

窗口根据风格分类主要有三大类。

①重叠式窗口(WS_TILEDWINDOW或WS_OVERLAPPEDWINDOW),具有应用程序主窗口的全部特点。它的非客户区包括一个可伸缩的框架、菜单条、标题栏和最小化、最大化按钮。

②弹出窗口(WS_POPUPWINDOW),具有消息框或者对话框的全部特点。它的非客户区是一个固定大小的框架。

③子窗口(WS_CHILDWINDOW),具有类似控件子窗口的全部特点。它不能作为主窗口,一般不显示非客户区,只有依赖于父窗口才能存在。(www.chuimin.cn)

9)在ResourceView中,单击鼠标右键,在弹出的快捷菜单中,选择“Insert”命令,添加一个菜单资源,如图11-6所示。

10)在新添加的菜单(IDR_MENU1)中,添加一些简单的菜单项,如图11-7所示。

978-7-111-46378-8-Chapter11-20.jpg

图11-6 插入菜单资源

978-7-111-46378-8-Chapter11-21.jpg

图11-7 编辑菜单资源

11)修改InitInstance函数代码,调用CWnd::CreateEx函数创建一个带菜单的窗口。

978-7-111-46378-8-Chapter11-22.jpg

978-7-111-46378-8-Chapter11-23.jpg

12)编译并运行,测试代码,如图11-8所示。

虽然菜单显示出来了,但是还是无法接收菜单和窗口消息。

13)在ClassView中,添加CWnd派生类,用于接收主窗口的消息,如图11-9所示。

978-7-111-46378-8-Chapter11-24.jpg

图11-8 查看运行结果

978-7-111-46378-8-Chapter11-25.jpg

图11-9 添加新类

14)类名填写“CMainWnd”,基类选择“generic CWnd”即可,如图11-10所示。

978-7-111-46378-8-Chapter11-26.jpg

图11-10 创建通用窗口派生类

15)在类视图中建立菜单项消息的反射函数,如图11-11所示。

978-7-111-46378-8-Chapter11-27.jpg

图11-11 添加菜单项的消息映射函数

16)修改OnAppExit消息反射函数代码。

978-7-111-46378-8-Chapter11-28.jpg

17)在类视图中添加一个虚函数,如图11-12所示。

978-7-111-46378-8-Chapter11-29.jpg

图11-12 添加虚函数

18)修改PostNcDestroy虚函数代码。

978-7-111-46378-8-Chapter11-30.jpg

19)修改InitInstance函数代码,在申请堆空间时指定CMainWnd类对象。

978-7-111-46378-8-Chapter11-31.jpg

20)编译并运行,测试代码。

总结使用自定义窗口做主窗口的特点如下。

①CWnd::CreateEx函数是非阻塞的,因此,必须在堆空间内申请窗口类对象。

②在申请堆空间时要指定派生类的对象,才能在派生类中接收并处理窗口的消息。

③申请的窗口派生类对象的地址,必须要保存在theApp.m_pMainWnd中。

④InitInstance函数如果返回FALSE,或m_pMainWnd是空值,则程序进程将被退出。

⑤MFC全局函数AfxGetMainWnd的返回值,就是theApp.m_pMainWnd的值。

⑥这类程序退出进程的方式,就是销毁m_pMainWnd关联的窗口。

例如,AfxGetMainWnd()→DestroyWindow();或AfxGetMainWnd()→PostMessage(WM_CLOSE);