一个简单的子类化窗口工具类
在《多标签视图类CTabView的设计实现》:http://www.2cto.com/kf/201112/113805.html 一文中,CTabView从CBasicSubClassWnd私有继承,重写其虚函数SubWindowProc,捕获WM_DRAWITEM和TTN_GETDISPINFO消息,从而实现了DrawItem和UpdateTooltipText虚函数回调机制,支持派生类的自定义处理,而CBasicSubClassWnd就是一个子类化窗口类,其原理很简单,就是挂钩替换目标窗口的消息处理过程,这里的设计实现为对于同一目标窗口,可以被多个CBasicSubClassWnd对象捕获消息,而一个CBasicSubClassWnd对象只能捕获一个目标窗口的消息,SubWindowProc返回值决定了消息是否被传递到下个CBasicSubClassWnd对象或原窗口过程处理,TRUE表示允许消息被传递,否则,反之。CBasicSubClassWnd类基于api + stl实现,简单易用,但不尽完善,比如没考虑支持不同进程间的窗口捕获、类的线程安全性等,这些东西都有待于进一步的解决。下面直接看看它的实现代码
1//basic_subclasswnd.h
2
3#ifndef _BASIC_SUBCLASSWND_H
4#define _BASIC_SUBCLASSWND_H
5
6#include <map>
7#include <list>
8
9class CBasicSubClassWnd
10{
11 friend class CBasicWndInfo;
12
13public:
14 CBasicSubClassWnd();
15 void Hook(HWND hWnd);
16 void Unhook();
17
18protected:
19 virtual BOOL SubWindowProc(UINT msg,WPARAM wParam,LPARAM lParam);
20
21private:
22 HWND m_hWnd;
23};
24
25class CBasicWndInfo
26{
27 typedef std::list<CBasicSubClassWnd*> CBasicSubClassWndList;
28 friend class CBasicSubClassWnd;
29
30private:
31 CBasicWndInfo(HWND hWnd);
32 void Add(CBasicSubClassWnd* pHandler);
33 void Remove(CBasicSubClassWnd* pHandler);
34 void RemoveAll();
35
36 typedef std::map<HWND,CBasicWndInfo> CBasicSubClassWndMap;
37 typedef CBasicSubClassWndMap::iterator MapIter;
38
39 static CBasicSubClassWndMap& GetHookMap();
40 static LRESULT HookWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
41
42 CBasicSubClassWndList m_list_scw;
43 WNDPROC m_oldWndProc;
44 HWND m_hWnd;
45};
46
47#endif
48
49//basic_subclasswnd.cpp
50#include "stdafx.h"
51#include "basic_subclasswnd.h"
52using namespace std;
53
54CBasicSubClassWnd::CBasicSubClassWnd()
55:m_hWnd(NULL)
56{
57}
58
59void CBasicSubClassWnd::Hook(HWND hWnd)
60{
61 assert(hWnd);
62 if (m_hWnd&&m_hWnd!=hWnd)
63 Unhook();
64 m_hWnd = hWnd;
65
66 CBasicWndInfo::MapIter iter = CBasicWndInfo::GetHookMap().find(hWnd);
67 if (iter==CBasicWndInfo::GetHookMap().end())
68 {
69 iter = CBasicWndInfo::GetHookMap().insert(make_pair(hWnd,CBasicWndInfo(hWnd))).first;
70 }
71 iter->second.Add(this);
72}
73
74void CBasicSubClassWnd::Unhook()
75{
76 assert(m_hWnd);
77
78 CBasicWndInfo::MapIter iter = CBasicWndInfo::GetHookMap().find(m_hWnd);
79 if (iter==CBasicWndInfo::GetHookMap().end())
80 return;
81 iter->second.Remove(this);
82}
83
84BOOL CBasicSubClassWnd::SubWindowProc(UINT msg,WPARAM wParam,LPARAM lParam)
85{
86 return TRUE;
87}
88
89//////////////////////////////////////////////////////////////////////////////////////////////
90CBasicWndInfo::CBasicWndInfo(HWND hWnd)
91:m_oldWndProc(NULL)
92,m_hWnd(hWnd)
93{
94}
95
96void CBasicWndInfo::Add(CBasicSubClassWnd* pHandler)
97{
98 if (NULL==m_oldWndProc)
99 {
100 m_oldWndProc = (WNDPROC)SetWindowLong(m_hWnd,GWL_WNDPROC,(LONG)HookWndProc);
101 }
102 m_list_scw.push_back(pHandler);
103}
104
105void CBasicWndInfo::Remove(CBasicSubClassWnd* pHandler)
106{
107 m_list_scw.remove(pHandler);
108 if (m_list_scw.empty())
109 {
110 assert(m_hWnd);
111 SetWindowLong(m_hWnd,GWL_WNDPROC,(LONG)m_oldWndProc);
112 }
113}
114
115void CBasicWndInfo::RemoveAll()
116{
117 m_list_scw.clear();
118}
119
120CBasicWndInfo::CBasicSubClassWndMap& CBasicWndInfo::GetHookMap()
121{
122 static CBasicSubClassWndMap s_map;
123 return s_map;
124}
125
126LRESULT CBasicWndInfo::HookWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
127{
128 MapIter iter = GetHookMap().find(hWnd);
129 if (uMsg==WM_NCDESTROY)
130 {
131 //iter->second.RemoveAll();
132 }
133 else
134 {
135 CBasicSubClassWndList::iterator it;
136 for (it=iter->second.m_list_scw.begin();it!=iter->second.m_list_scw.end();++it)
137 {
138 if (!(*it)->SubWindowProc(uMsg,wParam,lParam))
139 return 0;
140 }
141 }
142 return ::CallWindowProc(iter->second.m_oldWndProc,hWnd,uMsg,wParam,lParam);
143}
摘自 天道酬勤