随笔-99  评论-224  文章-30  trackbacks-0
   在《多标签视图类CTabView的设计实现》一文中,CTabView从CBasicSubClassWnd私有继承,重写其虚函数SubWindowProc,捕获WM_DRAWITEM和TTN_GETDISPINFO消息,从而实现了DrawItem和UpdateTooltipText虚函数回调机制,支持派生类的自定义处理,而CBasicSubClassWnd就是一个子类化窗口类,其原理很简单,就是挂钩替换目标窗口的消息处理过程,这里的设计实现为对于同一目标窗口,可以被多个CBasicSubClassWnd对象捕获消息,而一个CBasicSubClassWnd对象只能捕获一个目标窗口的消息,SubWindowProc返回值决定了消息是否被传递到下个CBasicSubClassWnd对象或原窗口过程处理,TRUE表示允许消息被传递,否则,反之。CBasicSubClassWnd类基于api + stl实现,简单易用,但不尽完善,比如没考虑支持不同进程间的窗口捕获、类的线程安全性等,这些东西都有待于进一步的解决。下面直接看看它的实现代码
  1//basic_subclasswnd.h
  2#ifndef _BASIC_SUBCLASSWND_H
  3#define _BASIC_SUBCLASSWND_H
  4
  5#include <map>
  6#include <list>
  7
  8class CBasicSubClassWnd
  9{
 10    friend class CBasicWndInfo;
 11
 12public:
 13    CBasicSubClassWnd();
 14    void Hook(HWND hWnd);
 15    void Unhook();
 16
 17protected:
 18    virtual BOOL SubWindowProc(UINT msg,WPARAM wParam,LPARAM lParam);    
 19
 20private:
 21    HWND m_hWnd;
 22}
;
 23
 24class CBasicWndInfo
 25{
 26    typedef std::list<CBasicSubClassWnd*> CBasicSubClassWndList;
 27    friend class CBasicSubClassWnd;
 28
 29private:
 30    CBasicWndInfo(HWND hWnd);
 31    void Add(CBasicSubClassWnd* pHandler);
 32    void Remove(CBasicSubClassWnd* pHandler);
 33    void RemoveAll();
 34
 35    typedef std::map<HWND,CBasicWndInfo> CBasicSubClassWndMap; 
 36    typedef CBasicSubClassWndMap::iterator MapIter;
 37
 38    static CBasicSubClassWndMap& GetHookMap();
 39    static LRESULT HookWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
 40
 41    CBasicSubClassWndList m_list_scw;
 42    WNDPROC m_oldWndProc;
 43    HWND m_hWnd;    
 44}
;
 45
 46#endif
 47
 48//basic_subclasswnd.cpp
 49#include "stdafx.h"
 50#include "basic_subclasswnd.h"
 51using namespace std;
 52
 53CBasicSubClassWnd::CBasicSubClassWnd()
 54:m_hWnd(NULL)
 55{
 56}

 57
 58void CBasicSubClassWnd::Hook(HWND hWnd)
 59{
 60    assert(hWnd);
 61    if (m_hWnd&&m_hWnd!=hWnd)
 62        Unhook();
 63    m_hWnd = hWnd;
 64
 65    CBasicWndInfo::MapIter iter = CBasicWndInfo::GetHookMap().find(hWnd);
 66    if (iter==CBasicWndInfo::GetHookMap().end())
 67    {
 68        iter = CBasicWndInfo::GetHookMap().insert(make_pair(hWnd,CBasicWndInfo(hWnd))).first;
 69    }

 70    iter->second.Add(this);
 71}

 72
 73void CBasicSubClassWnd::Unhook()
 74{
 75    assert(m_hWnd);
 76    
 77    CBasicWndInfo::MapIter iter = CBasicWndInfo::GetHookMap().find(m_hWnd);
 78    if (iter==CBasicWndInfo::GetHookMap().end())
 79        return;
 80    iter->second.Remove(this);
 81}

 82
 83BOOL CBasicSubClassWnd::SubWindowProc(UINT msg,WPARAM wParam,LPARAM lParam)
 84{
 85    return TRUE;
 86}

 87
 88//////////////////////////////////////////////////////////////////////////////////////////////
 89CBasicWndInfo::CBasicWndInfo(HWND hWnd)
 90:m_oldWndProc(NULL)
 91,m_hWnd(hWnd)
 92{
 93}

 94
 95void CBasicWndInfo::Add(CBasicSubClassWnd* pHandler)
 96{
 97    if (NULL==m_oldWndProc)
 98    {
 99        m_oldWndProc = (WNDPROC)SetWindowLong(m_hWnd,GWL_WNDPROC,(LONG)HookWndProc);
100    }

101    m_list_scw.push_back(pHandler);
102}

103
104void CBasicWndInfo::Remove(CBasicSubClassWnd* pHandler)
105{
106    m_list_scw.remove(pHandler);
107    if (m_list_scw.empty())
108    {
109        assert(m_hWnd);
110        SetWindowLong(m_hWnd,GWL_WNDPROC,(LONG)m_oldWndProc);
111    }

112}

113
114void CBasicWndInfo::RemoveAll()
115{
116    m_list_scw.clear();
117}

118
119CBasicWndInfo::CBasicSubClassWndMap& CBasicWndInfo::GetHookMap()
120{
121    static CBasicSubClassWndMap s_map;
122    return s_map;
123}

124
125LRESULT CBasicWndInfo::HookWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
126{    
127    MapIter iter = GetHookMap().find(hWnd);
128    for (CBasicSubClassWndList::iterator it=iter->second.m_list_scw.begin();it!=iter->second.m_list_scw.end();++it)
129    {
130        if (!(*it)->SubWindowProc(uMsg,wParam,lParam))
131            return 0;
132    }

133    return ::CallWindowProc(iter->second.m_oldWndProc,hWnd,uMsg,wParam,lParam);
134}
 
posted on 2011-12-11 11:07 春秋十二月 阅读(1964) 评论(0)  编辑 收藏 引用 所属分类: C/C++

只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理