|
|
@@ -0,0 +1,111 @@
|
|
|
+#include "Window.h"
|
|
|
+#include "resource.h"
|
|
|
+
|
|
|
+Window::WindowClass Window::WindowClass::wndClass;
|
|
|
+
|
|
|
+Window::WindowClass::WindowClass() noexcept
|
|
|
+ :
|
|
|
+ hInst(GetModuleHandle(nullptr))
|
|
|
+{
|
|
|
+ WNDCLASSEX wc = { 0 };
|
|
|
+ wc.cbSize = sizeof(wc);
|
|
|
+ wc.style = CS_OWNDC;
|
|
|
+ wc.lpfnWndProc = HandleMsgSetup;
|
|
|
+ wc.cbClsExtra = 0;
|
|
|
+ wc.cbWndExtra = 0;
|
|
|
+ wc.hInstance = GetInstance();
|
|
|
+ wc.hIcon = static_cast<HICON>(LoadImage(
|
|
|
+ GetInstance(), MAKEINTRESOURCE(IDI_ICON1),
|
|
|
+ IMAGE_ICON, 32, 32, 0
|
|
|
+ ));
|
|
|
+ wc.hCursor = nullptr;
|
|
|
+ wc.hbrBackground = nullptr;
|
|
|
+ wc.lpszMenuName = nullptr;
|
|
|
+ wc.lpszClassName = GetName();
|
|
|
+ wc.hIconSm = static_cast<HICON>(LoadImage(
|
|
|
+ GetInstance(), MAKEINTRESOURCE(IDI_ICON1),
|
|
|
+ IMAGE_ICON, 16, 16, 0
|
|
|
+ ));
|
|
|
+ RegisterClassEx(&wc);
|
|
|
+}
|
|
|
+
|
|
|
+Window::WindowClass::~WindowClass()
|
|
|
+{
|
|
|
+ UnregisterClass(wndClassName, GetInstance());
|
|
|
+}
|
|
|
+
|
|
|
+const wchar_t* Window::WindowClass::GetName() noexcept
|
|
|
+{
|
|
|
+ return wndClassName;
|
|
|
+}
|
|
|
+
|
|
|
+HINSTANCE Window::WindowClass::GetInstance() noexcept
|
|
|
+{
|
|
|
+ return wndClass.hInst;
|
|
|
+}
|
|
|
+
|
|
|
+Window::Window(int InWidth, int InHeight, const wchar_t* InName) noexcept
|
|
|
+{
|
|
|
+ RECT Wr;
|
|
|
+ Wr.left = 100;
|
|
|
+ Wr.right = InWidth + Wr.left;
|
|
|
+ Wr.top = 100;
|
|
|
+ Wr.bottom = InHeight + 100;
|
|
|
+
|
|
|
+ // AdjustWindowRect 会根据样式重新计算 RECT 中各个参数的值
|
|
|
+ AdjustWindowRect(&Wr, WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU, FALSE);
|
|
|
+
|
|
|
+ // 重新设置过 RECT 参数,所以这里不能直接使用 InWidth 和 InHeight
|
|
|
+ hWnd = CreateWindow(
|
|
|
+ WindowClass::GetName(), InName,
|
|
|
+ WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU,
|
|
|
+ CW_USEDEFAULT, CW_USEDEFAULT, Wr.right - Wr.left, Wr.bottom - Wr.top,
|
|
|
+ nullptr, nullptr, WindowClass::GetInstance(), this
|
|
|
+ );
|
|
|
+
|
|
|
+ ShowWindow(hWnd, SW_SHOWDEFAULT);
|
|
|
+}
|
|
|
+
|
|
|
+Window::~Window()
|
|
|
+{
|
|
|
+ DestroyWindow(hWnd);
|
|
|
+}
|
|
|
+
|
|
|
+LRESULT Window::HandleMsgSetup(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) noexcept
|
|
|
+{
|
|
|
+ // use create parameter passed in from CreateWindow() to store window class pointer at WinAPI side
|
|
|
+ if (msg == WM_NCCREATE)
|
|
|
+ {
|
|
|
+ // extract ptr to window class from creation data
|
|
|
+ const CREATESTRUCTW* const pCreate = reinterpret_cast<CREATESTRUCTW*>(lParam);
|
|
|
+ Window* const pWnd = static_cast<Window*>(pCreate->lpCreateParams);
|
|
|
+ // set WinAPI-managed user data to store ptr to window instance
|
|
|
+ SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pWnd));
|
|
|
+ // set message proc to normal (non-setup) handler now that setup is finished
|
|
|
+ SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(&Window::HandleMsgThunk));
|
|
|
+ // forward message to window instance handler
|
|
|
+ return pWnd->HandleMsg(hWnd, msg, wParam, lParam);
|
|
|
+ }
|
|
|
+ // if we get a message before the WM_NCCREATE message, handle with default handler
|
|
|
+ return DefWindowProc(hWnd, msg, wParam, lParam);
|
|
|
+}
|
|
|
+
|
|
|
+LRESULT Window::HandleMsgThunk(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) noexcept
|
|
|
+{
|
|
|
+ // retrieve ptr to window instance
|
|
|
+ Window* const pWnd = reinterpret_cast<Window*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
|
|
|
+ // forward message to window instance handler
|
|
|
+ return pWnd->HandleMsg(hWnd, msg, wParam, lParam);
|
|
|
+}
|
|
|
+
|
|
|
+LRESULT Window::HandleMsg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) noexcept
|
|
|
+{
|
|
|
+ switch (msg) {
|
|
|
+ case WM_CLOSE:
|
|
|
+ // 不在这里退出窗口,而是发送推出信息给 WinMain, 由 WinMain 来触发 Window 的析构函数 进而关闭窗口
|
|
|
+ PostQuitMessage(0);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ return DefWindowProc(hWnd, msg, wParam, lParam);
|
|
|
+}
|