关于如何换肤、子类化的解决方案
2010-06-23 20:40:47 来源:WEB开发网我写了一个简化的CWnd类来解决重复子类化问题和简化窗口过程,不过它不支持对自己的重复子类化(即只能用于没有被子类化的或者被CWnd子类化的HWND)。
因为不想弄得和MessageMap那样复杂,所以功能也有限:须手工转化WPARAM和LPARAM、消息处理无法继承、不支持多线程。使用很简单:CWndNew* pWnd = new CWndNew;
pWnd->SubclassWindow(hWnd);
用完了,记得释放处理:
pWnd->UnsubclassWindow();
delete pWnd;
如果要进行功能扩充(继承),就改写那几个虚函数:
class CWndNew
{
public:
CWndNew();
virtual ~CWndNew();
bool SubclassWindow(HWND hWnd);
void UnsubclassWindow();
protected: // virtual
virtual LRESULT WindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
virtual void PresubclassWindow(){};
virtual void PostunsubclassWindow(){};
protected:
LRESULT PrevWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
HWND m_hWnd;
private:
WNDPROC m_oldProc;
static map m_map;
static LRESULT CALLBACK StaticWindowProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
};
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
map CWndNew::m_map;
CWndNew::CWndNew()
{
m_hWnd = NULL;
}
CWndNew::~CWndNew()
{
ASSERT(m_hWnd == NULL);
}
bool CWndNew::SubclassWindow(HWND hWnd)
{
m_map[hWnd] = this;
ASSERT(m_hWnd == NULL);
m_hWnd = hWnd;
//允许派生类在子类化之前做一些初始化.
PresubclassWindow();
m_oldProc = (WNDPROC) GetWindowLong(hWnd, GWL_WNDPROC);
ASSERT(m_oldProc != 0);
SetWindowLong(hWnd, GWL_WNDPROC, (LONG) StaticWindowProc);
return true;
}
void CWndNew::UnsubclassWindow()
{
SetWindowLong(m_hWnd, GWL_WNDPROC, (LONG)m_oldProc);
PostunsubclassWindow();
m_map.erase(m_hWnd);
m_hWnd = NULL;
}
LRESULT CALLBACK CWndNew::StaticWindowProc(HWND hWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
CWndNew* pWnd = m_map[hWnd];
ASSERT(pWnd != NULL);
return pWnd->WindowProc(uMsg, wParam, lParam);
}
LRESULT CWndNew::PrevWindowProc(UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
return CallWindowProc(m_oldProc, m_hWnd, uMsg, wParam, lParam);
}
LRESULT CWndNew::WindowProc(UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
return PrevWindowProc(uMsg, wParam, lParam);
}
更多精彩
赞助商链接