现在的位置: 首页 > 综合 > 正文

Thunk技术封装好的win32项目窗口类

2019年04月19日 ⁄ 综合 ⁄ 共 3334字 ⁄ 字号 评论关闭

转载请注明出处:http://blog.csdn.net/hhhhhhhhhhkkkkkkkkkk/article/details/39613887

由于windows API写窗口有点麻烦而单调,而普通的类成员函数不能用作回调函数,所以在这里发一个用Thunk技术封装好的窗口类,方便调试。里面有部分封装的事件接口,可以根据需要自行扩展。

class MainWindow
{
public:
	HWND m_hWnd;
private:
#pragma pack(push,1)
	struct THUNK
	{
		DWORD m_mov; // = 0x042444C7
		DWORD m_this; // = this
		BYTE m_jmp; // = 0xe9
		DWORD m_relproc; // = relative distance
	}*thunk;
#pragma pack(pop)
public:
	MainWindow() :m_hWnd(NULL){}
	~MainWindow()
	{
		VirtualFree(thunk, sizeof(THUNK), MEM_RELEASE);
	}
	bool Create()
	{
		WNDCLASSEX wcex;
		LPCTSTR lpszClassName = _T("ClassName");
		wcex.cbSize = sizeof(WNDCLASSEX);
		wcex.style = CS_HREDRAW | CS_VREDRAW;
		wcex.lpfnWndProc = MainWindow::TempWndProc;
		wcex.cbClsExtra = 0;
		wcex.cbWndExtra = 0;
		wcex.hInstance = GetModuleHandle(NULL);
		wcex.hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_SMALL));
		wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
		wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
		wcex.lpszMenuName = MAKEINTRESOURCE(IDC_MY);
		wcex.lpszClassName = lpszClassName;
		wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
		RegisterClassEx(&wcex);
		thunk = (THUNK *)VirtualAlloc(NULL, sizeof(THUNK), MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
		thunk->m_mov = 0x042444c7;
		thunk->m_jmp = 0xe9;
		//CreateWindow的最后一个参数为this指针
		CreateWindow(lpszClassName, NULL, WS_OVERLAPPEDWINDOW,
			CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, GetModuleHandle(NULL), this);
		if (m_hWnd == NULL)return false;
		ShowWindow(m_hWnd, SW_SHOW);
		UpdateWindow(m_hWnd);
		///////
		MSG msg;
		HACCEL hAccelTable = LoadAccelerators(GetModuleHandle(NULL), MAKEINTRESOURCE(IDC_MY));
		while (GetMessage(&msg, NULL, 0, 0))
		{
			if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
			{
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}
		}
		return TRUE;
	}
protected:
	//辅助回调函数
	static LRESULT CALLBACK TempWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
	{
		if (message == WM_CREATE)//此处使用WM_NCCREATE消息也可以
		{
			//提取出对象指针
			MainWindow *w = NULL;
			w = (MainWindow*)((LPCREATESTRUCT)lParam)->lpCreateParams;
			w->m_hWnd = hWnd;
			WNDPROC pWndProc = (WNDPROC)w->thunk;
			w->thunk->m_this = (DWORD)w;

			//计算跳转位置
			w->thunk->m_relproc = (DWORD)&MainWindow::StaticWndProc - ((DWORD)w->thunk + sizeof(THUNK));

			SetWindowLong(hWnd, GWL_WNDPROC, (LONG)pWndProc);
			return pWndProc(hWnd, message, wParam, lParam);
		}
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	static LRESULT CALLBACK StaticWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
	{
		return ((MainWindow *)hWnd)->WndProc(message, wParam, lParam);
	}
protected:
	//主回调函数
	virtual LRESULT CALLBACK WndProc(UINT message, WPARAM wParam, LPARAM lParam)
	{
		HDC hdc;
		PAINTSTRUCT ps;
		RECT rect;
		switch (message)
		{
		case WM_CREATE:
			OnCreate();
			break;
		case WM_MOUSEMOVE:
			OnMouseMove(LOWORD(lParam), HIWORD(lParam));
			break;
		case WM_LBUTTONDOWN:
			OnLButtonDown(LOWORD(lParam), HIWORD(lParam));
			break;
		case WM_LBUTTONUP:
			OnLButtonUp(LOWORD(lParam), HIWORD(lParam));
			break;
		case WM_TIMER:
			OnTimer();
			break;
		case WM_PAINT:
			hdc = BeginPaint(m_hWnd, &ps);
			OnPaint(hdc);
			EndPaint(m_hWnd, &ps);
			break;
		case WM_SIZE:
			GetClientRect(m_hWnd, &rect);
			OnSize(rect);
			break;
		case WM_DESTROY:
			PostQuitMessage(0);
			break;
		default:
			return DefWindowProc(m_hWnd, message, wParam, lParam);
			break;
		}
		return TRUE;
	}
public:
	virtual void OnCreate()
	{

	}
	virtual void OnMouseMove(int mouseX, int mouseY)
	{

	}
	virtual void OnLButtonDown(int mouseX, int mouseY)
	{

	}
	virtual void OnLButtonUp(int mouseX, int mouseY)
	{

	}
	virtual void OnTimer()
	{

	}
	virtual void OnPaint(HDC&hdc)
	{

	}
	virtual void OnSize(RECT&rect)
	{

	}

};

调用方式:

int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{

	MainWindow window;
	window.Create();
	return 0;
}



抱歉!评论已关闭.