Windows为每个窗口都提供了默认的消息处理函数,自定义类的窗口的默认消息处理函数是DefWindowProc,各子窗口控件(见7.1节)的类名是Windows预定义的,其窗口函数自然由Windows提供。
我们的框架也提供了一个通用的消息处理函数AfxWndProc。为了响应窗口消息,必须让Windows把窗口的消息处理函数的地址全设为AfxWndProc,在处理消息时由我们自己决定是否调用默认的消息处理函数。改变窗口消息处理函数地址最简单的办法是使用SetWindowLong函数。比如,下面代码会将句柄为hWnd的窗口的窗口函数地址设为AfxWndProc,并将原来的地址保存在oldWndProc变量中。
WNDPROC oldWndProc = (WNDPROC)::SetWindowLong(hWnd, GWL_WNDPROC, (DWORD)AfxWndProc);
GWL_WNDPROC标记指示了此次调用的目的是设置窗口函数的地址,新的地址由第3个参数AfxWndProc指明。调用成功后,SetWindowLong返回原来窗口函数的地址。以这个地址为参数调用CallWindowProc函数就相当于对消息做了默认处理。
::CallWindowProc(oldWndProc, hWnd, message, wParam, lParam);
以前在注册窗口类的时候,都将一个自定义的函数WndProc的地址传给WNDCLASS 或 WNDCLASSEX 结构,然后在WndProc函数里处理Windows发来的消息。但是,以这种方式创建出来的窗口和标准的子窗口控件有一个明显的区别,就是其窗口函数不是由Windows系统提供的。为了消除这种区别,在注册窗口类时可以直接让API函数DefWindowProc做为窗口函数响应Windows消息,如下面代码所示。
WNDCLASS wndclass;
wndclass.lpfnWndProc = ::DefWindowProc;
... // 其他代码
因此,消息都会被直接发送到默认的消息处理函数,各种窗口处理消息的方式都相同了,我们的框架程序可以使用SetWindowLong和CallWindowProc两个函数对待所有的窗口。