窗口创建及窗口消息映射
可视化复习题 2

一、选择题1、下面说法正确的是( C )A、构造函数和析构函数都不可以重载。
B、构造函数不能重载,析构函数可以重载。
C、构造函数可以重载,析构函数不能重载。
D、构造函数可以重载,析构函数也可以重载。
2、下面关于API 的描述错误的是( C )A、API 函数构建在Windows 操作系统上。
B、创建应用程序、打开窗口、描绘图形都要调用API 函数。
C、现在,Windows 程序员编写程序只能使用API 函数。
D、API 是用来控制Windows 各个元素的外观和行为的一套预定义的Windows 函数。
3、下面关于MFC 的描述错误的是(B)A、MFC 是指微软基础类库。
B、MFC 不提供对底层API 的直接调用。
C、MFC 对API 函数进行了C++封装。
D、MFC 是微软公司提供的用在Visual C++环境下编写Windows 应用程序的一个框架和引擎。
4、下列对于WinMain 函数的描述中,错误的是(A )A、WinMain 函数不能有参数。
B、WinMain 函数是Windows 程序的入口点。
C、WinMain 函数的名称是固定的。
D、窗口函数与WinMain 的关联是通过窗口类的注册实现的。
5、对消息循环描述错误的是(D)A、TranslateMessage 将虚拟键转换成字符消息。
B、GetMessage 函数在消息队列为空时,将一直空闲。
C、GetMessage 函数在消息队列非空时,取得消息并返回。
D、若GetMessage 取得的是WM_QUIT 消息则返回非0,否则返回0。
6、注册窗口类型的API 函数是(B)A、CreateWindowB、RegisterClassC、ShowWindowD、UpdateWindow7、创建窗口的API 函数是(A)A、CreateWindowB、RegisterClassC、ShowWindowD、UpdateWindow8、关于GDI 的描述错误的是(D )A、GDI 指图像设备接口。
mfc 消息机制

mfc消息机制
MFC(Microsoft Foundation Class)是微软开发的一种面向对象的C++框架,用于Windows操作系统的应用程序开发。
MFC消息机制是MFC框架的核心之一,其基本原理是在窗口、控件等对象之间传递消息,以便处理事件和交互。
具体而言,MFC消息机制包括以下几个方面:1.消息循环:MFC使用一个消息循环来接受和处理Windows操作系统发送的Windows消息,处理完消息后将处理结果反馈给Windows操作系统。
2.消息映射:MFC中的控件和窗口都有一个关联的消息映射表,用于将Windows消息映射到应用程序代码中的相应处理函数上。
当某个控件或窗口收到消息后,根据消息类型在相应的消息映射表中查找对应的消息处理函数,并调用相应的处理函数处理消息。
3.消息类型:MFC处理的Windows消息类型包括键盘和鼠标消息、定时器消息、系统负载消息、窗口大小变化消息等等,具体的消息类型可以在MFC框架的文档中查找。
4.消息处理函数:MFC中的消息处理函数是C++成员函数,定义为afx_msg 修饰的函数,Windows消息处理函数命名时需要遵循一定的命名规则,例如OnPaint()函数用于处理绘图事件。
需要注意的是,MFC消息机制是针对Windows操作系统设计的,其他操作系统可能具有不同的消息机制。
此外,MFC框架已经不是微软推荐的最先进的应用程序开发框架,已经逐渐被其他框架和技术所取代,例如.NET Framework,WPF,UWP等。
QT新建一个窗口控制程序以实现添加按钮点击弹出信息提示框为例

