subclass.h

来自「管理项目进度工具的原代码」· C头文件 代码 · 共 171 行

H
171
字号
////////////////////////////////////////////////////////////////
// 1997 Microsoft Sytems Journal
// If this code works, it was written by Paul DiLascia.
// If not, I don't know who wrote it.
//
#ifndef _SUBCLASSW_H
#define _SUBCLASSW_H

//////////////////
// Generic class to hook messages on behalf of a CWnd.
// Once hooked, all messages go to CSubclassWnd::WindowProc before going
// to the window. Specific subclasses can trap messages and do something.
//
// To use:
//
// * Derive a class from CSubclassWnd.
//
// * Override CSubclassWnd::WindowProc to handle messages. Make sure you call
//   CSubclassWnd::WindowProc if you don't handle the message, or your
//   window will never get messages. If you write seperate message handlers,
//   you can call Default() to pass the message to the window.
//
// * Instantiate your derived class somewhere and call HookWindow(pWnd)
//   to hook your window, AFTER it has been created.
//	  To unhook, call HookWindow(NULL).
//
// This is a very important class, crucial to many of the widgets Window
// widgets implemented in PixieLib. To see how it works, look at the HOOK
// sample program.
//
// heavily modified and extended by .dan.g. abstractspoon

#ifndef GET_X_LPARAM
	#define GET_X_LPARAM(lp)	((int)(short)LOWORD(lp))
	#define GET_Y_LPARAM(lp)	((int)(short)HIWORD(lp))
#endif

class CSubclassWnd;

class ISubclassCallback
{
public:
	virtual void PostNcDestroy(HWND hWnd) = 0;
};

class CSubclassWnd
{
	friend class CSubclassWndMap;
	friend class CSubclasser;

public:
	CSubclassWnd();
	virtual ~CSubclassWnd();

	virtual BOOL HookWindow(HWND hRealWnd, CSubclasser* pSubclasser = NULL);
	virtual BOOL IsValid() const { return IsValidHook(); }

	inline HWND GetHwnd() const { return m_hWndHooked; }
	inline CWnd* GetCWnd() const { return CWnd::FromHandle(m_hWndHooked); }

	static void SetCallback(ISubclassCallback* pCallback) { s_pCallback = pCallback; }

protected:
	HWND			m_hWndHooked;		// the window hooked
	WNDPROC			m_pOldWndProc;		// ..and original window proc
	CSubclassWnd*	m_pNext;			// next in chain of hooks for this window
	CSubclasser*	m_pSubclasser;
	BOOL			m_bPreMFCSubclass;

	static ISubclassCallback* s_pCallback;

protected:
	// this is called only when m_hWndHooked is detached as a result
	// of receiving WM_NCDESTROY else HookWindow(NULL) was called
	virtual void PreDetachWindow() { }
	virtual void PostDetachWindow() { }

	// Subclass a window. Hook(NULL) to unhook (automatic on WM_NCDESTROY)
	virtual BOOL IsHooked() const { return m_hWndHooked != NULL; }
	virtual BOOL IsValidHook() const { return ::IsWindow(m_hWndHooked); }

	inline DWORD GetExStyle() const { return ::GetWindowLong(m_hWndHooked, GWL_EXSTYLE); }
	inline DWORD GetStyle() const { return ::GetWindowLong(m_hWndHooked, GWL_STYLE); }
	inline BOOL HasExStyle(DWORD dwExStyle) const { return (GetExStyle() & dwExStyle) == dwExStyle; }
	inline BOOL HasStyle(DWORD dwStyle) const { return (GetStyle() & dwStyle) == dwStyle; }

	inline HWND GetParent() const { return ::GetParent(m_hWndHooked); }
	inline void GetClientRect(LPRECT pRect) const { ::GetClientRect(m_hWndHooked, pRect); }
	inline void GetWindowRect(LPRECT pRect) const { ::GetWindowRect(m_hWndHooked, pRect); }
	inline void Invalidate(BOOL bErase = TRUE) const { ::InvalidateRect(m_hWndHooked, NULL, bErase); }
	inline BOOL IsWindowEnabled() const { return ::IsWindowEnabled(m_hWndHooked); }
	inline BOOL IsWindowVisible() const { return ::IsWindowVisible(m_hWndHooked); }

	inline UINT GetDlgCtrlID() const { return ::GetDlgCtrlID(m_hWndHooked); }

	void ClientToWindow(LPRECT pRect) const;
	void ScreenToClient(LPRECT pRect) const;
	void ClientToScreen(LPRECT pRect) const;
	void ScreenToWindow(LPRECT pRect) const;
	void ClientToWindow(LPPOINT pPoint) const;
	void ScreenToClient(LPPOINT pPoint) const;
	void ClientToScreen(LPPOINT pPoint) const;
	void ScreenToWindow(LPPOINT pPoint) const;

	void SetRedraw(BOOL bRedraw = TRUE) { ::SendMessage(m_hWndHooked, WM_SETREDRAW, bRedraw, 0); }
	virtual void Redraw() const { Invalidate(); }

	virtual BOOL PostMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) const;
	virtual BOOL SendMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) const;

	static LRESULT CALLBACK HookWndProc(HWND, UINT, WPARAM, LPARAM);

	static CMapPtrToPtr& GetValidMap(); // map containing every CSubclassWnd
	static BOOL IsValid(const CSubclassWnd* pScWnd);

	virtual LRESULT WindowProc(HWND hRealWnd, UINT msg, WPARAM wp, LPARAM lp);
	LRESULT Default(); // call this at the end of handler fns if you are happy with the defaults
	const MSG* GetCurrentMessage();
};

class CSubclasser
{
	friend class CSubclassWnd;
	friend class CSubclassWndMap;

protected:
	CSubclasser() {}

	virtual LRESULT ScWindowProc(HWND hRealWnd, UINT msg, WPARAM wp, LPARAM lp)
	{
		ASSERT(hRealWnd == m_subclass.GetHwnd()); 
		return m_subclass.WindowProc(hRealWnd, msg, wp, lp); 
	}

	virtual CSubclasser* GetTopSubclasser() { return this; }

	// this is called only when m_subclass.m_hWndHooked is detached as a result
	// of receiving WM_NCDESTROY else m_subclass.HookWindow(NULL) was called
	virtual void ScPreDetachWindow() { }
	virtual void ScPostDetachWindow() { }

	// Subclass a window. Hook(NULL) to unhook (automatic on WM_NCDESTROY)
	inline operator HWND() const { return m_subclass.GetHwnd(); }
	inline BOOL ScHookWindow(HWND hWnd) { return m_subclass.HookWindow(hWnd, GetTopSubclasser()); }
	inline BOOL ScIsHooked() { return m_subclass.IsHooked(); }
	inline BOOL ScIsValidHook() { return m_subclass.IsValidHook(); }
	inline CWnd* ScGetCWnd() { return m_subclass.GetCWnd(); }
	inline HWND ScGetHwnd() { return m_subclass.GetHwnd(); }

	inline BOOL ScPostMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0)
		{ return m_subclass.PostMessage(message, wParam, lParam); }

	BOOL ScSendMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0)
		{ return m_subclass.SendMessage(message, wParam, lParam); }

protected:
	CSubclassWnd m_subclass;

protected:
	LRESULT ScDefault(HWND hRealWnd) 
	{ 
		UNREFERENCED_PARAMETER(hRealWnd);
		
		ASSERT(hRealWnd == m_subclass.GetHwnd()); 
		return m_subclass.Default(); 
	} // in time we will have mutiple subclassed wnds
};

#endif // _SUBCLASSW_H

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?