#include "Window.h" #include "Ground.h" Mouse Window::mouse; Window::Window(HWND& hWnd, HINSTANCE& hInstance, int nCmdShow, int x, int y, Logger& logger) { // this struct holds information for the window class WNDCLASSEX wc; // clear out the window class for use ZeroMemory(&wc, sizeof(WNDCLASSEX)); // fill in the struct with the needed information wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = HandleMsgSetup; wc.hInstance = hInstance; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)COLOR_WINDOW; wc.lpszClassName = "WindowClass"; // register the window class RegisterClassEx(&wc); // create rectangle for client area RECT wr = { 0, 0, x, y }; // set the size only, but not the position AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE); // adjust the size // create the window and use the result as the handle hWnd = CreateWindowEx( NULL, "WindowClass", // name of the window class "Oasis Demo", // title of the window WS_OVERLAPPEDWINDOW, // window style 300, // x-position of the window 200, // y-position of the window x, // width of the window y, // height of the window NULL, // we have no parent window, NULL NULL, // we aren't using menus, NULL hInstance, // application handle NULL); // used with multiple windows, NULL // display the window on the screen ShowWindow(hWnd, nCmdShow); // Init graphics pGfx = std::make_unique(hWnd); // Set projection pGfx->SetProjection(DirectX::XMMatrixPerspectiveLH(1.0f, 3.0f / 4.0f, 0.5f, 40.0f)); // Init scenes this->InitScene(logger); } LRESULT CALLBACK 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 // 使用CREATESTRUCT函数的第一个参数lpCreateParams,通过reinterpret_cast,获取到CREATESTRUCT函数的指针 // lpCreateParams的指针和CREATESTRUCT的指针指向同一个物理地址,只是寻址对象不同 const CREATESTRUCTW* const pCreate = reinterpret_cast(lParam); // 取得指向Window的指针 Window* const pWnd = static_cast(pCreate->lpCreateParams); // 将Window类,存储到WinAPI // set WinAPI-managed user data to store ptr to window class SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast(pWnd)); // set message proc to normal (non-setup) handler now that setup is finished SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast(&Window::HandleMsgThunk)); // forward message to window class handler return pWnd->HandleMsg(hWnd, msg, wParam, lParam); } } LRESULT CALLBACK Window::HandleMsgThunk(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) noexcept { // retrieve ptr to window class Window* const pWnd = reinterpret_cast(GetWindowLongPtr(hWnd, GWLP_USERDATA)); // forward message to window class handler return pWnd->HandleMsg(hWnd, msg, wParam, lParam); } LRESULT Window::HandleMsg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) noexcept { POINTS pt; switch (msg) { // we don't want the DefProc to handle this message because // we want our destructor to destroy the window, so return 0 instead of break case WM_CLOSE: PostQuitMessage(0); return 0; case WM_MOUSEMOVE: pt = MAKEPOINTS(lParam); mouse.OnMouseMove(pt.x, pt.y); break; case WM_LBUTTONDOWN: pt = MAKEPOINTS(lParam); mouse.OnLeftClick(pt.x, pt.y); break; case WM_LBUTTONUP: pt = MAKEPOINTS(lParam); mouse.OnleftRelease(pt.x, pt.y); break; case WM_RBUTTONDOWN: pt = MAKEPOINTS(lParam); mouse.OnRightClick(pt.x, pt.y); break; case WM_RBUTTONUP: pt = MAKEPOINTS(lParam); mouse.OnRightRelease(pt.x, pt.y); break; } return DefWindowProc(hWnd, msg, wParam, lParam); } Graphics& Window::GetGfx() { return *pGfx; } void Window::InitScene(Logger &logger) { //Ground ground(*pGfx, logger); pSections.push_back(make_unique(*pGfx, logger)); } void Window::DrawScenes( Graphics& gfx, Logger& logger) noexcept { for (auto& section : pSections) { section->DrawShapes(gfx, logger); } }; void Window::SetTitle(HWND hWnd, const std::string& title) { SetWindowText(hWnd, title.c_str()); }