QT新建一个窗口控制程序以实现添加按钮点击弹出信息提示框为例为了实现添加按钮点击弹出信息提示框的功能,我们可以使用Qt来创建一个窗口控制程序。
首先,我们需要创建一个Qt窗口应用程序项目。
在Qt Creator中选择"新建项目",然后选择"C++"和"Qt Widgets应用",填写项目名称和路径,然后点击"下一步"。
在下一个界面,可以选择使用预设的窗口模板。
选择一个适合的窗口模板,例如"MainWindow",然后点击"下一步"。
接下来,在"项目管理器"中,展开源文件夹,找到"mainwindow.cpp"文件。
双击打开该文件。
在"mainwindow.cpp"文件中,我们需要添加按钮和相应的点击事件。
如果不存在"MainWindow"类的构造函数,则需要手动创建构造函数。
我们可以在构造函数中添加按钮。
```cpp#include "mainwindow.h"#include "ui_mainwindow.h"#include <QMessageBox>MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)ui->setupUi(this);//创建按钮QPushButton *btn = new QPushButton("添加按钮", this);btn->setGeometry(100, 100, 100, 30);//连接按钮的点击事件到槽函数connect(btn, SIGNAL(clicked(), this, SLOT(showMessageBox());MainWindow::~MainWindowdelete ui;//槽函数:点击按钮弹出信息提示框void MainWindow::showMessageBoxQMessageBox::information(this, "提示", "按钮已点击");```在上面的代码中,我们首先在构造函数中创建了一个按钮,并设置了按钮的位置和尺寸。
MFC学习笔记-窗口创建

MFChierarchy chart(类库列表)MFC与Win321 win32:函数,使用API一步一步搭建应用程序。
(常使用FileView操作)2 MFC编程:实现仍然调用API函数,但是是用类封装API函数,使用向导自动生成应用程序框架。
(常使用ClassView操作)2.1需要掌握的技能2.1.1断点调试2.1.2堆栈调用的查看MFC课程内容1 MFC:MFC的六大机制,文档式架构,常用的MFC类,(10--12)。
2 COM(组件对象模型):COM的原理和应用(6)。
3 ADO/Socket:MFC访问数据库以及一些简单的网络编程。
MFC应用程序编程1 MFC的历史:92(VC1)98(VC6)……………………….2 MFC库基础:2.1 MFC库,微软基础类库。
封装了Windows应用程序编程的各种API以及相关机制的C++类库3 类库的相关头文件件★afx-application framework(应用程序框架x)3.1<stdafx.h>-不是类库头文件,是项目的头文件,称为VC下编译的预编译头文件,用来提高编译速度的。
(*.pch)(头文件是不参加编译的但是他参与生成*.pch)3.2<afxwin.h>-几乎包含了各种常用的MFC有文件3.3 <afxext.h>-提供扩展窗口类的支持(创建工具栏,状态栏等………)MFC应用程序的类型1 支持MFC的控制台应用程序(控制台的第四个选项)1.1 多了一个CWinApp(应用程序类,封装类应用程序启动过沉重所涉及到得相关信息)的全局对象(必须有,而且只能有一个)1.2主函数中多了一个AfxWinInit函数,初始化MFC库中的相关信息2 MFC库程序2.1 MFC支持的静态库2.2 MFC支持的动态库2.2.1 MFC规则库(shared MFC DLL)-可以被各种应用程序调用(非MFC程序,没有MFC类也可以调用)★还是有一个CWinApp派生的CMFC_DLLApp类对象2.2.2 MFC扩展库(using shared MFC DLL)-只能被MFC库所编写的应用程序所调用(对原有的MFC类扩展)★DllMain主函数只能被MFC程序调用3 MFC应用程序-----(注意看父类,子类名字可能不一样)3.1单文档视图应用程序★CWinApp 应用程序类★CAboutDlg(对话框-生成关于窗口-和框架没有任何关系)★CMainFrame(父类是:CFrameWnd)(应用程序主框架窗口类-生成应用程序的主框架-负责各个对象的协调工作)★CDocument(它是父类)(文档类-看不到的很重要-管理数据)★CView(它是父类)(视图类-显示数据并和用户进行交互)★CSingleDocApp(父类是CWinApp)-(使用前面的3个类来创建对象)3.2多文档视图架构★CWinApp 应用程序类★CAboutDlg(对话框-生成关于窗口-和框架没有任何关系)★CView(它是父类)(视图类-显示数据并和用户进行交互)★CDocument(它是父类)(文档类-看不到的很重要-管理数据)★CMDIChildWnd(子框架窗口类,父类)★CMDIFrameWnd(主框架窗口类,父类)我们看到的子窗体其实是★CView和★CMDIChildWnd叠加的3.3基于对话框的应用程序★CWinApp 应用程序类★CDialog(对话框窗口类)★★m_pMainWnd保存主窗口地址DoModal 显示对话框MFC相关类的说明1继承自CObject1.1 CObject类:绝大多数MFC类的父类,提供了MFC库的一些机制1 new/delete操作符,定义了与构造函数相关的内存分配函数2 assert和dump调试,堆调试的支持★3 运行时类信息-属于哪个类,还有类的层次结构★4 动态创建★5 序列化1.2 CWinThread: 线程类。
mfc窗口创建过程

