在《
多標(biāo)簽視圖類CTabView的設(shè)計實現(xiàn)》一文中,CTabView從CBasicSubClassWnd私有繼承,重寫其虛函數(shù)SubWindowProc,捕獲WM_DRAWITEM和TTN_GETDISPINFO消息,從而實現(xiàn)了DrawItem和UpdateTooltipText虛函數(shù)回調(diào)機制,支持派生類的自定義處理,而CBasicSubClassWnd就是一個子類化窗口類,其原理很簡單,就是掛鉤替換目標(biāo)窗口的消息處理過程,這里的設(shè)計實現(xiàn)為對于同一目標(biāo)窗口,可以被多個CBasicSubClassWnd對象捕獲消息,而一個CBasicSubClassWnd對象只能捕獲一個目標(biāo)窗口的消息,SubWindowProc返回值決定了消息是否被傳遞到下個CBasicSubClassWnd對象或原窗口過程處理,TRUE表示允許消息被傳遞,否則,反之。CBasicSubClassWnd類基于api + stl實現(xiàn),簡單易用,但不盡完善,比如沒考慮支持不同進程間的窗口捕獲、類的線程安全性等,這些東西都有待于進一步的解決。下面直接看看它的實現(xiàn)代碼
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
春秋十二月 閱讀(2300)
評論(0) 編輯 收藏 引用 所屬分類:
C/C++