📄 subclasswnd.h
字号:
/** @file SubclassWnd.h
*
* Definition of CSubclassWnd.h.
*
* @author William E. Kempf
* @version 2.0
*
* Copyright © 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 + -