mfc窗口创建过程
MFC窗口的创建过程包括以下几个步骤:
1. 定义窗口类:首先需要定义一个派生自CWnd类的窗口类,该类是窗口的实例。
可以在应用程序的头文件中声明该类,并在源文件中实现其成员函数。
2. 注册窗口类:在应用程序的初始化阶段,需要调用AfxRegisterClass函数来注册窗口类,该函数会将窗口类的信息添加到注册表中。
3. 创建窗口:在初始化阶段,还需要创建窗口实例。
可以通过调用Create函数来创建一个新的窗口。
在调用Create函数之前,需要设置一些窗口的属性,如标题、大小、样式等。
4. 响应消息:窗口创建后,会进入一个消息循环。
在消息循环中,窗口会不断接收和处理消息。
可以通过覆盖窗口类的OnXXX函数来响应不同的消息,如OnPaint函数来处理窗口绘制消息。
5. 显示窗口:当窗口创建并响应消息后,需要调用ShowWindow 函数来显示窗口。
可以通过传入SW_SHOW参数来显示窗口。
以上就是MFC窗口的创建过程,通过这些步骤可以创建和管理窗口的实例,并实现窗口的功能。
cwnd类内容详解

cwnd类内容详解cwnd类提供了微软基础类库中所有窗口类的基本功能。
cwnd对象与windows的窗口不同,但是两者有紧密联系。
cwnd对象是由cwnd的构造函数和析构函数创建或销毁的。
另一方面,windows的窗口是windows的一种内部数据结构,它是由cwnd的create成员函数创建的,而由cwnd的虚拟析构函数销毁。
destroywindow函数销毁windows的窗口,但是不销毁对象。
cwnd类和消息映射机制隐藏了wndproc函数。
接收到的windows通知消息通过消息映射被自动发送到适当的cwnd onmessage成员函数。
你可以在派生类中重载onmessage成员函数以处理成员的特定消息。
cwnd类同时还使你能够为应用程序创建windows的子窗口。
先从cwnd继承一个类,然后在派生类中加入成员变量以保存与你的应用程序有关的数据。
在派生类中实现消息处理成员函数和消息映射,以指定当消息被发送到窗口时应该如何动作。
你可以经过两个步骤来创建一个子窗口。
首先,调用构造函数cwnd以创建一个cwnd 对象,然后调用create成员函数以创建子窗口并将它连接到cwnd对象。
当用户关闭你的子窗口时,应销毁cwnd对象,或者调用destroywindow成员函数以清除窗口并销毁它的数据结构。
在微软基础类库中,从cwnd派生了许多其它类以提供特定的窗口类型。
这些类中有许多,包括cframewnd,cmdiframewnd,cmdichildwnd,cview和cdialog,被用来进一步派生。
从cwnd派生的控件类,如cbutton,可以被直接使用,也可以被进一步派生出其它类来。
#include <afxwin.h>请参阅:cframewnd, cviewcwnd类的成员坐标映射函数onenteridle 调用这个函数以通知应用程序的主窗口过程,模式对话框或菜单正在进入空闲状态onerasebkgnd 当需要擦除窗口的背景时调用这个函数ongetminmaxinfo 每当windows需要知道最大化的位置和大小,或者最小或最大跟踪尺寸时,就调用这个函数oniconerasebkgnd 当cwnd被最小化(图标化),并且在画出图标之前,必须填充图标的背景时调用这个函数onkillfocus 当cwnd失去输入焦点时立即调用这个函数onmenuchar 当用户按下一个菜单助记字符,但是不能与当前菜单中任何预定义的助记符相匹配时,就调用这个函数onmenuselect 当用户选择了一个菜单项时就调用这个函数onmove 当cwnd的位置发生变化时调用这个函数onmoving 指明用户正在移动cwnd对象ondevicechange 通知应用程序或设备驱动程序,设备或计算机的其他硬件配置发生了变化onstylechanged 指明windows的::setwindowlong函数已经改变了一个或多个窗口风格onstylechanging 指明windows的::setwindowlong函数将要改变一个或多个窗口风格onpaint 调用这个函数以重画窗口的一部分onparentnotify 当创建或销毁一个子窗口,或者当用户在子窗口上方点击了鼠标键时调用这个函数onquerydragicon 当一个最小化(图标化)的cwnd要被用户拖拉时就调用这个函数onqueryendsession 当用户选择结束windows会话时就调用这个函数onquerynewpalette 通知cwnd它将接收输入焦点onqueryopen 当cwnd是一个图标并且用户请求打开这个图标时就调用这个函数一般消息处理函数。
MFC动态按钮的创建及其消息响应(自定义消息)

