使用子类化截获窗口消息

使用子类化截获窗口消息
   在《 多标签视图类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
  8 class  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
 24 class  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 "
 51 using   namespace  std;
 52
 53 CBasicSubClassWnd::CBasicSubClassWnd()
 54 :m_hWnd(NULL)
 55 {
 56}

 57
 58 void  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
 73 void  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
 83 BOOL CBasicSubClassWnd::SubWindowProc(UINT msg,WPARAM wParam,LPARAM lParam)
 84 {
 85    return TRUE;
 86}

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

 94
 95 void  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
104 void  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
114 void  CBasicWndInfo::RemoveAll()
115 {
116    m_list_scw.clear();
117}

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

124
125 LRESULT 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}
 

你可能感兴趣的:(使用子类化截获窗口消息)