程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 一個簡單的子類化窗口工具類

一個簡單的子類化窗口工具類

編輯:關於C語言

在《多標簽視圖類CTabView的設計實現》:http://www.BkJia.com/kf/201112/113805.html 一文中,CTabView從CBasicSubClassWnd私有繼承,重寫其虛函數SubWindowProc,捕獲WM_DRAWITEM和TTN_GETDISPINFO消息,從而實現了DrawItem和UpdateTooltipText虛函數回調機制,支持派生類的自定義處理,而CBasicSubClassWnd就是一個子類化窗口類,其原理很簡單,就是掛鉤替換目標窗口的消息處理過程,這裡的設計實現為對於同一目標窗口,可以被多個CBasicSubClassWnd對象捕獲消息,而一個CBasicSubClassWnd對象只能捕獲一個目標窗口的消息,SubWindowProc返回值決定了消息是否被傳遞到下個CBasicSubClassWnd對象或原窗口過程處理,TRUE表示允許消息被傳遞,否則,反之。CBasicSubClassWnd類基於api + stl實現,簡單易用,但不盡完善,比如沒考慮支持不同進程間的窗口捕獲、類的線程安全性等,這些東西都有待於進一步的解決。下面直接看看它的實現代碼

  1//basic_subclasswnd.h
  2
  3#ifndef _BASIC_SUBCLASSWND_H
  4#define _BASIC_SUBCLASSWND_H
  5
  6#include <map>
  7#include <list>
  8
  9class CBasicSubClassWnd
 10{
 11    friend class CBasicWndInfo;
 12
 13public:
 14    CBasicSubClassWnd();
 15    void Hook(HWND hWnd);
 16    void Unhook();
 17
 18protected:
 19    virtual BOOL SubWindowProc(UINT msg,WPARAM wParam,LPARAM lParam);   
 20
 21private:
 22    HWND m_hWnd;
 23};
 24
 25class CBasicWndInfo
 26{
 27    typedef std::list<CBasicSubClassWnd*> CBasicSubClassWndList;
 28    friend class CBasicSubClassWnd;
 29
 30private:
 31    CBasicWndInfo(HWND hWnd);
 32    void Add(CBasicSubClassWnd* pHandler);
 33    void Remove(CBasicSubClassWnd* pHandler);
 34    void RemoveAll();
 35
 36    typedef std::map<HWND,CBasicWndInfo> CBasicSubClassWndMap;
 37    typedef CBasicSubClassWndMap::iterator MapIter;
 38
 39    static CBasicSubClassWndMap& GetHookMap();
 40    static LRESULT HookWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
 41
 42    CBasicSubClassWndList m_list_scw;
 43    WNDPROC m_oldWndProc;
 44    HWND m_hWnd;   
 45};
 46
 47#endif
 48
 49//basic_subclasswnd.cpp
 50#include "stdafx.h"
 51#include "basic_subclasswnd.h"
 52using namespace std;
 53
 54CBasicSubClassWnd::CBasicSubClassWnd()
 55:m_hWnd(NULL)
 56{
 57}
 58
 59void CBasicSubClassWnd::Hook(HWND hWnd)
 60{
 61    assert(hWnd);
 62    if (m_hWnd&&m_hWnd!=hWnd)
 63        Unhook();
 64    m_hWnd = hWnd;
 65
 66    CBasicWndInfo::MapIter iter = CBasicWndInfo::GetHookMap().find(hWnd);
 67    if (iter==CBasicWndInfo::GetHookMap().end())
 68    {
 69        iter = CBasicWndInfo::GetHookMap().insert(make_pair(hWnd,CBasicWndInfo(hWnd))).first;
 70    }
 71    iter->second.Add(this);
 72}
 73
 74void CBasicSubClassWnd::Unhook()
 75{
 76    assert(m_hWnd);
 77   
 78    CBasicWndInfo::MapIter iter = CBasicWndInfo::GetHookMap().find(m_hWnd);
 79    if (iter==CBasicWndInfo::GetHookMap().end())
 80        return;
 81    iter->second.Remove(this);
 82}
 83
 84BOOL CBasicSubClassWnd::SubWindowProc(UINT msg,WPARAM wParam,LPARAM lParam)
 85{
 86    return TRUE;
 87}
 88
 89//////////////////////////////////////////////////////////////////////////////////////////////
 90CBasicWndInfo::CBasicWndInfo(HWND hWnd)
 91:m_oldWndProc(NULL)
 92,m_hWnd(hWnd)
 93{
 94}
 95
 96void CBasicWndInfo::Add(CBasicSubClassWnd* pHandler)
 97{
 98    if (NULL==m_oldWndProc)
 99    {
100        m_oldWndProc = (WNDPROC)SetWindowLong(m_hWnd,GWL_WNDPROC,(LONG)HookWndProc);
101    }
102    m_list_scw.push_back(pHandler);
103}
104
105void CBasicWndInfo::Remove(CBasicSubClassWnd* pHandler)
106{
107    m_list_scw.remove(pHandler);
108    if (m_list_scw.empty())
109    {
110        assert(m_hWnd);
111        SetWindowLong(m_hWnd,GWL_WNDPROC,(LONG)m_oldWndProc);
112    }
113}
114
115void CBasicWndInfo::RemoveAll()
116{
117    m_list_scw.clear();
118}
119
120CBasicWndInfo::CBasicSubClassWndMap& CBasicWndInfo::GetHookMap()
121{
122    static CBasicSubClassWndMap s_map;
123    return s_map;
124}
125
126LRESULT CBasicWndInfo::HookWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
127{   
128    MapIter iter = GetHookMap().find(hWnd);
129    if (uMsg==WM_NCDESTROY)
130    {
131        //iter->second.RemoveAll();
132    }
133    else
134    {
135        CBasicSubClassWndList::iterator it;
136        for (it=iter->second.m_list_scw.begin();it!=iter->second.m_list_scw.end();++it)
137        {
138            if (!(*it)->SubWindowProc(uMsg,wParam,lParam))
139                return 0;
140        }
141    }
142    return ::CallWindowProc(iter->second.m_oldWndProc,hWnd,uMsg,wParam,lParam);
143}

 摘自 天道酬勤

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