MFC动态按钮的创建及其消息响应(⾃定义消息)动态按钮(多个)的创建:1、在类中声明并定义按钮控件的ID#define IDC_D_BTN 100002、在类的OnInitDialog()函数中动态创建按钮(建⽴按钮对象时最好建⽴对象的指针)3、⼿动释放对象指针下⾯是动态⽣成多个按钮的例⼦:CButton* btn = new CButton[5];DWORD dwStyle = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON;for(int i = 0; i < 5; i++){btn[i].Create(_T("动态按钮"), dwStyle,CRect(20+80*i,20,80+80*i,60),this,IDC_D_BTN+i);}注:Create()的第⼀个参数为按钮的标题,可直接给出(如上所⽰),也可在String Table中先定义字符串,再利⽤控件的LoadString()函数将字符串读取进来程序运⾏效果如下所⽰:动态按钮(多个)的消息响应: ⼀个MFC的消息响应函数在程序中有三处相关信息:函数原型、函数实现以及⽤来关联消息和消息响应函数的宏。
头⽂件中在两个AFX_MSG注释宏之间是消息响应函数原型的声明。
源⽂件中有两处:⼀处是在AFX_MSG_MAP注释宏之间的消息映射宏,⽤来关联消息和消息响应函数的宏;另⼀处是源⽂件中的消息响应函数的实现代码。
下⾯为动态⽣成的多个按钮的消息响应的建⽴步骤:1、在对话框类的定义⽂件(.h⽂件)中声明消息响应函数OnButtonClickafx_msg void OnButtonClick(UINT uID);注:OnButtonClick函数的参数nID代表响应函数对应按钮控件的ID号,单个按钮可不设参数2、在对话框类的函数实现⽂件(.cpp⽂件)中定义消息映射ON_COMMAND_RANGE (多个按钮) 在函数实现⽂件中的消息映射部分(BEGIN_MESSAGE_MAP与END_MESSAGE_MAP之间)定义按钮控件与其消息响应函数之间的映射关系。
MFC之模态与非模态对话框的创建与销毁

