Jackiesteed

www.github.com/jackiesteed

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

为什么要讨论这个问题? 
因为原来的window 所有的设计都是基于c过程的, 没有对象的概念. 
后来大家都开始用c++开始编程, 当然也包括win32客户端开发. 
用c++类封装一个普通窗口, 是c++开发客户端的最开始最基本的问题. 

我们平时不太接触这个问题, 是因为我们基本都是基于某个开发框架写自己的客户端程序的, 比如MFC, WTL, QT等, 甚至包括DuiLib这个小型的皮肤框架. 
这个框架都为我们封装好了, 所以我们其实最开始不需要考虑这个问题(到底c++类是怎么做到封装win32窗口的). 

但是, 随着开发的深入, 你会发现你需要自己封装一个, 比如, 你要自己做一个简版的开发框架. 

下面就简单介绍一下这个问题. 

窗口类大概声明如下. 
class CWndFrame 

public: 
     HWND m_hwnd; 
     LRESULT HandleMessage().  
     void Create();  
}  
其实封装的关键, 就是用类自己的HandleMessage, 替换掉窗口过程. 
或者说, 在窗口过程中, 能任意地调用CWndFrame的函数, 这样就需要把CWndFrame的this指针传递到窗口过程中去. 
 windows在创建窗口的时候, 允许传入一个自定义字段, 而这个字段就是我们可以利用的. 
CWndFrame::Create() 

     m_hWnd = ::CreateWindowEx(dwExStyle, szWindowClass, szTitle, dwStyle, x, y, cx, cy, hwndParent, hMenu, hInst, this); 
    //这里的最后一个参数就是我们传入的this指针.  
}  

 这样, 在窗口过程中, 
处理WM_NCCREATE消息时. 
pThis = static_cast<CBrowserFrame*>(lpcs->lpCreateParams);  
//lparam是CREATESTRUCT的指针, 其中就有我们需要的this指针. 
至于为什么在处理这个消息的时候做这件事, 因为这是消息循环的开始. 
然后 
::SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LPARAM>(pThis));  
把this指针存放在窗口的一个特殊的extra位置GWLP_USERDATA, 这个位置部分用途就是 用来存自定义内容. 
然后, 每次窗口过程启动的时候, 
调用GetWindowLongPtr取出this指针, 然后在窗口过程中调用this->HandleMessage. 

如上, 这样就用窗口类自己的成员函数替换掉了窗口过程.  
  
参考代码如下: 

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam,
    LPARAM lParam)
{

    CBrowserFrame* pThis = NULL;
    if( message == WM_NCCREATE ) {
        LPCREATESTRUCT lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam);
        pThis = static_cast<CBrowserFrame*>(lpcs->lpCreateParams);
        pThis->m_hWnd = hWnd;
        ::SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LPARAM>(pThis));
    } 
    else {
        pThis = reinterpret_cast<CBrowserFrame*>(::GetWindowLongPtr(hWnd, GWLP_USERDATA));
        if( message == WM_NCDESTROY && pThis != NULL ) {

            //By Jackie 2013-10-24 先别动这个代码, 我给注掉了, 貌似没什么影响.
            //除非旧的过程中有特殊调用, 或者GWLP_USERDATA有其他特殊用途

            //LRESULT lRes = ::CallWindowProc(pThis->m_OldWndProc, hWnd, uMsg, wParam, lParam);
            //::SetWindowLongPtr(pThis->m_hWnd, GWLP_USERDATA, 0L);
            //if( pThis->m_bSubclassed ) pThis->Unsubclass();
            //pThis->m_hWnd = NULL;
            //pThis->OnFinalMessage(hWnd);
            return 0;
        }
    }
    if( pThis != NULL ) {
        return pThis->HandleMessage(message, wParam, lParam);
    } 
    else {
        return ::DefWindowProc(hWnd, message, wParam, lParam);
    }

 

posted on 2013-10-24 18:20  Jackiesteed  阅读(1810)  评论(0编辑  收藏  举报