MFC WindowProc AfxWndProc lpfnWndProc

来源:互联网 发布:内网管理软件排名 编辑:程序博客网 时间:2024/06/07 03:16
2010-04-29 11:08
MFC的窗口类(如CWnd)与窗口过程。
Windows是基于事件机制的,任何窗口都能发送和处理消息,每一个窗口都对应着自己的消息处理函数,即通常所说的窗口过程(WindowProc)。窗口过程通常是在WNDCLASSEX的lpfnWndProc变量中指定的,然后调用RegisterClassEx注册窗口类,lpfnWndProc要求是全局的或是类的静态成员,而MFC的窗口和类对象是一一对应的,在类中定义的窗口过程(CWnd::WindowProc)并非类的静态成员,那么窗口消息是怎样传给窗口对象的WindowProc函数去处理的呢?MFC中定义了一个全局的AfxWndProc函数,AfxWndProc是MFC中所有的窗口共用的窗口过程。这里要注意在AfxEndDeferRegisterClass中注册窗口类时并没有把AfxWndProc赋给lpfnWndProc,而是把DefWindowProc赋给了lpfnWndProc。真正把AfxWndProc指定为窗口过程的是在CWnd::CreateEx函数中,CWnd::CreateEx中先后调用了SetWindowsHookEx、CreateWindowEx和UnhookWindowsHookEx,SetWindowsHookEx安装了一个WH_CBT类型的钩子,在调用CreateWindowEx时(在CreateWindowEx返回之前)窗口会发送WM_CREATE、 WM_NCCREATE等消息,钩子过程CBTProc会在窗口消息WM_CREATE、 WM_NCCREATE等发送前被调用,并提前得到窗口的句柄值。钩子过程CBTProc的任务是把窗口句柄赋给窗口对象(CWnd::m_hWnd),并调用SetWindowLong把窗口过程替换成AfxWndProc(如是控件还要保留原窗口过程,用CallWindowProc进行默认处理)。在这有人可能会问,为什么不在AfxEndDeferRegisterClass中直接指定AfxWndProc呢?当然是有原因的:其一是控件的窗口过程必须用SetWindowLong来替换,其二是消息WM_CREATE、 WM_NCCREATE等是在CreateWindowEx返回前发送的,CWnd::WindowProc在处理这些消息时CWnd::m_hWnd必须是已经被初始化的,这个就是由前面的CBTProc完成的。
好现在我们只要关注AfxWndProc了。AfxWndProc是如何把消息分配给各个窗口对象的窗口过程的呢?在MFC中有一个全局的映射表(还没到消息映射,呵呵),这个表是窗口句柄到窗口对象的映射(即通过窗口句柄就能找到窗口对象的地址),找到了窗口对象就可以把消息处理的任务交给CWnd::WindowProc了(调用pWnd- >WindowProc)。
原创粉丝点击