MFC中用于创建窗口的CWnd类
1、 创建窗口的函数
2、 本文重点介绍Create与CreateEx函数,二者封装了Win32的::CreateWindowEx窗口创建接口。其中,Create函数的原型结构如下所示。
3、 Create是一个用于创建子窗口的虚拟函数,无法创建桌面窗口或弹出式窗口。CWnd的派生类可重写此函数以实现特定功能,如框架窗口类通过重写实现边框窗口的创建,而视图类则利用它来生成视图窗口,满足不同界面元素的构建需求。
4、 Create函数调用了成员函数CreateEx,其原型定义在CWnd类中,具体形式如下所示。
5、 CreateEx函数包含11个参数,用于调用底层的::CreateWindowEx来创建窗口,所有参数会逐一传递给该系统函数。这些参数分别定义了窗口的扩展样式、注册的窗口类名、显示标题、尺寸与位置坐标、父窗口句柄、菜单资源句柄以及用户自定义的创建数据,全面控制窗口的外观和行为特征。
6、 关于CreateEx的处理流程,将在第4.4.1节讲解窗口过程时详细探讨。
7、 当窗口创建时,系统会发送WM_CREATE消息,其lParam参数指向一个CreateStruct结构体变量。该结构包含11个成员字段,具体含义将在后续4.4.1节关于窗口过程的分析中详细说明。Windows会使用与CreateEx函数调用时传入的参数相同的数据来填充此结构体内容。
8、 窗口关闭处理函数
9、 例如:
10、 DestroyWindow函数用于销毁指定的窗口。
11、 窗口销毁后调用的虚函数PostNcDestroy()。
12、 用于设置、读取和修改窗口属性的函数,如:
13、 调用SetWindowText函数,传入CString类型的标题参数,用于修改窗口的显示标题内容。
14、 获取窗口标题可通过GetWindowText函数实现
15、 设置窗口图标函数,用于指定窗口显示的大或小图标。
16、 获取窗口图标,根据参数返回大或小图标。
17、 获取指定ID的窗口控件子对象。
18、 设置窗口的菜单项,指定菜单指针以关联到当前窗口。
19、 获取窗口的菜单信息
20、 …
21、 实现窗口操作功能的函数
22、 用于实现窗口刷新、滚动等功能,部分成员函数被设计为可重载函数、虚函数或MFC消息响应函数。这些函数有的具备具体功能实现,有的则为空函数体,仅为后续扩展预留接口,便于派生类根据需要进行重写或补充相应逻辑处理。
23、 消息发送功能相关函数
24、 向窗口发送消息并立即调用
25、 向窗口发送消息并加入队列
26、 …
27、 调整窗口状态的相关函数
28、 将窗口移至指定位置
29、 显示或隐藏窗口,通过布尔值控制其可见状态。
30、 ….
31、 实现MFC消息处理的函数方法
32、 窗口过程函数,用于处理窗口消息的虚拟方法。该函数接收消息类型及两个参数,实现对不同消息的分发与响应,是窗口类中核心的消息处理机制,可通过重写定制具体行为。
33、 处理命令消息的函数,接收 wParam 和 lParam 两个参数,返回布尔类型值,用于响应用户界面中的各种命令操作。
34、 …
35、 处理消息的函数
36、 OnCreate(LPCREATESTRUCT lpCreateStruct) 是MFC框架在窗口创建时自动调用的消息处理函数,用于执行初始化操作,完成窗口创建前的准备工作,确保后续功能正常运行。
37、 窗口关闭时触发,由MFC框架在创建窗口后自动调用的消息处理函数。
38、 …
39、 其他功能函数
40、 CWnd的派生类是功能更丰富、类型更具体的窗口类,它们不仅继承了CWnd的基本属性与方法,还扩展了新的成员函数,如消息处理函数和虚函数等。
41、 常见窗口类及层级结构1-1所示。
42、 用MFC创建窗口对象
43、 在MFC中创建窗口对象需分两步进行:首先构建MFC窗口对象,随后创建对应的Windows窗口。该MFC对象可位于栈上,也可在堆中动态分配(通过new操作符实现),内存布局灵活,取决于具体使用需求。
44、 通过定义CWnd或其派生类的实例变量,可在栈中创建MFC窗口对象;通过动态创建该类实例,则在堆中生成MFC窗口对象。这两种方式分别实现了窗口对象在不同内存区域的建立,适用于不同的应用场景。
45、 调用函数创建Windows窗口对象。
46、 例如,在前述由AppWizard生成的代码中,CMainFrame类(继承自CMDIFrameWnd或CMDIFrameWnd)包含两个成员变量,其定义如下所示。该类用于实现主框架窗口功能,是应用程序界面的核心组成部分之一。
47、 创建CMainFrame类对象时,会同时构造上述两个MFC对象。
48、 CMainFrame类包含另一个成员函数。
49、 其具体实现包含一段代码,通过调用CToolBar和CStatusBar的Create成员函数,创建与这两个MFC对象相对应的工具栏和状态栏窗口句柄(HWND)。
50、 {
51、 …
52、 {
53、 }
54、 {
55、 }
56、 …
57、 }
58、 工具栏与状态栏的具体内容将在后续章节详细讲解。
59、 MFC提供了一种动态创建机制,该过程虽也分为两步,但由框架自动完成。通常,主框架窗口、文档框架窗口以及视图类都采用这种技术进行创建。由于MFC自身的架构设计特点,即使不显式使用动态创建,CFrameWnd和CView及其派生类的对象也必须通过new在堆上分配内存。这一要求主要源于窗口销毁时的处理机制,具体原因可参考相关章节关于窗口销毁的说明。
60、 动态创建技术的具体内容将在后续章节详细阐述。
61、 创建Windows窗口时,系统会发送一系列相关消息。
62、 窗口非客户区创建完成后,系统会发送WM_NCCREATE消息通知应用程序。
63、 窗口客户区创建完成后,系统会向其发送WM_CREATE消息。
64、 窗口在显示前,其窗口过程会接收到这两个消息。
65、 若为子窗口,在发送前述两个消息后,还需向父窗口发送WM_PARENTNOTIFY消息。具有其他类别或样式的窗口可能触发更多消息,详情请参考SDK开发文档。
66、 MFC窗口应用方法
67、 MFC包含众多功能各异的窗口类,程序员需根据需求选择合适的类,并掌握其具体使用方法。
68、 在大多数情况下,使用MFC提供的窗口类或从其派生新的C++类时,程序员无需手动编写窗口注册代码。是否需要派生新类,取决于现有MFC窗口类能否满足实际需求。通过继承,新类可保留基类的特性,同时扩展或修改功能,例如对特定消息和事件进行定制化处理,从而实现更灵活的窗口行为控制,提升应用程序的可维护性与可扩展性。
69、 主要采用或继承若干MFC窗口类,具体层次结构1-1所示。
70、 包含CFrameWnd和CMdiFrameWnd的框架类。
71、 文档框架类CMdiChildWnd的结构解析
72、 视图类CView及其派生类包含多种具有特定功能的视图,例如用于显示列表的CListView、提供文本编辑功能的CEditView、实现树形结构展示的CTreeView、支持富文本格式的CRichEditView,以及基于对话框布局的CFormView等,这些视图扩展了基本视图的功能,适用于不同的用户界面需求。
73、 对话框类CDialog的使用方法
74、 一般需从这些类派生出应用的框架窗口、视图窗口或对话框。
75、 工具栏 CToolBar
76、 状态栏 CStatusBar
77、 包括列表框、编辑框、组合框、按钮等多种类型的控制窗口。
78、 一般直接调用这些类即可。
79、 MFC中窗口的销毁过程
80、 窗口对象使用结束后应及时销毁。在MFC中,销毁过程包括HWND句柄和MFC窗口对象两部分的释放,通常由MFC框架自动完成相关处理,开发者无需手动干预整个销毁流程。
81、 派生自CFrameWnd和CView的类用于构建应用程序主窗口与视图功能。
82、 当这些窗口被关闭时,系统会调用DestroyWindow函数来销毁窗口。在销毁Windows窗口的过程中,MFC框架最后执行的成员函数是OnNcDestroy,该函数主要负责清理与窗口相关的资源,并在其末尾调用一个虚函数PostNcDestroy。对于CFrameWnd和CView类而言,它们的PostNcDestroy函数中包含了delete this语句,这意味着在窗口销毁后,对应的MFC窗口对象将自动释放自身所占用的内存,从而实现对象的自我销毁。这一机制确保了窗口资源的完整回收,避免了内存泄漏问题,是MFC框架中窗口生命周期管理的重要组成部分。
83、 因此,这些窗口应如前所说在堆中分配内存,且不应对其使用delete操作来释放。
84、 操作Windows控制窗口的相关设置与功能调整。
85、 当窗口对象的析构函数被调用时,会自动执行DestroyWindow以销毁窗口。若该对象在栈上创建,一旦超出其作用域,析构函数便会触发,导致MFC窗口对象及其对应的Windows窗口一同被释放。若对象是在堆上动态分配的,则需手动调用delete操作符,从而引发析构函数执行,完成窗口资源的清理与销毁。
86、 这类窗口应尽量在栈上分配,以减少额外的销毁代码。例如,CMainFrame中的成员变量m_wndStatusBar和m_wndToolBar便是典型实例,它们在对象生命周期内自动管理,无需手动释放,既简化了资源管理,又提高了程序的稳定性和效率。
87、 程序员直接从CWnd派生的窗口处理方式
88、 开发者可在子类中选择实现任一机制,并按规范要求进行应用。
评论
更多评论