的话,则把消息返回到WindowProc()函数,由它将消息发送给DefWindowProc()函数;
5、OnCommand() 该函数查看这是不是一个控件通知(lParam参数不为NULL,如果lParam参数为空的话,说明该消息不是控件通知),如果它是,OnCommand()函数会试图将消
======================================================================
MFC非模态窗口的创建过程:
1、PreCreateWindow() 该函数是一个重载函数,在窗口被创建前,可以在该重载函数中改变创建参数 (可以设置窗口风格等);
5、PostNcDestroy() 重载函数,作为处理OnNcDestroy()函数的最后动作被CWnd调用。
##############################################################################
附:MFC应用程序中处理消息的顺序
6、OnSetFont() 消息响应函数,响应WM_SETFONT消息,发送此消息,以允许改变对话框中控件的字体;
7、OnInitDialog() 源自 消息响应函数,响应WM_INITDIALOG消息,发送此消息以允许初始化对话框中的控件,或者是创建新控件;
8、OnShowWindow() 消息响应函数,响应WM_SHOWWINDOW消息,该函数被ShowWindow()函数调用;
8、OnMove() 消息响应函数,响应WM_MOVE消息,发送此消息说明窗口在移动;
9、OnChildNotify() 该函数为重载函数,作为部分消息映射被调用,告诉父窗口即将被告知一个窗口刚刚被创建。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
进入MFC讲坛的前言 2008-02-14 10:53:59分类:WINDOWSMFC中的窗口创建及窗口消息映射我经常碰到有人问我有关窗口创建的问题,他们经常把用HWND描述的系统窗口对象和用CWnd描述的MFC的窗口对象混淆不清。
这两者之间是紧密联系在一起的,但是MFC为了自身的管理,在CWnd中加了一些额外的内容,包括如何从HWND生成CWnd。
在MFC中,有几种典型的窗口对象,CWnd描述的一般窗口对象,CView描述的视图对象,CFrameWnd描述的SDI框窗对象,CMDIFrameWnd描述的MDI框窗对象等等。
在这一章中,主要讨论下述内容:MFC中窗口的创建MFC的消息映射机制(MESSAGE MAP)对于上面两点MFC的设计者们使用了很高的技巧来确保应用程序的代码尽可能小,其中的技巧和隐藏在它们背后的思想值得我们学习。
下面对各项内容进行讨论。
MFC中窗口的创建在Window下,创建窗口可以使用两个函数,CreateWindow()和CreateWindowEx(),它们都需要一个参数,这个参数是标识窗口类的字符串。
所以,如果要创建窗口,一般的做法是,先使用RegisterClass()或RegisterClassEx()注册一个窗口类,然后使用该窗口类来创建窗口。
在前面我也提到过,注册窗口类的最主要目的是为系统提供窗口函数的地址,以便被DispatchMessage()之类的函数回。
在MFC中,创建窗口的函数是CWnd或其派生类的Create()或CreateEx方法,注册窗口类一般使用AfxRegisterWndClass(),在这个全局函数中,并没有发现窗口函数地址这样的参数,因此脑子里自然就会有这样的问题:窗口函数在哪里?它是如何同窗口关联的?下面我们将对MFC的一些与此有关的代码进行仔细分析,回答上述两个问题。
窗口函数在MFC中,有一个全局的函数AfxWndProc(),正如下面的注释所示,它就是CWnd及所有从它派生的窗口类的窗口函数,它的实现如下:// The WndProc for all CWnd's and derived classesLRESULT CALLBACKAfxWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam){// special message which identifies the window as using AfxWndProcif (nMsg == WM_QUERYAFXWNDPROC)return 1;// all other messages route through message mapCWnd* pWnd = CWnd::FromHandlePermanent(hWnd);ASSERT(pWnd != NULL);ASSERT(pWnd->m_hWnd == hWnd);return AfxCallWndProc(pWnd, hWnd, nMsg, wParam, lParam);}AfxCallWndProc()调用pWnd对象的虚拟函数WindowProc(),它的代码如下:LRESULT CWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam){// OnWndMsg does most of the work, except for DefWindowProc callLRESULT lResult = 0;if (!OnWndMsg(message, wParam, lParam, &lResult))lResult = DefWindowProc(message, wParam, lParam);return lResult;}上面的代码中,OnWndMsg()是用来处理该窗口消息的函数,如果某条消息没有被OnWndMsg()处理,也就是该窗口没有提供处理该消息的函数,它就调用DefWindowProc()进行处理,DefWindowProc()也是一个虚拟函数,看看它的代码:LRESULT CWnd::DefWindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam){if (m_pfnSuper != NULL)return ::CallWindowProc(m_pfnSuper, m_hWnd, nMsg, wParam, lParam);WNDPROC pfnWndProc;if ((pfnWndProc = *GetSuperWndProcAddr()) == NULL)return ::DefWindowProc(m_hWnd, nMsg, wParam, lParam);elsereturn ::CallWindowProc(pfnWndProc, m_hWnd, nMsg, wParam, lParam);}DefWindowProc()的策略很简单,调用基类的窗口函数m_pfnSuper来处理该消息。
通过上面的分析,可以得出这样的结论:与其说AfxWndProc()是MFC的唯一窗口函数,还不如说AfxWndProc()是MFC的窗口消息分发中心。
正是由于有了这个消息分发中心,才使得MFC的应用程序能够用有限的几个窗口类,作出各种形形色色的窗口,使得在应用程序中,增加CWnd的派生类,并不增加系统中窗口类的个数,将对系统资源的使用控制在一个稳定的范围之内。
注册窗口类除了提供窗口函数外,还指定该窗口的一些外观,如是否有标题条,窗口缺省背景等等。
在MFC框架中,有框窗、视图和控制条(CControlBar)等,它们除了操作行为不同外,外观等也不相同,所以MFC注册了几种缺省的窗口类。
在MFC中,有一个全局函数AfxEndDeferRegisterClass(LONG fToRegister),它用来注册MFC预定义的窗口类,包括同框窗、视图所对应的窗口类。
由于它的代码占的篇幅很长,而且实现也很简单,所以就不列出它的代码了,如果你有兴趣,可以在wincore.cpp中找到它的实现代码。
挂接窗口函数如果你考察过AfxEndDeferRegisterClass()的实现代码,你会对一行代码感到迷惑,下面列出的是AfxEndDeferRegisterClass()的部分代码,带阴影部分的是那一行令人迷惑的代码:BOOL AFXAPI AfxEndDeferRegisterClass(LONG fToRegister){。
wndcls.lpfnWndProc = DefWindowProc;。
}MFC将所有预定义的窗口类的窗口函数都设置成DefWindowProc。
大家都知道,DefWindowProc是Window下为一般窗口提供消息缺省处理的API,它肯定不是应用程序所需要的窗口函数,所以,MFC肯定在某个地方置换了它,置换DefWindowProc的代码在哪里呢?前面说过,在MFC中创建窗口时是用CWnd的两个虚拟函数Create()和CreateEx(),Create()是通过调用CreateEx()实现的,所以最终窗口的创建都要归结到CreateEx()函数上。
因此,我们可以推断MFC在CreateEx()中置换了DefWindowProc。
为了证实这一点,看看CWnd::CreateEx()的代码:BOOL CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName,LPCTSTR lpszWindowName, DWORD dwStyle,int x, int y, int nWidth, int nHeight,HWND hWndParent, HMENU nIDorHMenu, LPVOID lpParam){// allow modification of several common create parametersCREATESTRUCT cs;cs.dwExStyle = dwExStyle;cs.lpszClass = lpszClassName;cs.lpszName = lpszWindowName;cs.style = dwStyle;cs.x = x;cs.y = y;cs.cx = nWidth;cs.cy = nHeight;cs.hwndParent = hWndParent;cs.hMenu = nIDorHMenu;cs.hInstance = AfxGetInstanceHandle();cs.lpCreateParams = lpParam;if (!PreCreateWindow(cs)){PostNcDestroy();return FALSE;}AfxHookWindowCreate(this);HWND hWnd = ::CreateWindowEx(cs.dwExStyle, cs.lpszClass,cs.lpszName, cs.style, cs.x, cs.y, cs.cx, cs.cy,cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams);if (!AfxUnhookWindowCreate()) PostNcDestroy(); // cleanup if CreateWindowEx fails too soonif (hWnd == NULL) return FALSE;ASSERT(hWnd == m_hWnd); // should have been set in send msg hookreturn TRUE;}从上面的代码看不出任何显式的置换DefWindowProc的代码,其实,它隐藏在AfxHookWindowCreate(this)之中,顺藤摸瓜,再看看AfxHookWindowCreate()的代码:void AFXAPI AfxHookWindowCreate(CWnd* pWnd){_AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();if (pThreadState->m_pWndInit == pWnd)return;if (pThreadState->m_hHookOldCbtFilter == NULL){pThreadState->m_hHookOldCbtFilter = ::SetWindowsHookEx(WH_CBT,_AfxCbtFilterHook, NULL, ::GetCurrentThreadId());if (pThreadState->m_hHookOldCbtFilter == NULL)AfxThrowMemoryException();}ASSERT(pThreadState->m_hHookOldCbtFilter != NULL);ASSERT(pWnd != NULL);ASSERT(pWnd->m_hWnd == NULL); // only do onceASSERT(pThreadState->m_pWndInit == NULL); // hook not already in progresspThreadState->m_pWndInit = pWnd;}AfxHookWindowCreate()设置了一个线程级的CBT Hook,该Hook的入口地址为_AfxCbtFilterHook,_AfxCbtFilterHook是一个全局的MFC函数,_AfxCbtFilterHook通过调用SetWindowLong()用AfxWndProc()的入口地址置换掉DefWindowProc。