程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> c++窗口過程封裝的一些實現

c++窗口過程封裝的一些實現

編輯:C++入門知識

如何封裝窗口過程是所有UI庫最核心的設計之一,像MFC/WTL/VCL都各有自己的實現代碼,最終的目標卻是一樣的:將窗口過程轉化為對象的方法,從而把面向過程的Windows轉化為面向對象的方式。這裡要介紹我自己想到兩種實現方式,這些實現都很簡單,但都可以達到同樣的目的。
一、利用窗口的屬性表
基本原理是將窗口句柄和窗口類實例綁定在一起,每個窗口都有自己的屬性表,通過GetProp和SetProp等API操作之,屬性表本質上就是哈希表,通過一個Key快速查找到Value,在這裡Key就是窗口句柄,Value就是窗口類。
另外,我們需要一個自己的標准窗口過程,用來找到與句柄關聯的窗口類,然後再調用窗口類的窗口過程。
先看看實現的代碼:
view plaincopy to clipboardprint?
#ifndef WndHandler_h__  
#define WndHandler_h__  
#include <crtdbg.h>  
#define _WINDOW_CLSATOM  "wndatom"  
class WndHandler  
{  
public:  
    WndHandler(): mDefWndProc(NULL), mHwnd(NULL)  
    {  
    }  
    virtual ~WndHandler()  
    {  
        Unsubclass();  
    }  
    bool Subclass(HWND hwnd)  
    {  
        Unsubclass();  
        _ASSERT(::IsWindow(hwnd));  
        _ASSERT(::GetPropA(hwnd, _WINDOW_CLSATOM) == NULL);  
        mDefWndProc = (WNDPROC)::GetWindowLongW(hwnd, GWL_WNDPROC);  
        if (mDefWndProc == WndHandler::StdWndProc)  
            mDefWndProc = DefWindowProcW;  
        ::SetWindowLongW(hwnd, GWL_WNDPROC, (long)StdWndProc);  
        ::SetPropA(hwnd, _WINDOW_CLSATOM, (HANDLE)this);  
        mHwnd = hwnd;  
        return true;  
    }  
    void Unsubclass()  
    {  
        if (!::IsWindow(mHwnd) || !mDefWndProc)  
            return;  
        ::SetWindowLongW(mHwnd, (LONG)mDefWndProc, GWL_WNDPROC);  
        ::RemovePropA(mHwnd, _WINDOW_CLSATOM);  
        mDefWndProc = NULL;  
        mHwnd = NULL;  
    }  
protected:  
    static LRESULT CALLBACK StdWndProc(HWND hwnd, UINT msg, WPARAM wparam,  LPARAM lparam)  
    {  
        WndHandler* handler = (WndHandler*)GetPropA(hwnd, _WINDOW_CLSATOM);  
        _ASSERT(handler);  
        LRESULT ret = 0;  
        BOOL done = handler->WndProc(hwnd, msg, wparam, lparam, ret);  
        if (done)  
            return ret;  
        else 
            return CallWindowProcW(handler->mDefWndProc, hwnd, msg, wparam, lparam);  
    }  
    virtual BOOL WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, LRESULT& ret)  
    {  
        switch (msg)  
        {  
        case WM_NCDESTROY:  
            {  
                mHwnd = NULL;  
                break;  
            }  
        }  
        return FALSE;  
    }  
protected:  
    WNDPROC     mDefWndProc;  
    HWND        mHwnd;  
};  
#endif // WndHandler_h__ 
#ifndef WndHandler_h__
#define WndHandler_h__
#include <crtdbg.h>
#define _WINDOW_CLSATOM  "wndatom"
class WndHandler
{
public:
    WndHandler(): mDefWndProc(NULL), mHwnd(NULL)
    {
    }
    virtual ~WndHandler()
    {
        Unsubclass();
    }
    bool Subclass(HWND hwnd)
    {
        Unsubclass();
        _ASSERT(::IsWindow(hwnd));
        _ASSERT(::GetPropA(hwnd, _WINDOW_CLSATOM) == NULL);
        mDefWndProc = (WNDPROC)::GetWindowLongW(hwnd, GWL_WNDPROC);
        if (mDefWndProc == WndHandler::StdWndProc)
            mDefWndProc = DefWindowProcW;
        ::SetWindowLongW(hwnd, GWL_WNDPROC, (long)StdWndProc);
        ::SetPropA(hwnd, _WINDOW_CLSATOM, (HANDLE)this);
        mHwnd = hwnd;
        return true;
    }
    void Unsubclass()
    {
        if (!::IsWindow(mHwnd) || !mDefWndProc)
            return;
        ::SetWindowLongW(mHwnd, (LONG)mDefWndProc, GWL_WNDPROC);
        ::RemovePropA(mHwnd, _WINDOW_CLSATOM);
        mDefWndProc = NULL;
        mHwnd = NULL;
    }
protected:
    static LRESULT CALLBACK StdWndProc(HWND hwnd, UINT msg, WPARAM wparam,  LPARAM lparam)
    {
        WndHandler* handler = (WndHandler*)GetPropA(hwnd, _WINDOW_CLSATOM);
        _ASSERT(handler);
        LRESULT ret = 0;
        BOOL done = handler->WndProc(hwnd, msg, wparam, lparam, ret);
        if (done)
            return ret;
        else
            return CallWindowProcW(handler->mDefWndProc, hwnd, msg, wparam

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved