⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 subclasswnd.h

📁 用VC實現截取Window的消息
💻 H
📖 第 1 页 / 共 3 页
字号:
/** @file SubclassWnd.h
 *
 * Definition of CSubclassWnd.h.
 *
 * @author William E. Kempf
 * @version 2.0
 *
 * Copyright &copy 2000 NEWare Software.
 *
 * This code may be used in compiled form in any way you desire (including
 * commercial use). The code may be redistributed unmodified by any means providing
 * it is not sold for profit without the authors written consent, and providing that
 * this notice and the authors name and all copyright notices remains intact. However,
 * this file and the accompanying source code may not be hosted on a website or bulletin
 * board without the authors written permission.
 *
 * <b><i>This software is provided "as is" without express or implied warranty. Use it
 * at your own risk!</i></b>
 */

#if !defined(_SUBCLASSWND_H_199B246E_AE5D_11D3_A459_000629B2F85_INCLUDED_)
#define _SUBCLASSWND_H_199B246E_AE5D_11D3_A459_000629B2F85_INCLUDED_

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000

/**
 * Pluggable window message handler.
 *
 * This class can be used to "subclass" a window in the C API sense of the term.
 * It is a base class, meant to be derived from.  Derived classes should provide
 * an interface that will call CSubclassWnd::SubclassWindow in order to hook into
 * a window's message handling interface.  Typically this will be done in the
 * derived's constructor and the OnFinalMessage method will be overriden to delete
 * the object's instance (delete this).
 */

class CSubclassWnd
{
private:
	class WndProcThunk
	{
	public:
#if defined(_M_IX86)
#pragma pack(push,1)
		struct Thunk
		{
			DWORD   m_mov;          // mov dword ptr [esp+0x4], pThis (esp+0x4 is hWnd)
			DWORD   m_this;         //
			BYTE    m_jmp;          // jmp WndProc
			DWORD   m_relproc;      // relative jmp
		};
#pragma pack(pop)
#elif defined (_M_ALPHA)
	// For ALPHA we will stick the this pointer into a0, which is where
	// the HWND is.  However, we don't actually need the HWND so this is OK.
#pragma pack(push,4)
		struct Thunk //this should come out to 20 bytes
		{
			DWORD ldah_at;      //  ldah    at, HIWORD(func)
			DWORD ldah_a0;      //  ldah    a0, HIWORD(this)
			DWORD lda_at;       //  lda     at, LOWORD(func)(at)
			DWORD lda_a0;       //  lda     a0, LOWORD(this)(a0)
			DWORD jmp;          //  jmp     zero,(at),0
		};
#pragma pack(pop)
#else
#error Only Alpha and X86 supported
#endif

		Thunk thunk;

		void Init(WNDPROC proc, void* pThis)
		{
#if defined (_M_IX86)
			thunk.m_mov = 0x042444C7;  //C7 44 24 0C
			thunk.m_this = (DWORD)pThis;
			thunk.m_jmp = 0xe9;
			thunk.m_relproc = (int)proc - ((int)this+sizeof(Thunk));
#elif defined (_M_ALPHA)
			thunk.ldah_at = (0x279f0000 | HIWORD(proc)) + (LOWORD(proc)>>15);
			thunk.ldah_a0 = (0x261f0000 | HIWORD(pThis)) + (LOWORD(pThis)>>15);
			thunk.lda_at = 0x239c0000 | LOWORD(proc);
			thunk.lda_a0 = 0x22100000 | LOWORD(pThis);
			thunk.jmp = 0x6bfc0000;
#endif
			// write block from data cache and
			//  flush from instruction cache
			FlushInstructionCache(GetCurrentProcess(), &thunk, sizeof(thunk));
		}
	};

protected:
	CSubclassWnd();
	virtual ~CSubclassWnd();

	virtual BOOL ProcessWindowMessage(UINT message, WPARAM wParam, LPARAM lParam,
		LRESULT& lResult);
	virtual void OnFinalMessage();

	LRESULT DefWindowProc();
	LRESULT DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam);

#ifdef _MFC_VER
	BOOL SubclassWindow(CWnd* pWnd, BOOL bReflect=TRUE);
#endif
	BOOL SubclassWindow(HWND hWnd, BOOL bReflect=TRUE);
	HWND UnsubclassWindow();

public:
	const MSG* GetCurrentMessage() const;

	HWND GetHandle() const;

	LRESULT SendMessage(UINT message, WPARAM wParam=0, LPARAM lParam=0);
	BOOL PostMessage(UINT message, WPARAM wParam=0, LPARAM lParam=0);
	void SendMessageToDescendants(UINT message, WPARAM wParam, LPARAM lParam,
		BOOL bDeep=TRUE);

private:
	static LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam,
		LPARAM lParam);

private:
	WndProcThunk m_thunk;
	WNDPROC m_pfnSuperWindowProc;
	const MSG* m_pCurrentMsg;
	HWND m_hWnd;
};

#ifdef	_MFC_VER
/**
 * Called to subclass the specified window.  If the @a bReflect
 * parameter is TRUE then the parent window will be subclassed to
 * support message reflection.
 *
 * @param pWnd [in] Points to the CWnd to be subclassed.
 * @param bReflect [in] Specifies whether or not the parent should
 *		reflect messages back to the window.
 *
 * @return TRUE if successful; otherwise FALSE.
 */

