当前位置:编程学习 > C/C++ >>

一个简单的子类化窗口工具类

在《多标签视图类CTabView的设计实现》:http://www.zzzyk.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}

 摘自 天道酬勤

补充:软件开发 , C语言 ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,