转载请注明出处: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; }