inline BOOL CSubclassWnd::SubclassWindow(CWnd* pWnd, BOOL bReflect)
{
	return SubclassWindow(pWnd->GetSafeHwnd(), bReflect);
}
#endif

/**
 * Retrieves a pointer to the "current" MSG structure being handled.
 *
 * @return Returns a pointer to the "current" MSG structure being handled.
 */
inline const MSG* CSubclassWnd::GetCurrentMessage() const
{
	return m_pCurrentMsg;
}

/**
 * Calls the "default" window procedure with the current message.  The
 * "default" procedure is what ever procedure was subclassed by this
 * class.
 *
 * @return The return value is the result of the message processing and
 *		depends on the message.
 */

inline LRESULT CSubclassWnd::DefWindowProc()
{
	const MSG* pMsg = m_pCurrentMsg;
	LRESULT lRes = 0;
	if (pMsg != NULL)
		lRes = DefWindowProc(pMsg->message, pMsg->wParam, pMsg->lParam);
	return lRes;
}

/**
 * Calls the "default" window procedure with the specified message.  The
 * "default" procedure is what ever procedure was subclassed by this
 * class.
 *
 * @param message [in] Specifies the message id.
 * @param wParam [in] Specifies additional message-specific information.
 * @param lParam [in] Specifies additional message-specific information.
 *
 * @return The return value is the result of the message processing and
 *		depends on the message.
 */
inline LRESULT CSubclassWnd::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
#ifdef STRICT
	return ::CallWindowProc(m_pfnSuperWindowProc, m_hWnd, message, wParam, lParam);
#else
	return ::CallWindowProc((FARPROC)m_pfnSuperWindowProc, m_hWnd, message, wParam, lParam);
#endif
}

/**
 * Called to get the handle of the subclassed window.
 *
 * @return The handle to the currently subclassed window.
 */

inline HWND CSubclassWnd::GetHandle() const
{
	return m_hWnd;
}

/**
 * Sends a message to the subclassed window.
 *
 * @param message [in] Specifies the message id.
 * @param wParam [in] Specifies additional message-specific information.
 * @param lParam [in] Specifies additional message-specific information.
 *
 * @return The return value is the result of the message processing and
 *		depends on the message.
 */

inline LRESULT CSubclassWnd::SendMessage(UINT message, WPARAM wParam, LPARAM lParam)
{
	return ::SendMessage(GetHandle(), message, wParam, lParam);
}

/**
 * Posts a message to the subclassed window.
 *
 * @param message [in] Specifies the message id.
 * @param wParam [in] Specifies additional message-specific information.
 * @param lParam [in] Specifies additional message-specific information.
 *
 * @return If the function succeeds, the return value is nonzero. If the
 *		function fails, the return value is zero. To get extended error
 *		information, call GetLastError. 
 */

inline BOOL CSubclassWnd::PostMessage(UINT message, WPARAM wParam, LPARAM lParam)
{
	return ::PostMessage(GetHandle(), message, wParam, lParam);
}

template <typename T>
struct DISPATCH_TRAITS
{
	typedef T type;
};

/** @def BEGIN_MSG_DISPATCH(className, rootClass)
 *
 * Begins the message dispatch map.
 */
#define	BEGIN_MSG_DISPATCH(className, rootClass)	\
	virtual BOOL ProcessWindowMessage(UINT message, WPARAM wParam, \
		LPARAM lParam, LRESULT& lResult) {	\
		typedef DISPATCH_TRAITS<##rootClass>::type root_type;	\
		if (FALSE) ;
/**
 * Ends the message dispatch map.
 */
#define	END_MSG_DISPATCH()	\
		return root_type::ProcessWindowMessage(message, wParam, lParam, lResult); }

/**
 * Dispatches a message to a member function from within the message map.  If you
 * want to dispatch a user define message you must declare a dispatch macro
 * for it.  See the header file <b>SubclassWnd.h</b> for examples of how to declare
 * such macros.
 */
#define DISPATCH_MSG(msg, mfn)    \
	else if (message == msg)  { lResult = DISPATCH_##msg((wParam), (lParam), (mfn)); return TRUE; }

/* void Class::OnCompacting(UINT compactRatio) */
#define DISPATCH_WM_COMPACTING(wParam, lParam, fn) \
    ((fn)((UINT)(wParam)), 0L)

/* void Class::OnWinIniChange(LPCTSTR lpszSectionName) */
#define DISPATCH_WM_WININICHANGE(wParam, lParam, fn) \
    ((fn)((LPCTSTR)(lParam)), 0L)

/* void Class::OnSysColorChange() */
#define DISPATCH_WM_SYSCOLORCHANGE(wParam, lParam, fn) \
    ((fn)(), 0L)

/* BOOL Class::OnQueryNewPalette() */
#define DISPATCH_WM_QUERYNEWPALETTE(wParam, lParam, fn) \
    MAKELRESULT((BOOL)(fn)(), 0L)

/* void Class::OnPaletteIsChanging(HWND hwndPaletteChange) */
#define DISPATCH_WM_PALETTEISCHANGING(wParam, lParam, fn) \
    ((fn)((HWND)(wParam)), 0L)

/* void Class::OnPaletteChanged(HWND hwndPaletteChange) */
#define DISPATCH_WM_PALETTECHANGED(wParam, lParam, fn) \
    ((fn)((HWND)(wParam)), 0L)

⌨️ 快捷键说明

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