在《
多标签视图类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
春秋十二月 阅读(2274)
评论(0) 编辑 收藏 引用 所属分类:
C/C++