#include template class BaseWindow { public: static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { DERIVED_TYPE *pThis = NULL; if (uMsg == WM_NCCREATE) { CREATESTRUCT* pCreate = (CREATESTRUCT*)lParam; pThis = (DERIVED_TYPE*)pCreate->lpCreateParams; SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pThis); pThis->m_hwnd = hwnd; } else { pThis = (DERIVED_TYPE*)GetWindowLongPtr(hwnd, GWLP_USERDATA); } if (pThis) { return pThis->HandleMessage(uMsg, wParam, lParam); } else { return DefWindowProc(hwnd, uMsg, wParam, lParam); } } BaseWindow() : m_hwnd(NULL) { } BOOL Create( PCWSTR lpWindowName, DWORD dwStyle, DWORD dwExStyle = 0, int x = CW_USEDEFAULT, int y = CW_USEDEFAULT, int nWidth = CW_USEDEFAULT, int nHeight = CW_USEDEFAULT, HWND hWndParent = 0, HMENU hMenu = 0 ) { WNDCLASS wc = {0}; wc.lpfnWndProc = DERIVED_TYPE::WindowProc; wc.hInstance = GetModuleHandle(NULL); wc.lpszClassName = ClassName(); RegisterClass(&wc); m_hwnd = CreateWindowEx( dwExStyle, ClassName(), lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, GetModuleHandle(NULL), this ); return (m_hwnd ? TRUE : FALSE); } HWND Window() const { return m_hwnd; } protected: virtual PCWSTR ClassName() const = 0; virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) = 0; HWND m_hwnd; }; class MainWindow : public BaseWindow { public: PCWSTR ClassName() const { return L"Sample Window Class"; } LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); }; int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow) { MainWindow win; if (!win.Create(L"Learn to Program Windows", WS_OVERLAPPEDWINDOW)) { return 0; } ShowWindow(win.Window(), nCmdShow); // Run the message loop. MSG msg = { }; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return 0; } LRESULT MainWindow::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_DESTROY: PostQuitMessage(0); return 0; case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(m_hwnd, &ps); FillRect(hdc, &ps.rcPaint, (HBRUSH) (COLOR_WINDOW+1)); EndPaint(m_hwnd, &ps); } return 0; default: return DefWindowProc(m_hwnd, uMsg, wParam, lParam); } return TRUE; }