QWindow.h
#pragma once
#define QWIN_DECLARE_MESSAGE_MAP() BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
#define QWIN_BEGIN_MESSAGE_MAP(cls) BOOL cls::ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
#define QWIN_END_MESSAGE_MAP() return FALSE;}
#define QWIN_MESSAGE_MAP(id,fun) if(uMsg==id){return fun(hWnd,uMsg,wParam,lParam);}
#define QWIN_CHAIN_MESSAGE_MAP(id,cls) if(uMsg==id){return cls::ProcessWindowMessage(hWnd,uMsg,wParam,lParam);}
#define QWIN_DECLARE_EMPTY_MSG_MAP() BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){return FALSE;}
#define QWIN_COMMAND_CODE_MAP(code,fun) if(uMsg == WM_COMMAND && code == HIWORD(wParam)){return fun(hWnd,uMsg,wParam,lParam);}
#define QWIN_COMMAND_ID_MAP(id,fun) if(uMsg == WM_COMMAND && id == LOWORD(wParam)){return fun(hWnd,uMsg,wParam,lParam);}
#define QWIN_COMMAND_MAP(id,code,fun) if(uMsg == WM_COMMAND && id == LOWORD(wParam) && code == HIWORD(wParam)){return fun(hWnd,uMsg,wParam,lParam);}
#define QWIN_DECLARE_WND_CLASS(WndClassName) \
public:\
static WNDCLASSEX& GetWndClassInfo() \
{ \
static WNDCLASSEX wc = \
{ \
sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS, (WNDPROC)CQWindow::StartWindowProc, \
0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, WndClassName, NULL \
}; \
return wc; \
}
#define QWIN_DECLARE_WND_SUPER_CLASS(cls,ClassName,WndClassName) \
public: \
WNDPROC cls##ComponentProc; \
public: \
static WNDCLASSEX& GetWndClassInfoEx(cls* c) \
{ \
static WNDCLASSEX wc={0}; \
::GetClassInfoEx(_WinModule.GetInstance(),WndClassName,&wc); \
c->cls##ComponentProc=wc.lpfnWndProc; \
wc.lpfnWndProc = (WNDPROC)CQWindow::StartWindowProc; \
wc.lpszClassName =ClassName; \
wc.cbSize=sizeof(WNDCLASSEX); \
return wc; \
}
#define QWIN_REFLECTION_WND_SUPER_CLASS(cls) else{::CallWindowProc(cls##ComponentProc,hWnd,uMsg,wParam,lParam);return FALSE;}
#pragma pack(push,1)
struct _WndProcThunk
{
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)
class WndProcThunk
{
public:
_WndProcThunk thunk;
void Init(WNDPROC proc, void* pThis)
{
thunk.m_mov = 0x042444C7; //C7 44 24 04
thunk.m_this = (DWORD)pThis;
thunk.m_jmp = 0xe9;
thunk.m_relproc = (int)proc - ((int)this+sizeof(_WndProcThunk));
::FlushInstructionCache(GetCurrentProcess(), &thunk, sizeof(thunk));
}
WNDPROC GetWndProc()
{
return (WNDPROC)&(thunk);
}
};
struct IMessageMap
{
virtual BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)=0;
};
class CQWindow;
class CQWinModule;
extern CQWinModule _WinModule;
class CQWinModule
{
private:
HINSTANCE m_hInst;
CQWindow *m_pWindow;
DWORD m_dwThreadID;
public:
CQWinModule(){m_dwThreadID=::GetCurrentThreadId();}
~CQWinModule(){Term();}
void Init(HINSTANCE hInstance){m_hInst=hInstance;}
void Term(){m_hInst=NULL;}
void SetInstance(HINSTANCE hInstance){Init(hInstance);}
void AddCreateWndData(CQWindow* pWindow){m_pWindow=pWindow;}
HINSTANCE GetInstance(){return m_hInst;}
CQWindow* GetCurrentWindow(){return m_pWindow;}
};
class CQWindow:public IMessageMap
{
public:
CQWindow(void);
~CQWindow(void);
public:
static LRESULT CALLBACK StandardWindowProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
CQWindow* pThis=(CQWindow*)hWnd;
if(uMsg==WM_NCDESTROY)
::PostQuitMessage(0);
if(!pThis->ProcessWindowMessage(pThis->m_hWnd,uMsg,wParam,lParam))
return ::DefWindowProc(pThis->m_hWnd,uMsg,wParam,lParam);
else
return 0;
}
static LRESULT CALLBACK StartWindowProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
CQWindow* pThis=_WinModule.GetCurrentWindow();
pThis->m_hWnd=hWnd;
pThis->thunk.Init(StandardWindowProc,pThis);
WNDPROC proc=pThis->thunk.GetWndProc();
::SetWindowLong(hWnd,GWL_WNDPROC,(LONG)proc);
return proc(hWnd,uMsg,wParam,lParam);
}
public:
BOOL UpdateWindow(void);
BOOL ShowWindow(int cCmd);
virtual LRESULT SendMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
virtual LRESULT PostMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
virtual BOOL Create(LPCTSTR szClassName, LPCTSTR szTitle, HINSTANCE hInstance, HWND hWndParent = 0,
DWORD dwStyle = WS_OVERLAPPEDWINDOW, DWORD dwExStyle = 0, HMENU hMenu = 0,
int x = CW_USEDEFAULT, int y = CW_USEDEFAULT, int nWidth = CW_USEDEFAULT, int nHeight = CW_USEDEFAULT);
virtual BOOL ProcessWindowMessage(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
public:
HWND m_hWnd;
WndProcThunk thunk;
};
template<class TC>class CQWindowImpl :public CQWindow
{
public:
WNDPROC tx;
public:
CQWindowImpl(void){}
public:
~CQWindowImpl(void){}
public:
int RegCls()
{
tx=CQWindow::StartWindowProc;
m_cls=TC::GetWndClassInfo();
PerRegistercls(&m_cls);
return RegisterClassEx(&m_cls);
}
int RegSuperCls()
{
m_cls=TC::GetWndClassInfoEx((TC*)this);
PerRegistercls(&m_cls);
return RegisterClassEx(&m_cls);
}
virtual int PerRegistercls(WNDCLASSEX* cls){return 0;}
public:
WNDCLASSEX m_cls;
WNDPROC m_OldlpfnWndProc;
};
QWindow.cpp
#include "StdAfx.h"
#include "QWindow.h"
CQWinModule _WinModule;
CQWindow::CQWindow(void)
{
}
CQWindow::~CQWindow(void)
{
}
BOOL CQWindow::Create(LPCTSTR szClassName, LPCTSTR szTitle, HINSTANCE hInstance, HWND hWndParent /* = 0 */, DWORD dwStyle /* = WS_OVERLAPPEDWINDOW */, DWORD dwExStyle /* = 0 */, HMENU hMenu /* = 0 */, int x /* = CW_USEDEFAULT */, int y /* = CW_USEDEFAULT */, int nWidth /* = CW_USEDEFAULT */, int nHeight /* = CW_USEDEFAULT */)
{
_WinModule.AddCreateWndData(this);
m_hWnd =::CreateWindowEx(dwExStyle, szClassName, szTitle, dwStyle, x, y,
nWidth, nHeight, hWndParent, hMenu, hInstance,NULL);
return m_hWnd != NULL;
}
BOOL CQWindow::UpdateWindow(void)
{
return ::UpdateWindow(m_hWnd);
}
BOOL CQWindow::ShowWindow(int cCmd)
{
return ::ShowWindow(m_hWnd,cCmd);
}
LRESULT CQWindow::SendMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
return ::SendMessage(m_hWnd,uMsg,wParam,lParam);
}
LRESULT CQWindow::PostMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
return ::PostMessage(m_hWnd,uMsg,wParam,lParam);
}
BOOL CQWindow::ProcessWindowMessage(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
return FALSE;
}
分享到:
相关推荐
在实际开发中,Thunk技术不仅限于解决32位和64位兼容性问题,还可以应用于其他场景。例如,在跨线程通信或者异步编程中,Thunk可以作为回调函数的代理,将调用上下文转换为适合异步处理的形式。此外,现代编程语言如...
thunk-redis, 基于 thunk/promise的redis客户端,支持所有redis特性 thunk基于 thunk/promise的redis客户端,支持所有redis特性。 插件实现:thunk RateLimiter 最快的抽象速率限制器。定时队列分布式计时作业队列,...
thunk技术实现窗口类的封装.rtf
最快的基于thunk/promise的redis客户端,支持所有redis功能。thunk-redis最快的基于thunk/promise的redis客户端,支持所有redis功能。 砰实现方式thunk-ratelimiter最快的抽象速率限制器。timed-queue分布式定时作业...
为了解决这个问题,我们可以利用Thunk技术将窗口类的回调函数改写为窗口对象的成员函数,从而更好地封装和管理代码。 首先,让我们理解什么是Thunk。在Windows API中,Thunk是一种用于不同地址空间或不同代码段之间...
x64实现Thunk的新思路,兼容x86,目前能使用的第一份x64下的thunk代码。
在MinGW中,Thunk是一个关键的概念,它是用于在不同调用约定之间转换的代码段,特别是在32位Windows程序中,处理stdcall和cdecl调用约定的转换。 Thunk通常被用于动态库(DLL)中,以便在不同地址空间和调用约定...
在React开发中,Redux是一个非常流行的 state management 库,它帮助我们管理应用的状态。而Redux Thunk 是一个 Redux 的中间件,专门用于处理异步操作,使得在Redux中执行复杂的逻辑变得简单。在这个"redux-thunk ...
Thunk,你懂的,这么简单,就没写示例了。
Thunk经典资料全集,收集几乎所有的Thunk资料。
Thunk v0.4 by intret 是一个C++实现的Thunk技术实例,它提供了一个简单的类,并包含使用示例,帮助开发者理解和应用Thunk技术。 首先,我们要理解什么是Thunk。在Windows编程中,Thunk通常被用来解决32位和64位...
《通用Thunk技术在C语言中的应用——以"toy63r Vc"为例》 Thunk技术,源于汇编语言的概念,通常用于不同编程环境或体系结构间的接口转换。在C语言中,由于其不支持成员函数的this指针,使得在处理对象方法时面临...
在前端开发领域,Redux是一个非常流行的状态管理库,它帮助开发者集中管理应用中的全局状态,使得复杂的单页面应用(SPA)能够保持数据流的一致性和可预测性。本项目"前端项目-redux-thunk.zip"专注于介绍如何在...
**vCO: 另一个基于 Thunk 的 CO 版本** 在JavaScript的世界中,异步编程是不可或缺的一部分,尤其是在处理I/O操作时。传统的回调函数模式由于其“回调地狱”问题,导致代码可读性和可维护性降低。为了解决这个问题...
【标题】"管理系统系列--基于antd、redux-observable、redux-thunk、react-router响应" 提供了一个关于构建管理系统的框架,这个系统利用了现代前端技术栈中的几个关键组件。在这个项目中,开发者采用了一些最流行的...
Hooks Admin 是一个全面的后台管理框架,它充分利用了React18、React-Router V6、Redux、React Hooks、TypeScript以及Vite2等现代前端技术,同时采用了流行的Ant Design UI库,为开发者提供了高效且易用的开发环境。...
总的来说,KWinGUI 1.0界面库是一个致力于简化跨平台GUI开发的工具,其thunk封装技术是实现这一目标的关键,它帮助开发者克服不同平台间API的不一致性,提高代码的可移植性和维护性。对于那些想要为KDE环境或其他...
在现代前端开发中,尤其是在使用Redux进行状态管理时,经常会遇到需要处理异步操作的情况。这些操作可能包括发送网络请求、设置定时器等。然而,Redux的核心设计原则是行动(Action)必须是同步的并且返回一个纯对象...
Redux 的 Thunk 中间件。它允许编写带有内部逻辑的函数,这些函数可以与 Redux 存储的 dispatch 和 getState 方法交互。