diff --git a/.clang-format b/.clang-format index 48949df..847c9ec 100644 --- a/.clang-format +++ b/.clang-format @@ -46,7 +46,7 @@ AllowAllArgumentsOnNextLine: true # 如果false,强制把函数参数每个换 AllowAllParametersOfDeclarationOnNextLine: true # 如果false,强制把函数形参每个换行 AllowBreakBeforeNoexceptSpecifier: Always # 是否允许复合noexcept换行 Never|OnlyWithParen AllowShortBlocksOnASingleLine: Always # WIN Always, Empty|Never -AllowShortCaseLabelsOnASingleLine: true # WIN true, false +AllowShortCaseLabelsOnASingleLine: false # WIN true, false AllowShortCompoundRequirementOnASingleLine: true # BTW true, false AllowShortEnumsOnASingleLine: true # WIN true, false AllowShortFunctionsOnASingleLine: All # WIN All, None|InlineOnly|Empty|Inline diff --git a/CMakeLists.txt b/CMakeLists.txt index 10125be..460bcd7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,7 +18,16 @@ enable_testing() add_executable(${PROJECT_NAME} main.cpp def.h InteractManager.cpp - InteractManager.h) + InteractManager.h + Renderer.cpp + Renderer.h + Game.cpp + Game.h + Window.cpp + Window.h + Hud.cpp + Hud.h + includes.h) set(CPACK_PROJECT_NAME ${PROJECT_NAME}) set(CPACK_PROJECT_VERSION ${PROJECT_VERSION}) include(CPack) diff --git a/Game.cpp b/Game.cpp new file mode 100644 index 0000000..d9b697c --- /dev/null +++ b/Game.cpp @@ -0,0 +1,5 @@ +// +// Created by EmsiaetKadosh on 25-1-14. +// + +#include "Game.h" diff --git a/Game.h b/Game.h new file mode 100644 index 0000000..85e6790 --- /dev/null +++ b/Game.h @@ -0,0 +1,33 @@ +// +// Created by EmsiaetKadosh on 25-1-14. +// + +#pragma once + +#include "Hud.h" +#include "InteractManager.h" +#include "Renderer.h" +#include "Window.h" + +class Game { + Hud hud = Hud(); + Window* window = nullptr; + +public: + explicit Game() = default; + + void render() const noexcept { + if (window) window->render(); + hud.render(); + } + + void setWindow(Window* window) noexcept { + if (this->window == window) return; + if (this->window) this->window->onClose(); + this->window = nullptr; + if (window && window->onOpen()) + this->window = window; + } +}; + +inline static Game game = Game(); diff --git a/Hud.cpp b/Hud.cpp new file mode 100644 index 0000000..7a0a998 --- /dev/null +++ b/Hud.cpp @@ -0,0 +1,7 @@ +// +// Created by EmsiaetKadosh on 25-1-14. +// + +#include "Hud.h" + +void Hud::render() const noexcept {} diff --git a/Hud.h b/Hud.h new file mode 100644 index 0000000..f309118 --- /dev/null +++ b/Hud.h @@ -0,0 +1,12 @@ +// +// Created by EmsiaetKadosh on 25-1-14. +// + +#pragma once +#include "Renderer.h" + +class Hud : public Renderable { +public: + void render() const noexcept override; +}; + diff --git a/InteractManager.h b/InteractManager.h index 588dd36..b314e1b 100644 --- a/InteractManager.h +++ b/InteractManager.h @@ -5,6 +5,7 @@ #pragma once #include "def.h" +#include "hbp.h" struct KeyStatus { String name; @@ -26,13 +27,22 @@ struct KeyStatus { struct KeyBinding; class InteractManager { + inline static TRACKMOUSEEVENT trackMouseEvent{ + .cbSize = sizeof(TRACKMOUSEEVENT), + .dwFlags = TME_HOVER | TME_LEAVE | TME_NONCLIENT, + .hwndTrack = nullptr, + .dwHoverTime = 0 + }; KeyStatus keyStatus[256]; int mouseX = 0, mouseY = 0; int mouseWheel = 0; int rebindResult = 0; bool rebinding = false; - bool inWindow = false; // 鼠标是否在窗口内部 + bool inWindow = false;// 鼠标是否在窗口内部 + bool hovering = false; + public: + static void initialize() noexcept { trackMouseEvent.hwndTrack = MainWindowHandle; } explicit InteractManager(); void update(const int keyCode, const bool isPressed) noexcept { @@ -51,14 +61,29 @@ public: void updateMouse(const int x, const int y) noexcept { mouseX = x; mouseY = y; - std::wcout << x << " " << y << std::endl; + inWindow = true; + hovering = false; + if (!TrackMouseEvent(&trackMouseEvent)) std::wcout << L"TrackMouseEvent failed. LastError: " << GetLastError() << std::endl; + } + + void mouseHover() noexcept { + hovering = true; + inWindow = true; + std::wcout << L"hover" << std::endl; + } + + void mouseLeave() noexcept { + inWindow = false; + hovering = false; + std::wcout << L"leave" << std::endl; } void updateWheel(const int wheel) noexcept { mouseWheel += wheel; } - [[nodiscard]] int getMouseX() const noexcept { return mouseX; } [[nodiscard]] int getMouseY() const noexcept { return mouseY; } [[nodiscard]] int getMouseWheel() const noexcept { return mouseWheel; } + [[nodiscard]] bool isHovering() const noexcept { return hovering; } + [[nodiscard]] bool isInWindow() const noexcept { return inWindow; } KeyStatus& getKey(const int keyCode) noexcept { return keyStatus[keyCode]; } KeyStatus& getKey(const KeyBinding& binding) noexcept; diff --git a/Renderer.cpp b/Renderer.cpp new file mode 100644 index 0000000..4a63515 --- /dev/null +++ b/Renderer.cpp @@ -0,0 +1,7 @@ +// +// Created by EmsiaetKadosh on 25-1-14. +// + +#include "Renderer.h" + +void Renderer::initialize() noexcept { MainDC = GetDC(MainWindowHandle); } diff --git a/Renderer.h b/Renderer.h new file mode 100644 index 0000000..799abd0 --- /dev/null +++ b/Renderer.h @@ -0,0 +1,31 @@ +// +// Created by EmsiaetKadosh on 25-1-14. +// + +#pragma once + +#include "def.h" + +interface Renderable { + virtual ~Renderable() = default; + virtual void render() const noexcept = 0; +}; + +class Renderer { + inline static HDC MainDC; + int windowWidth = 0, windowHeight = 0; + +public: + static void initialize() noexcept; + explicit Renderer() = default; + + void resize(const int width, const int height) noexcept(false) { + windowWidth = width; + windowHeight = height; + } + + [[nodiscard]] int getWidth() const noexcept { return windowWidth; } + [[nodiscard]] int getHeight() const noexcept { return windowHeight; } +}; + +inline static Renderer renderer = Renderer(); diff --git a/Window.cpp b/Window.cpp new file mode 100644 index 0000000..8d38040 --- /dev/null +++ b/Window.cpp @@ -0,0 +1,5 @@ +// +// Created by EmsiaetKadosh on 25-1-14. +// + +#include "Window.h" diff --git a/Window.h b/Window.h new file mode 100644 index 0000000..64926e2 --- /dev/null +++ b/Window.h @@ -0,0 +1,27 @@ +// +// Created by EmsiaetKadosh on 25-1-14. +// + +#pragma once + +#include "Renderer.h" + +class Window : public Renderable { +protected: + Window() = default; + +public: + /** + * 在Game.setWindow()时,本窗口开启时调用。 + * 不应当外部调用。 + * 如果返回false,则拒绝设置窗口。 + * @return 是否允许将显示窗口设为自身 + */ + virtual bool onOpen() = 0; + /** + * 在Game.setWindow()时,本窗口关闭时调用。 + * 不应当外部调用。 + * 注意,关闭未必就是删除。 + */ + virtual void onClose() = 0; +}; diff --git a/hbp.h b/hbp.h index bb4d142..8d21ccb 100644 --- a/hbp.h +++ b/hbp.h @@ -2,7 +2,6 @@ #include "def.h" - inline BOOL NewProcess(const String& cmdline) noexcept { STARTUPINFOW si = { sizeof(si), nullptr, nullptr, nullptr, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, nullptr, nullptr, nullptr, nullptr @@ -13,7 +12,7 @@ inline BOOL NewProcess(const String& cmdline) noexcept { return CreateProcessW(nullptr, const_cast(cmdline.c_str()), nullptr, nullptr, 0, 0, nullptr, nullptr, &si, &pi); } -inline HRESULT RemoveDefaultCaption(HWND const hWnd, const MARGINS* p) noexcept { return DwmExtendFrameIntoClientArea(hWnd, p); } +inline HRESULT RemoveDefaultCaption(HWND hWnd, const MARGINS* p) noexcept { return DwmExtendFrameIntoClientArea(hWnd, p); } inline void ShowConsoleIO() noexcept { AllocConsole(); @@ -26,7 +25,3 @@ inline void ShowConsoleIO() noexcept { inline const String ApplicationName = L"Hyblud Presher"; inline HINSTANCE MainInstance; inline HWND MainWindowHandle; - -inline void Initialize() {} - -inline void Finalize() {} diff --git a/includes.h b/includes.h new file mode 100644 index 0000000..39ae2b3 --- /dev/null +++ b/includes.h @@ -0,0 +1,15 @@ +// +// Created by EmsiaetKadosh on 25-1-14. +// + +#pragma once + +#include "def.h" +#include "hbp.h" +#include "Renderer.h" +#include "InteractManager.h" + +#include "Hud.h" +#include "Window.h" + +#include "Game.h" diff --git a/main.cpp b/main.cpp index fcefc1d..dda43e7 100644 --- a/main.cpp +++ b/main.cpp @@ -1,47 +1,85 @@ -#include "hbp.h" -#include "InteractManager.h" +#include "includes.h" LRESULT __stdcall WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { _LIKELY case WM_PAINT: { PAINTSTRUCT ps; - HDC hdc = BeginPaint(hwnd, &ps);// Paint caption + BeginPaint(hwnd, &ps); EndPaint(hwnd, &ps); break; } _LIKELY case WM_NCHITTEST: { + POINT point = { GET_X_LPARAM(lParam), (GET_Y_LPARAM(lParam)) }; + ScreenToClient(hwnd, &point); + const int xPos = point.x; + const int yPos = point.y; + if (xPos < 30) { + if (yPos < 30) return HTTOPLEFT; + if (renderer.getHeight() - yPos < 30) return HTBOTTOMLEFT; + return HTLEFT; + } + if (renderer.getWidth() - xPos < 30) { + if (yPos < 30) return HTTOPRIGHT; + if (renderer.getHeight() - yPos < 30) return HTBOTTOMRIGHT; + return HTBOTTOM; + } + if (yPos < 30) return HTTOP; + if (renderer.getHeight() - yPos < 30) return HTBOTTOM; + if (yPos < 240) return HTCAPTION; LRESULT lr = 0; - BOOL r = DwmDefWindowProc(hwnd, uMsg, wParam, lParam, &lr); + DwmDefWindowProc(hwnd, uMsg, wParam, lParam, &lr); return HTCLIENT; } - case WM_KEYDOWN: interactManager.update(static_cast(wParam), true); + case WM_KEYDOWN: + interactManager.update(static_cast(wParam), true); break; - case WM_KEYUP: interactManager.update(static_cast(wParam), false); + case WM_KEYUP: + interactManager.update(static_cast(wParam), false); break; - case WM_SYSKEYDOWN: interactManager.update(static_cast(wParam), true); + case WM_SYSKEYDOWN: + interactManager.update(static_cast(wParam), true); break; - case WM_SYSKEYUP: interactManager.update(static_cast(wParam), false); + case WM_SYSKEYUP: + interactManager.update(static_cast(wParam), false); break; - case WM_LBUTTONDOWN: interactManager.update(VK_LBUTTON, true); + case WM_LBUTTONDOWN: + interactManager.update(VK_LBUTTON, true); break; - case WM_RBUTTONDOWN: interactManager.update(VK_RBUTTON, true); + case WM_RBUTTONDOWN: + interactManager.update(VK_RBUTTON, true); break; - case WM_LBUTTONUP: interactManager.update(VK_LBUTTON, false); + case WM_LBUTTONUP: + interactManager.update(VK_LBUTTON, false); break; - case WM_RBUTTONUP: interactManager.update(VK_RBUTTON, false); + case WM_RBUTTONUP: + interactManager.update(VK_RBUTTON, false); break; - case WM_MOUSEMOVE: interactManager.updateMouse(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); + case WM_MOUSEMOVE: + interactManager.updateMouse(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); break; - case WM_MBUTTONDOWN: if (wParam & 0x10) interactManager.update(VK_MBUTTON, true); + case WM_MBUTTONDOWN: + if (wParam & 0x10) interactManager.update(VK_MBUTTON, true); break; - case WM_MBUTTONUP: interactManager.update(VK_MBUTTON, false); + case WM_MBUTTONUP: + interactManager.update(VK_MBUTTON, false); break; - case WM_MOUSEWHEEL: interactManager.update(VK_MBUTTON, true); + case WM_MOUSEWHEEL: + interactManager.update(VK_MBUTTON, true); + interactManager.update(VK_MBUTTON, true); break; - case WM_COMMAND: std::wcout << L"WM_COMMAND" << std::endl; + case WM_MOUSEHOVER: + // case WM_NCMOUSEHOVER: + interactManager.mouseHover(); + break; + case WM_MOUSELEAVE: + // case WM_NCMOUSELEAVE: + interactManager.mouseLeave(); + break; + case WM_COMMAND: + std::wcout << L"WM_COMMAND" << std::endl; break; case WM_DWMCOMPOSITIONCHANGED: { MARGINS margins{ @@ -50,10 +88,11 @@ LRESULT __stdcall WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { .cyTopHeight = 0, .cyBottomHeight = 0 }; - HRESULT hr = RemoveDefaultCaption(hwnd, &margins); + RemoveDefaultCaption(hwnd, &margins); break; } - case WM_NCCALCSIZE: if (wParam == 1) { + case WM_NCCALCSIZE: + if (wParam == 1) { NCCALCSIZE_PARAMS* pncsp = reinterpret_cast(lParam); pncsp->rgrc[0].left = pncsp->rgrc[0].left + 0; pncsp->rgrc[0].top = pncsp->rgrc[0].top + 0; @@ -61,15 +100,19 @@ LRESULT __stdcall WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { pncsp->rgrc[0].bottom = pncsp->rgrc[0].bottom - 0; return 0; } - case WM_SIZE: switch (wParam) { + case WM_SIZE: { + renderer.resize(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); + switch (wParam) { case SIZE_RESTORED: case SIZE_MINIMIZED: case SIZE_MAXIMIZED: case SIZE_MAXSHOW: case SIZE_MAXHIDE: - default: break; + default: + break; } break; + } case WM_ACTIVATE: { constexpr MARGINS margins{ .cxLeftWidth = 0, @@ -81,20 +124,22 @@ LRESULT __stdcall WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { } break; _UNLIKELY - case WM_DESTROY: PostQuitMessage(0); + case WM_DESTROY: + PostQuitMessage(0); return 0; _UNLIKELY - case WM_CREATE: SetWindowPos(hwnd, nullptr, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER);// Force post NCCALCSIZE + case WM_CREATE: + SetWindowPos(hwnd, nullptr, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER);// Force post NCCALCSIZE + break; + default: break; - default: break; } return DefWindowProc(hwnd, uMsg, wParam, lParam); } int __stdcall wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) { - AllocConsole(); - freopen("CONOUT$", "w", stdout); - WNDCLASSEX wc = { 0 }; + ShowConsoleIO(); + WNDCLASSEX wc = {}; wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; @@ -111,8 +156,9 @@ int __stdcall wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCm MainInstance = hInstance; MainWindowHandle = CreateWindowExW(0, wc.lpszClassName, wc.lpszClassName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, nullptr, nullptr, hInstance, nullptr); ShowWindow(MainWindowHandle, nCmdShow); - Initialize(); - HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(109)); + InteractManager::initialize(); + Renderer::initialize(); + HACCEL hAccelTable = LoadAcceleratorsW(hInstance, MAKEINTRESOURCE(109)); MSG msg = { nullptr }; while (GetMessageW(&msg, nullptr, 0, 0)) { if (!TranslateAcceleratorW(msg.hwnd, hAccelTable, &msg)) {