📄 atlwin.h
字号:
// 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 _WndProcThunk //this should come out to 36 bytes
{
DWORD ldah3_at; // ldah at, LOWORD((func >> 32))
DWORD sll_at; // sll at, 32, at
DWORD ldah_at; // ldah at, HIWORD(func)
DWORD lda_at; // lda at, LOWORD(func)(at)
DWORD ldah3_a0; // ldah a0, LOWORD((this >> 32))
DWORD sll_a0; // sll a0, 32, a0
DWORD ldah_a0; // ldah a0, HIWORD(this)
DWORD lda_a0; // lda a0, LOWORD(this)(a0)
DWORD jmp; // jmp zero,(at),0
};
#pragma pack(pop)
#else
// 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 _WndProcThunk //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)
#endif
#elif defined (_M_IA64)
#pragma pack(push,8)
extern "C" LRESULT CALLBACK _WndProcThunkProc( HWND, UINT, WPARAM, LPARAM );
struct _FuncDesc
{
void* pfn;
void* gp;
};
struct _WndProcThunk
{
_FuncDesc funcdesc;
void* pRealWndProcDesc;
void* pThis;
};
extern "C" LRESULT CALLBACK _WndProcThunkProc( HWND, UINT, WPARAM, LPARAM );
#pragma pack(pop)
#else
#error Only Alpha, AXP64, IA64, and X86 supported
#endif
class CWndProcThunk
{
public:
union
{
_AtlCreateWndData cd;
_WndProcThunk 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(_WndProcThunk));
#elif defined (_M_ALPHA)
#if defined (_WIN64)
thunk.ldah3_at = (0x239f0000 | LOWORD((ULONG_PTR)proc >> 32));
thunk.sll_at = 0x04B94173C;
thunk.ldah_at = (0x279c0000 | HIWORD((ULONG_PTR)proc)) + (LOWORD((ULONG_PTR)proc)>>15);
thunk.lda_at = 0x239c0000 | LOWORD(proc);
thunk.ldah3_a0 = (0x221f0000 | LOWORD((ULONG_PTR)pThis >> 32));
thunk.sll_a0 = 0x4A041730;
thunk.ldah_a0 = (0x26100000 | HIWORD((ULONG_PTR)pThis)) + (LOWORD((ULONG_PTR)pThis)>>15);
thunk.lda_a0 = 0x22100000 | LOWORD(pThis);
thunk.jmp = 0x6bfc0000;
#else
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
#elif defined (_M_IA64)
_FuncDesc* pFuncDesc;
pFuncDesc = (_FuncDesc*)_WndProcThunkProc;
thunk.funcdesc.pfn = pFuncDesc->pfn;
thunk.funcdesc.gp = &thunk.pRealWndProcDesc; // Set gp up to point to our thunk data
thunk.pRealWndProcDesc = proc;
thunk.pThis = pThis;
#endif
// write block from data cache and
// flush from instruction cache
FlushInstructionCache(GetCurrentProcess(), &thunk, sizeof(thunk));
}
};
/////////////////////////////////////////////////////////////////////////////
// CMessageMap - abstract class that provides an interface for message maps
class ATL_NO_VTABLE CMessageMap
{
public:
virtual BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
LRESULT& lResult, DWORD dwMsgMapID) = 0;
};
/////////////////////////////////////////////////////////////////////////////
// Message map
#define BEGIN_MSG_MAP(theClass) \
public: \
BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID = 0) \
{ \
BOOL bHandled = TRUE; \
hWnd; \
uMsg; \
wParam; \
lParam; \
lResult; \
bHandled; \
switch(dwMsgMapID) \
{ \
case 0:
#define ALT_MSG_MAP(msgMapID) \
break; \
case msgMapID:
#define MESSAGE_HANDLER(msg, func) \
if(uMsg == msg) \
{ \
bHandled = TRUE; \
lResult = func(uMsg, wParam, lParam, bHandled); \
if(bHandled) \
return TRUE; \
}
#define MESSAGE_RANGE_HANDLER(msgFirst, msgLast, func) \
if(uMsg >= msgFirst && uMsg <= msgLast) \
{ \
bHandled = TRUE; \
lResult = func(uMsg, wParam, lParam, bHandled); \
if(bHandled) \
return TRUE; \
}
#define COMMAND_HANDLER(id, code, func) \
if(uMsg == WM_COMMAND && id == LOWORD(wParam) && code == HIWORD(wParam)) \
{ \
bHandled = TRUE; \
lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
if(bHandled) \
return TRUE; \
}
#define COMMAND_ID_HANDLER(id, func) \
if(uMsg == WM_COMMAND && id == LOWORD(wParam)) \
{ \
bHandled = TRUE; \
lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
if(bHandled) \
return TRUE; \
}
#define COMMAND_CODE_HANDLER(code, func) \
if(uMsg == WM_COMMAND && code == HIWORD(wParam)) \
{ \
bHandled = TRUE; \
lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
if(bHandled) \
return TRUE; \
}
#define COMMAND_RANGE_HANDLER(idFirst, idLast, func) \
if(uMsg == WM_COMMAND && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \
{ \
bHandled = TRUE; \
lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
if(bHandled) \
return TRUE; \
}
#define NOTIFY_HANDLER(id, cd, func) \
if(uMsg == WM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom && cd == ((LPNMHDR)lParam)->code) \
{ \
bHandled = TRUE; \
lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
if(bHandled) \
return TRUE; \
}
#define NOTIFY_ID_HANDLER(id, func) \
if(uMsg == WM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom) \
{ \
bHandled = TRUE; \
lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
if(bHandled) \
return TRUE; \
}
#define NOTIFY_CODE_HANDLER(cd, func) \
if(uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code) \
{ \
bHandled = TRUE; \
lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
if(bHandled) \
return TRUE; \
}
#define NOTIFY_RANGE_HANDLER(idFirst, idLast, func) \
if(uMsg == WM_NOTIFY && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \
{ \
bHandled = TRUE; \
lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
if(bHandled) \
return TRUE; \
}
#define CHAIN_MSG_MAP(theChainClass) \
{ \
if(theChainClass::ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult)) \
return TRUE; \
}
#define CHAIN_MSG_MAP_MEMBER(theChainMember) \
{ \
if(theChainMember.ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult)) \
return TRUE; \
}
#define CHAIN_MSG_MAP_ALT(theChainClass, msgMapID) \
{ \
if(theChainClass::ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, msgMapID)) \
return TRUE; \
}
#define CHAIN_MSG_MAP_ALT_MEMBER(theChainMember, msgMapID) \
{ \
if(theChainMember.ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, msgMapID)) \
return TRUE; \
}
#define CHAIN_MSG_MAP_DYNAMIC(dynaChainID) \
{ \
if(CDynamicChain::CallChain(dynaChainID, hWnd, uMsg, wParam, lParam, lResult)) \
return TRUE; \
}
#define END_MSG_MAP() \
break; \
default: \
ATLTRACE2(atlTraceWindowing, 0, _T("Invalid message map ID (%i)\n"), dwMsgMapID); \
ATLASSERT(FALSE); \
break; \
} \
return FALSE; \
}
// Handler prototypes:
// LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
// LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
// LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);
// Empty message map macro
#define DECLARE_EMPTY_MSG_MAP() \
public: \
BOOL ProcessWindowMessage(HWND, UINT, WPARAM, LPARAM, LRESULT&, DWORD) \
{ \
return FALSE; \
}
// Message reflection macros
#define REFLECT_NOTIFICATIONS() \
{ \
bHandled = TRUE; \
lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \
if(bHandled) \
return TRUE; \
}
#define DEFAULT_REFLECTION_HANDLER() \
if(DefaultReflectionHandler(hWnd, uMsg, wParam, lParam, lResult)) \
return TRUE;
/////////////////////////////////////////////////////////////////////////////
// CDynamicChain - provides support for dynamic chaining
class CDynamicChain
{
public:
struct ATL_CHAIN_ENTRY
{
DWORD m_dwChainID;
CMessageMap* m_pObject;
DWORD m_dwMsgMapID;
};
CSimpleArray<ATL_CHAIN_ENTRY*> m_aChainEntry;
CDynamicChain()
{ }
~CDynamicChain()
{
for(int i = 0; i < m_aChainEntry.GetSize(); i++)
{
if(m_aChainEntry[i] != NULL)
delete m_aChainEntry[i];
}
}
BOOL SetChainEntry(DWORD dwChainID, CMessageMap* pObject, DWORD dwMsgMapID = 0)
{
// first search for an existing entry
for(int i = 0; i < m_aChainEntry.GetSize(); i++)
{
if(m_aChainEntry[i] != NULL && m_aChainEntry[i]->m_dwChainID == dwChainID)
{
m_aChainEntry[i]->m_pObject = pObject;
m_aChainEntry[i]->m_dwMsgMapID = dwMsgMapID;
return TRUE;
}
}
// create a new one
ATL_CHAIN_ENTRY* pEntry = NULL;
ATLTRY(pEntry = new ATL_CHAIN_ENTRY);
if(pEntry == NULL)
return FALSE;
pEntry->m_dwChainID = dwChainID;
pEntry->m_pObject = pObject;
pEntry->m_dwMsgMapID = dwMsgMapID;
// search for an empty one
for(i = 0; i < m_aChainEntry.GetSize(); i++)
{
if(m_aChainEntry[i] == NULL)
{
m_aChainEntry[i] = pEntry;
return TRUE;
}
}
// add a new one
BOOL bRet = m_aChainEntry.Add(pEntry);
if(!bRet)
{
delete pEntry;
return FALSE;
}
return TRUE;
}
BOOL RemoveChainEntry(DWORD dwChainID)
{
for(int i = 0; i < m_aChainEntry.GetSize(); i++)
{
if(m_aChainEntry[i] != NULL && m_aChainEntry[i]->m_dwChainID == dwChainID)
{
delete m_aChainEntry[i];
m_aChainEntry[i] = NULL;
return TRUE;
}
}
return FALSE;
}
BOOL CallChain(DWORD dwChainID, HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult)
{
for(int i = 0; i < m_aChainEntry.GetSize(); i++)
{
if(m_aChainEntry[i] != NULL && m_aChainEntry[i]->m_dwChainID == dwChainID)
return (m_aChainEntry[i]->m_pObject)->ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, m_aChainEntry[i]->m_dwMsgMapID);
}
return FALSE;
}
};
/////////////////////////////////////////////////////////////////////////////
// CWndClassInfo - Manages Windows class information
#define DECLARE_WND_CLASS(WndClassName) \
static CWndClassInfo& GetWndClassInfo() \
{ \
static CWndClassInfo wc = \
{ \
{ sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS, StartWindowProc, \
0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, WndClassName, NULL }, \
NULL, NULL, IDC_ARROW, TRUE, 0, _T("") \
}; \
return wc; \
}
#define DECLARE_WND_CLASS_EX(WndClassName, style, bkgnd) \
static CWndClassInfo& GetWndClassInfo() \
{ \
static CWndClassInfo wc = \
{ \
{ sizeof(WNDCLASSEX), style, StartWindowProc, \
0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName, NULL }, \
NULL, NULL, IDC_ARROW, TRUE, 0, _T("") \
}; \
return wc; \
}
#define DECLARE_WND_SUPERCLASS(WndClassName, OrigWndClassName) \
static CWndClassInfo& GetWndClassInfo() \
{ \
static CWndClassInfo wc = \
{ \
{ sizeof(WNDCLASSEX), 0, StartWindowProc, \
0, 0, NULL, NULL, NULL, NULL, NULL, WndClassName, NULL }, \
OrigWndClassName, NULL, NULL, TRUE, 0, _T("") \
}; \
return wc; \
}
/////////////////////////////////////////////////////////////////////////////
// CWinTraits - Defines various default values for a window
template <DWORD t_dwStyle = 0, DWORD t_dwExStyle = 0>
class CWinTraits
{
public:
static DWORD GetWndStyle(DWORD dwStyle)
{
return dwStyle == 0 ? t_dwStyle : dwStyle;
}
static DWORD GetWndExStyle(DWORD dwExStyle)
{
return dwExStyle == 0 ? t_dwExStyle : dwExStyle;
}
};
typedef CWinTraits<WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0> CControlWinTraits;
typedef CWinTraits<WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, WS_EX_APPWINDOW | WS_EX_WINDOWEDGE> CFrameWinTraits;
typedef CWinTraits<WS_OVERLAPPEDWINDOW | WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, WS_EX_MDICHILD> CMDIChildWinTraits;
typedef CWinTraits<0, 0> CNullTraits;
template <DWORD t_dwStyle = 0, DWORD t_dwExStyle = 0, class TWinTraits = CControlWinTraits>
class CWinTraitsOR
{
public:
static DWORD GetWndStyle(DWORD dwStyle)
{
return dwStyle | t_dwStyle | TWinTraits::GetWndStyle(dwStyle);
}
static DWORD GetWndExStyle(DWORD dwExStyle)
{
return dwExStyle | t_dwExStyle | TWinTraits::GetWndExStyle(dwExStyle);
}
};
/////////////////////////////////////////////////////////////////////////////
// CWindowImpl - Implements a window
template <class TBase = CWindow>
class ATL_NO_VTABLE CWindowImplRoot : public TBase, public CMessageMap
{
public:
CWndProcThunk m_thunk;
const MSG* m_pCurrentMsg;
// Constructor/destructor
CWindowImplRoot() : m_pCurrentMsg(NULL)
{ }
~CWindowImplRoot()
{
#ifdef _DEBUG
if(m_hWnd != NULL) // should be cleared in WindowProc
{
ATLTRACE2(atlTraceWindowing, 0, _T("ERROR - Object deleted before window was destroyed\n"));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -