3.2一Wnd窗口基类的设计

来源:互联网 发布:excel2010软件下载 编辑:程序博客网 时间:2024/06/05 09:00
编写面向对象的Windows应用程序并不容易,主要是因为Windows API没有设计为支持面向对象的语言。例如,Windows消息处理函数属于全局函数,该函数中仅仅指明了窗口句柄,但没有指明传入窗口对象指针。同时,C++编译器不允许传入一个普通的成员函数做为回调函数。
我们可以采用一个变通的方法,在回调函数里设置一个虚成员函数,让该虚函数全权处理窗口消息。也就是说,这个虚成员函数成了真正的消息处理函数,之前的回调函数只是一个傀儡。因为C++类的成员函数为每一个函数调用传入一个隐藏的this指针,为实现这一点,回调函数里面需要一个 指向窗口对象的指针。MFC通过一个从HWND到CWnd对象指针的Map映射,把Win32窗口句柄转化为一个指向C++窗口对象的指针。
 上述的解决方法是:在窗口创建完成后,将窗口对象指针保存在窗口类所指定的额外窗口数据结构中,然后回调函数从额外窗口数据结构中取出窗口对象指针,调用成员函数。整个流程图如下:
SetWindowLong函数
函数功能:将窗口对象的this指针保存到窗口所关联的额外空间。
HWND hWnd=::CreateWinodwEx(cs.dwExStyle,cs.lpszClass,cs.lpszName,cs.x,cs.y,cs.cx,cs.cy,cs.hwndParent,cs.hMenu,cs.hInstance,cs.lpCreateParams);assert(hWnd);m_hWnd=hWnd;SetWindowLong(m_hWnd,GWL_USERDATA,(LONG)this);//GWL_USERDATA //获得与窗口有关的32位值。每一个窗口均有一个由创建该窗口的应用程序使用的32位值。


GetWindowLong
函数功能:窗口回调函数从窗口类相关联的额外空间中取出该窗口对象的指针。该对象指针调用一个虚成员函数,将窗口消息路由到WindowProc进行处理。从某种意义上来说,WindowProc成为了WinProc后面的真正执行者。
 
LRESULT CALLBACK QWnd::WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam){QWnd* pWnd=(QWnd*)GetWindowLong(hWnd,GWL_USERDATA); //if(pWnd){return pWnd->WindowProc(uMsg,wParam,lParam);}return ::DefWindowProc(hWnd,uMsg,wParam,lParam);}


WM_CREATE与WM_NCCREATE消息
调用CreateWindowEx后,会紧着调用SetWindowLong将窗口对象指针保存到窗口句柄所指定的额外地址空间中。但该函数调用过程中会产生WM_CREATE和WM_NCCREATE消息,因为在处理这两个消息的过程中还无法从额外的地址空间中获取窗口对象的指针,so这两个消息还无法处理,所以需要另行处理。
this指针的传入
调用CreateWindowEx时,通过产生cs.lpCreateParms将this指针传入
// lpCreateParams 指向将被用于创建窗口的数据的指针
 
WindowProc消息处理

采用虚函数作为消息响应函数,相对于MFC来说:

优点:逻辑清晰,易懂,不需要再去实现消息映射宏。

缺点:虚函数表中需要记录函数的地址指针,每个函数指针占用4个字节,点用内存大。

0 0
原创粉丝点击