diff --git a/src/Hook.cpp b/src/Hook.cpp index eae8843..15d83e1 100644 --- a/src/Hook.cpp +++ b/src/Hook.cpp @@ -1,9 +1,12 @@ #include #include "Hook.h" +#include "input/MessageHook.h" #include "cdc/render/PCDeviceManager.h" +using namespace std::placeholders; + static bool(*s_D3D_Init)(); static bool D3D_Init() @@ -28,13 +31,27 @@ void Hook::Initialize() MH_EnableHook(MH_ALL_HOOKS); } +void Hook::PostInitialize() +{ + // Create the menu + m_menu = std::make_unique(); + + // Register the message hook + MessageHook::OnMessage(std::bind(&Hook::OnMessage, this, _1, _2, _3, _4)); +} + +void Hook::OnMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + m_menu->OnMessage(hWnd, msg, wParam, lParam); +} + void Hook::OnDevice() { // Assign the DeviceManager instance cdc::PCDeviceManager::s_pInstance = *(cdc::PCDeviceManager**)0xA6669C; - // Creat the menu - m_menu = std::make_unique(); + // Initialize the hook + PostInitialize(); } Hook& Hook::GetInstance() diff --git a/src/Hook.h b/src/Hook.h index f738bc7..37a5ee3 100644 --- a/src/Hook.h +++ b/src/Hook.h @@ -10,6 +10,9 @@ class Hook std::unique_ptr m_menu; void Initialize(); + void PostInitialize(); + + void OnMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); public: Hook(); diff --git a/src/input/Input.cpp b/src/input/Input.cpp new file mode 100644 index 0000000..e68a1dd --- /dev/null +++ b/src/input/Input.cpp @@ -0,0 +1,6 @@ +#include "Input.h" + +void Input::DisableInput(bool disable) +{ + *(bool*)0x8551A9 = disable; +} \ No newline at end of file diff --git a/src/input/Input.h b/src/input/Input.h new file mode 100644 index 0000000..6a8514f --- /dev/null +++ b/src/input/Input.h @@ -0,0 +1,7 @@ +#pragma once + +class Input +{ +public: + static void DisableInput(bool disable); +}; \ No newline at end of file diff --git a/src/input/MessageHook.cpp b/src/input/MessageHook.cpp new file mode 100644 index 0000000..bc30938 --- /dev/null +++ b/src/input/MessageHook.cpp @@ -0,0 +1,24 @@ +#include "MessageHook.h" + +#include "cdc/render/PCDeviceManager.h" + +static std::function s_callback; +static WNDPROC s_original; + +static LRESULT WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + s_callback(hWnd, msg, wParam, lParam); + + return CallWindowProc(s_original, hWnd, msg, wParam, lParam); +} + +void MessageHook::OnMessage(std::function callback) +{ + // Get the window handle + auto hWnd = cdc::PCDeviceManager::s_pInstance->GetWindow(); + + // Set the new message handler to our handler + s_original = (WNDPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)WndProc); + + s_callback = callback; +} \ No newline at end of file diff --git a/src/input/MessageHook.h b/src/input/MessageHook.h new file mode 100644 index 0000000..6d2f9e0 --- /dev/null +++ b/src/input/MessageHook.h @@ -0,0 +1,10 @@ +#pragma once + +#include +#include + +class MessageHook +{ +public: + static void OnMessage(std::function callback); +}; \ No newline at end of file diff --git a/src/input/MouseHook.cpp b/src/input/MouseHook.cpp new file mode 100644 index 0000000..ce3c49d --- /dev/null +++ b/src/input/MouseHook.cpp @@ -0,0 +1,28 @@ +#include +#include + +#include "MouseHook.h" + +static bool s_disabled; +static BOOL(WINAPI* s_SetCursorPos)(int, int); + +BOOL WINAPI SetCursorPosHook(int X, int Y) +{ + if (s_disabled) + { + return TRUE; + } + + return s_SetCursorPos(X, Y); +} + +void MouseHook::Init() +{ + MH_CreateHookApi(L"user32", "SetCursorPos", SetCursorPosHook, (void**)&s_SetCursorPos); + MH_EnableHook(MH_ALL_HOOKS); +} + +void MouseHook::DisableCursorLock(bool disable) +{ + s_disabled = disable; +} \ No newline at end of file diff --git a/src/input/MouseHook.h b/src/input/MouseHook.h new file mode 100644 index 0000000..f7b9700 --- /dev/null +++ b/src/input/MouseHook.h @@ -0,0 +1,8 @@ +#pragma once + +class MouseHook +{ +public: + static void Init(); + static void DisableCursorLock(bool disable); +}; \ No newline at end of file diff --git a/src/menu/Menu.cpp b/src/menu/Menu.cpp index 6ff7c8f..6710dab 100644 --- a/src/menu/Menu.cpp +++ b/src/menu/Menu.cpp @@ -2,11 +2,17 @@ #include #include +#include + #include "Menu.h" #include "render/RenderContext.h" +#include "input/MouseHook.h" +#include "input/Input.h" #include "cdc/render/PCDeviceManager.h" +extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); + Menu::Menu() : PCInternalResource() { ImGui::CreateContext(); @@ -15,7 +21,8 @@ Menu::Menu() : PCInternalResource() ImGui_ImplWin32_Init(cdc::PCDeviceManager::s_pInstance->GetWindow()); // Add present callback to draw the UI - RenderContext::OnPresent([this] { OnPresent(); }); + RenderContext::OnPresent(std::bind(&Menu::OnPresent, this)); + MouseHook::Init(); OnConstruct(); } @@ -44,13 +51,20 @@ void Menu::OnDestroyDevice() void Menu::OnPresent() { + // Set the mouse cursor visible when we have focus + ImGui::GetIO().MouseDrawCursor = m_focus; + + // Start the frame ImGui_ImplDX9_NewFrame(); ImGui_ImplWin32_NewFrame(); ImGui::NewFrame(); // Draw the menu - Draw(); + if (m_focus) + { + Draw(); + } // End the frame ImGui::EndFrame(); @@ -59,9 +73,37 @@ void Menu::OnPresent() ImGui_ImplDX9_RenderDrawData(ImGui::GetDrawData()); } +void Menu::OnMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + if (msg == WM_KEYUP && wParam == VK_F8) + { + SetFocus(!m_focus); + } + + if (m_focus) + { + ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam); + } +} + void Menu::Draw() { - ImGui::Begin("Menu"); - ImGui::Text("Hello, World!"); - ImGui::End(); + if (ImGui::BeginMainMenuBar()) + { + ImGui::EndMainMenuBar(); + } +} + +void Menu::SetFocus(bool focus) +{ + m_focus = focus; + + // Disable the cursor lock and game input + MouseHook::DisableCursorLock(focus); + Input::DisableInput(focus); +} + +bool Menu::HasFocus() +{ + return m_focus; } \ No newline at end of file diff --git a/src/menu/Menu.h b/src/menu/Menu.h index 0d3189f..d3a1c59 100644 --- a/src/menu/Menu.h +++ b/src/menu/Menu.h @@ -1,20 +1,27 @@ #pragma once +#include + #include "cdc/render/PCInternalResource.h" class Menu : public cdc::PCInternalResource { private: bool m_initialized = false; + bool m_focus = false; public: Menu(); void OnPresent(); + void OnMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); bool OnCreateDevice(); void OnDestroyDevice(); + void SetFocus(bool focus); + bool HasFocus(); + private: void Draw(); }; \ No newline at end of file