在《
多标签视图类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
12
public:
13
CBasicSubClassWnd();
14
void Hook(HWND hWnd);
15
void Unhook();
16
17
protected:
18
virtual BOOL SubWindowProc(UINT msg,WPARAM wParam,LPARAM lParam);
19
20
private:
21
HWND m_hWnd;
22
};
23
24
class CBasicWndInfo
25

{
26
typedef std::list<CBasicSubClassWnd*> CBasicSubClassWndList;
27
friend class CBasicSubClassWnd;
28
29
private:
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
}
posted on 2011-12-11 11:07
春秋十二月 阅读(2291)
评论(0) 编辑 收藏 引用 所属分类:
C/C++