mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Merge helper GUI threads
This commit is contained in:
parent
fa8dec88c5
commit
229fe449ef
@ -301,6 +301,7 @@
|
|||||||
<ClInclude Include="Gdi\Caret.h" />
|
<ClInclude Include="Gdi\Caret.h" />
|
||||||
<ClInclude Include="Gdi\Dc.h" />
|
<ClInclude Include="Gdi\Dc.h" />
|
||||||
<ClInclude Include="Gdi\DcFunctions.h" />
|
<ClInclude Include="Gdi\DcFunctions.h" />
|
||||||
|
<ClInclude Include="Gdi\GuiThread.h" />
|
||||||
<ClInclude Include="Gdi\Icon.h" />
|
<ClInclude Include="Gdi\Icon.h" />
|
||||||
<ClInclude Include="Gdi\Metrics.h" />
|
<ClInclude Include="Gdi\Metrics.h" />
|
||||||
<ClInclude Include="Gdi\PresentationWindow.h" />
|
<ClInclude Include="Gdi\PresentationWindow.h" />
|
||||||
@ -401,6 +402,7 @@
|
|||||||
<ClCompile Include="Gdi\Caret.cpp" />
|
<ClCompile Include="Gdi\Caret.cpp" />
|
||||||
<ClCompile Include="Gdi\Dc.cpp" />
|
<ClCompile Include="Gdi\Dc.cpp" />
|
||||||
<ClCompile Include="Gdi\DcFunctions.cpp" />
|
<ClCompile Include="Gdi\DcFunctions.cpp" />
|
||||||
|
<ClCompile Include="Gdi\GuiThread.cpp" />
|
||||||
<ClCompile Include="Gdi\Icon.cpp" />
|
<ClCompile Include="Gdi\Icon.cpp" />
|
||||||
<ClCompile Include="Gdi\Metrics.cpp" />
|
<ClCompile Include="Gdi\Metrics.cpp" />
|
||||||
<ClCompile Include="Gdi\PresentationWindow.cpp" />
|
<ClCompile Include="Gdi\PresentationWindow.cpp" />
|
||||||
@ -454,4 +456,4 @@
|
|||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
</Project>
|
</Project>
|
@ -513,6 +513,9 @@
|
|||||||
<ClInclude Include="Common\Rect.h">
|
<ClInclude Include="Common\Rect.h">
|
||||||
<Filter>Header Files\Common</Filter>
|
<Filter>Header Files\Common</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="Gdi\GuiThread.h">
|
||||||
|
<Filter>Header Files\Gdi</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="Gdi\Gdi.cpp">
|
<ClCompile Include="Gdi\Gdi.cpp">
|
||||||
@ -809,6 +812,9 @@
|
|||||||
<ClCompile Include="Common\Rect.cpp">
|
<ClCompile Include="Common\Rect.cpp">
|
||||||
<Filter>Source Files\Common</Filter>
|
<Filter>Source Files\Common</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="Gdi\GuiThread.cpp">
|
||||||
|
<Filter>Source Files\Gdi</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="DDrawCompat.rc">
|
<ResourceCompile Include="DDrawCompat.rc">
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include <Direct3d/Hooks.h>
|
#include <Direct3d/Hooks.h>
|
||||||
#include <Dll/Dll.h>
|
#include <Dll/Dll.h>
|
||||||
#include <Gdi/Gdi.h>
|
#include <Gdi/Gdi.h>
|
||||||
|
#include <Gdi/GuiThread.h>
|
||||||
#include <Gdi/PresentationWindow.h>
|
#include <Gdi/PresentationWindow.h>
|
||||||
#include <Gdi/VirtualScreen.h>
|
#include <Gdi/VirtualScreen.h>
|
||||||
#include <Input/Input.h>
|
#include <Input/Input.h>
|
||||||
@ -113,7 +114,7 @@ namespace
|
|||||||
Compat::Log() << "Installing GDI hooks";
|
Compat::Log() << "Installing GDI hooks";
|
||||||
Gdi::installHooks();
|
Gdi::installHooks();
|
||||||
Compat::closeDbgEng();
|
Compat::closeDbgEng();
|
||||||
Gdi::PresentationWindow::startThread();
|
Gdi::GuiThread::start();
|
||||||
Compat::Log() << "Finished installing hooks";
|
Compat::Log() << "Finished installing hooks";
|
||||||
isAlreadyInstalled = true;
|
isAlreadyInstalled = true;
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <Gdi/DcFunctions.h>
|
#include <Gdi/DcFunctions.h>
|
||||||
#include <Gdi/Font.h>
|
#include <Gdi/Font.h>
|
||||||
#include <Gdi/Gdi.h>
|
#include <Gdi/Gdi.h>
|
||||||
|
#include <Gdi/GuiThread.h>
|
||||||
#include <Gdi/Icon.h>
|
#include <Gdi/Icon.h>
|
||||||
#include <Gdi/Metrics.h>
|
#include <Gdi/Metrics.h>
|
||||||
#include <Gdi/Palette.h>
|
#include <Gdi/Palette.h>
|
||||||
@ -74,6 +75,7 @@ namespace Gdi
|
|||||||
Caret::installHooks();
|
Caret::installHooks();
|
||||||
Cursor::installHooks();
|
Cursor::installHooks();
|
||||||
Font::installHooks();
|
Font::installHooks();
|
||||||
|
WinProc::installHooks();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isDisplayDc(HDC dc)
|
bool isDisplayDc(HDC dc)
|
||||||
@ -90,7 +92,7 @@ namespace Gdi
|
|||||||
|
|
||||||
void redrawWindow(HWND hwnd, HRGN rgn)
|
void redrawWindow(HWND hwnd, HRGN rgn)
|
||||||
{
|
{
|
||||||
if (!IsWindowVisible(hwnd) || IsIconic(hwnd) || PresentationWindow::isPresentationWindow(hwnd))
|
if (!IsWindowVisible(hwnd) || IsIconic(hwnd) || GuiThread::isGuiThreadWindow(hwnd))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
157
DDrawCompat/Gdi/GuiThread.cpp
Normal file
157
DDrawCompat/Gdi/GuiThread.cpp
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
#include <Common/Log.h>
|
||||||
|
#include <Common/Hook.h>
|
||||||
|
#include <D3dDdi/ScopedCriticalSection.h>
|
||||||
|
#include <Dll/Dll.h>
|
||||||
|
#include <Gdi/GuiThread.h>
|
||||||
|
#include <Gdi/Region.h>
|
||||||
|
#include <Gdi/WinProc.h>
|
||||||
|
#include <Overlay/ConfigWindow.h>
|
||||||
|
#include <Win32/DisplayMode.h>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
const UINT WM_USER_EXECUTE = WM_USER;
|
||||||
|
|
||||||
|
unsigned g_threadId = 0;
|
||||||
|
Overlay::ConfigWindow* g_configWindow = nullptr;
|
||||||
|
HWND g_messageWindow = nullptr;
|
||||||
|
bool g_isReady = false;
|
||||||
|
|
||||||
|
BOOL CALLBACK initChildWindow(HWND hwnd, LPARAM /*lParam*/)
|
||||||
|
{
|
||||||
|
Gdi::WinProc::onCreateWindow(hwnd);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL CALLBACK initTopLevelWindow(HWND hwnd, LPARAM /*lParam*/)
|
||||||
|
{
|
||||||
|
DWORD windowPid = 0;
|
||||||
|
GetWindowThreadProcessId(hwnd, &windowPid);
|
||||||
|
if (GetCurrentProcessId() == windowPid)
|
||||||
|
{
|
||||||
|
Gdi::WinProc::onCreateWindow(hwnd);
|
||||||
|
EnumChildWindows(hwnd, &initChildWindow, 0);
|
||||||
|
if (8 == Win32::DisplayMode::getBpp())
|
||||||
|
{
|
||||||
|
PostMessage(hwnd, WM_PALETTECHANGED, reinterpret_cast<WPARAM>(GetDesktopWindow()), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT CALLBACK messageWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
LOG_FUNC("messageWindowProc", Compat::WindowMessageStruct(hwnd, uMsg, wParam, lParam));
|
||||||
|
|
||||||
|
if (WM_USER_EXECUTE == uMsg)
|
||||||
|
{
|
||||||
|
auto& func = *reinterpret_cast<const std::function<void()>*>(lParam);
|
||||||
|
func();
|
||||||
|
return LOG_RESULT(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return LOG_RESULT(CALL_ORIG_FUNC(DefWindowProc)(hwnd, uMsg, wParam, lParam));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned WINAPI messageWindowThreadProc(LPVOID /*lpParameter*/)
|
||||||
|
{
|
||||||
|
WNDCLASS wc = {};
|
||||||
|
wc.lpfnWndProc = &messageWindowProc;
|
||||||
|
wc.hInstance = Dll::g_currentModule;
|
||||||
|
wc.lpszClassName = "DDrawCompatMessageWindow";
|
||||||
|
CALL_ORIG_FUNC(RegisterClassA)(&wc);
|
||||||
|
|
||||||
|
g_messageWindow = CreateWindow(
|
||||||
|
"DDrawCompatMessageWindow", nullptr, 0, 0, 0, 0, 0, HWND_MESSAGE, nullptr, nullptr, nullptr);
|
||||||
|
if (!g_messageWindow)
|
||||||
|
{
|
||||||
|
Compat::Log() << "ERROR: Failed to create a message-only window";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Overlay::ConfigWindow configWindow;
|
||||||
|
g_configWindow = &configWindow;
|
||||||
|
|
||||||
|
{
|
||||||
|
D3dDdi::ScopedCriticalSection lock;
|
||||||
|
g_isReady = true;
|
||||||
|
EnumWindows(initTopLevelWindow, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
MSG msg = {};
|
||||||
|
while (GetMessage(&msg, nullptr, 0, 0))
|
||||||
|
{
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessage(&msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Gdi
|
||||||
|
{
|
||||||
|
namespace GuiThread
|
||||||
|
{
|
||||||
|
HWND createWindow(DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, DWORD dwStyle,
|
||||||
|
int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam)
|
||||||
|
{
|
||||||
|
// Workaround for ForceSimpleWindow shim
|
||||||
|
static auto createWindowExA = reinterpret_cast<decltype(&CreateWindowExA)>(
|
||||||
|
Compat::getProcAddress(GetModuleHandle("user32"), "CreateWindowExA"));
|
||||||
|
|
||||||
|
HWND hwnd = nullptr;
|
||||||
|
execute([&]()
|
||||||
|
{
|
||||||
|
hwnd = createWindowExA(dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight,
|
||||||
|
hWndParent, hMenu, hInstance, lpParam);
|
||||||
|
});
|
||||||
|
return hwnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
void destroyWindow(HWND hwnd)
|
||||||
|
{
|
||||||
|
execute([&]() { DestroyWindow(hwnd); });
|
||||||
|
}
|
||||||
|
|
||||||
|
void executeFunc(const std::function<void()>& func)
|
||||||
|
{
|
||||||
|
DWORD_PTR result = 0;
|
||||||
|
SendMessageTimeout(g_messageWindow, WM_USER_EXECUTE, 0, reinterpret_cast<LPARAM>(&func),
|
||||||
|
SMTO_BLOCK | SMTO_NOTIMEOUTIFNOTHUNG, 0, &result);
|
||||||
|
}
|
||||||
|
|
||||||
|
Overlay::ConfigWindow* getConfigWindow()
|
||||||
|
{
|
||||||
|
return g_configWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isGuiThreadWindow(HWND hwnd)
|
||||||
|
{
|
||||||
|
return GetWindowThreadProcessId(hwnd, nullptr) == g_threadId;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isReady()
|
||||||
|
{
|
||||||
|
return g_isReady;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setWindowRgn(HWND hwnd, Gdi::Region rgn)
|
||||||
|
{
|
||||||
|
execute([&]()
|
||||||
|
{
|
||||||
|
if (SetWindowRgn(hwnd, rgn, FALSE))
|
||||||
|
{
|
||||||
|
rgn.release();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void start()
|
||||||
|
{
|
||||||
|
Dll::createThread(messageWindowThreadProc, &g_threadId, THREAD_PRIORITY_TIME_CRITICAL, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
34
DDrawCompat/Gdi/GuiThread.h
Normal file
34
DDrawCompat/Gdi/GuiThread.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
#include <Gdi/Region.h>
|
||||||
|
|
||||||
|
namespace Overlay
|
||||||
|
{
|
||||||
|
class ConfigWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Gdi
|
||||||
|
{
|
||||||
|
namespace GuiThread
|
||||||
|
{
|
||||||
|
HWND createWindow(DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, DWORD dwStyle,
|
||||||
|
int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam);
|
||||||
|
void destroyWindow(HWND hwnd);
|
||||||
|
void setWindowRgn(HWND hwnd, Gdi::Region rgn);
|
||||||
|
|
||||||
|
Overlay::ConfigWindow* getConfigWindow();
|
||||||
|
|
||||||
|
template <typename Func>
|
||||||
|
void execute(const Func& func) { executeFunc(std::cref(func)); }
|
||||||
|
void executeFunc(const std::function<void()>& func);
|
||||||
|
|
||||||
|
bool isGuiThreadWindow(HWND hwnd);
|
||||||
|
bool isReady();
|
||||||
|
|
||||||
|
void start();
|
||||||
|
}
|
||||||
|
}
|
@ -196,7 +196,7 @@ namespace
|
|||||||
if (result && !bForceBackground)
|
if (result && !bForceBackground)
|
||||||
{
|
{
|
||||||
HWND dcWindow = CALL_ORIG_FUNC(WindowFromDC)(hdc);
|
HWND dcWindow = CALL_ORIG_FUNC(WindowFromDC)(hdc);
|
||||||
if (dcWindow && !(GetWindowLong(dcWindow, GWL_EXSTYLE) & WS_EX_TOOLWINDOW))
|
if (dcWindow && !(CALL_ORIG_FUNC(GetWindowLongA)(dcWindow, GWL_EXSTYLE) & WS_EX_TOOLWINDOW))
|
||||||
{
|
{
|
||||||
HWND activeWindow = GetActiveWindow();
|
HWND activeWindow = GetActiveWindow();
|
||||||
if (activeWindow == dcWindow || IsChild(activeWindow, dcWindow))
|
if (activeWindow == dcWindow || IsChild(activeWindow, dcWindow))
|
||||||
|
@ -1,160 +1,17 @@
|
|||||||
#include <Common/Hook.h>
|
#include <Common/Hook.h>
|
||||||
#include <Common/Log.h>
|
#include <Common/Log.h>
|
||||||
#include <D3dDdi/ScopedCriticalSection.h>
|
|
||||||
#include <Dll/Dll.h>
|
#include <Dll/Dll.h>
|
||||||
|
#include <Gdi/GuiThread.h>
|
||||||
#include <Gdi/PresentationWindow.h>
|
#include <Gdi/PresentationWindow.h>
|
||||||
#include <Gdi/WinProc.h>
|
|
||||||
#include <Overlay/ConfigWindow.h>
|
|
||||||
#include <Win32/DisplayMode.h>
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
const UINT WM_CREATEPRESENTATIONWINDOW = WM_USER;
|
ATOM g_classAtom = 0;
|
||||||
const UINT WM_SETPRESENTATIONWINDOWPOS = WM_USER + 1;
|
|
||||||
const UINT WM_SETPRESENTATIONWINDOWRGN = WM_USER + 2;
|
|
||||||
|
|
||||||
HANDLE g_presentationWindowThread = nullptr;
|
|
||||||
unsigned g_presentationWindowThreadId = 0;
|
|
||||||
Overlay::ConfigWindow* g_configWindow = nullptr;
|
|
||||||
HWND g_messageWindow = nullptr;
|
|
||||||
bool g_isThreadReady = false;
|
|
||||||
|
|
||||||
BOOL CALLBACK initChildWindow(HWND hwnd, LPARAM /*lParam*/)
|
|
||||||
{
|
|
||||||
Gdi::WinProc::onCreateWindow(hwnd);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL CALLBACK initTopLevelWindow(HWND hwnd, LPARAM /*lParam*/)
|
|
||||||
{
|
|
||||||
DWORD windowPid = 0;
|
|
||||||
GetWindowThreadProcessId(hwnd, &windowPid);
|
|
||||||
if (GetCurrentProcessId() == windowPid)
|
|
||||||
{
|
|
||||||
Gdi::WinProc::onCreateWindow(hwnd);
|
|
||||||
EnumChildWindows(hwnd, &initChildWindow, 0);
|
|
||||||
if (8 == Win32::DisplayMode::getBpp())
|
|
||||||
{
|
|
||||||
PostMessage(hwnd, WM_PALETTECHANGED, reinterpret_cast<WPARAM>(GetDesktopWindow()), 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
LRESULT CALLBACK messageWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
||||||
{
|
|
||||||
LOG_FUNC("messageWindowProc", Compat::WindowMessageStruct(hwnd, uMsg, wParam, lParam));
|
|
||||||
|
|
||||||
switch (uMsg)
|
|
||||||
{
|
|
||||||
case WM_CREATEPRESENTATIONWINDOW:
|
|
||||||
{
|
|
||||||
// Workaround for ForceSimpleWindow shim
|
|
||||||
static auto origCreateWindowExA = reinterpret_cast<decltype(&CreateWindowExA)>(
|
|
||||||
Compat::getProcAddress(GetModuleHandle("user32"), "CreateWindowExA"));
|
|
||||||
|
|
||||||
HWND owner = reinterpret_cast<HWND>(wParam);
|
|
||||||
HWND presentationWindow = origCreateWindowExA(
|
|
||||||
WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_NOPARENTNOTIFY | WS_EX_TOOLWINDOW,
|
|
||||||
"DDrawCompatPresentationWindow",
|
|
||||||
nullptr,
|
|
||||||
WS_DISABLED | WS_POPUP,
|
|
||||||
0, 0, 1, 1,
|
|
||||||
owner,
|
|
||||||
nullptr,
|
|
||||||
nullptr,
|
|
||||||
nullptr);
|
|
||||||
|
|
||||||
if (presentationWindow)
|
|
||||||
{
|
|
||||||
if (lParam)
|
|
||||||
{
|
|
||||||
CALL_ORIG_FUNC(SetWindowLongA)(presentationWindow, GWL_WNDPROC, lParam);
|
|
||||||
}
|
|
||||||
CALL_ORIG_FUNC(SetLayeredWindowAttributes)(presentationWindow, 0, 255, LWA_ALPHA);
|
|
||||||
}
|
|
||||||
|
|
||||||
return LOG_RESULT(reinterpret_cast<LRESULT>(presentationWindow));
|
|
||||||
}
|
|
||||||
|
|
||||||
case WM_DESTROY:
|
|
||||||
PostQuitMessage(0);
|
|
||||||
return LOG_RESULT(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return LOG_RESULT(CALL_ORIG_FUNC(DefWindowProc)(hwnd, uMsg, wParam, lParam));
|
|
||||||
}
|
|
||||||
|
|
||||||
LRESULT CALLBACK presentationWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
LRESULT CALLBACK presentationWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
LOG_FUNC("presentationWindowProc", Compat::WindowMessageStruct(hwnd, uMsg, wParam, lParam));
|
LOG_FUNC("presentationWindowProc", Compat::WindowMessageStruct(hwnd, uMsg, wParam, lParam));
|
||||||
|
return CALL_ORIG_FUNC(DefWindowProcA)(hwnd, uMsg, wParam, lParam);
|
||||||
switch (uMsg)
|
|
||||||
{
|
|
||||||
case WM_SETPRESENTATIONWINDOWPOS:
|
|
||||||
{
|
|
||||||
const auto& wp = *reinterpret_cast<WINDOWPOS*>(lParam);
|
|
||||||
return SetWindowPos(hwnd, wp.hwndInsertAfter, wp.x, wp.y, wp.cx, wp.cy, wp.flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
case WM_SETPRESENTATIONWINDOWRGN:
|
|
||||||
{
|
|
||||||
HRGN rgn = nullptr;
|
|
||||||
if (wParam)
|
|
||||||
{
|
|
||||||
rgn = CreateRectRgn(0, 0, 0, 0);
|
|
||||||
CombineRgn(rgn, reinterpret_cast<HRGN>(wParam), nullptr, RGN_COPY);
|
|
||||||
}
|
|
||||||
return SetWindowRgn(hwnd, rgn, FALSE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return CALL_ORIG_FUNC(DefWindowProc)(hwnd, uMsg, wParam, lParam);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned WINAPI presentationWindowThreadProc(LPVOID /*lpParameter*/)
|
|
||||||
{
|
|
||||||
WNDCLASS wc = {};
|
|
||||||
wc.lpfnWndProc = &messageWindowProc;
|
|
||||||
wc.hInstance = Dll::g_currentModule;
|
|
||||||
wc.lpszClassName = "DDrawCompatMessageWindow";
|
|
||||||
CALL_ORIG_FUNC(RegisterClassA)(&wc);
|
|
||||||
|
|
||||||
g_messageWindow = CreateWindow(
|
|
||||||
"DDrawCompatMessageWindow", nullptr, 0, 0, 0, 0, 0, HWND_MESSAGE, nullptr, nullptr, nullptr);
|
|
||||||
if (!g_messageWindow)
|
|
||||||
{
|
|
||||||
Compat::Log() << "ERROR: Failed to create a message-only window";
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
D3dDdi::ScopedCriticalSection lock;
|
|
||||||
Gdi::WinProc::installHooks();
|
|
||||||
g_isThreadReady = true;
|
|
||||||
EnumWindows(initTopLevelWindow, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
Compat::closeDbgEng();
|
|
||||||
|
|
||||||
Overlay::ConfigWindow configWindow;
|
|
||||||
g_configWindow = &configWindow;
|
|
||||||
|
|
||||||
MSG msg = {};
|
|
||||||
while (GetMessage(&msg, nullptr, 0, 0))
|
|
||||||
{
|
|
||||||
TranslateMessage(&msg);
|
|
||||||
DispatchMessage(&msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
LRESULT sendMessageBlocking(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
||||||
{
|
|
||||||
DWORD_PTR result = 0;
|
|
||||||
SendMessageTimeout(hwnd, msg, wParam, lParam, SMTO_BLOCK | SMTO_NOTIMEOUTIFNOTHUNG, 0, &result);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,20 +19,28 @@ namespace Gdi
|
|||||||
{
|
{
|
||||||
namespace PresentationWindow
|
namespace PresentationWindow
|
||||||
{
|
{
|
||||||
HWND create(HWND owner, WNDPROC wndProc)
|
HWND create(HWND owner)
|
||||||
{
|
{
|
||||||
return reinterpret_cast<HWND>(sendMessageBlocking(g_messageWindow, WM_CREATEPRESENTATIONWINDOW,
|
HWND presentationWindow = nullptr;
|
||||||
reinterpret_cast<WPARAM>(owner), reinterpret_cast<LPARAM>(wndProc)));
|
GuiThread::execute([&]()
|
||||||
}
|
{
|
||||||
|
presentationWindow = GuiThread::createWindow(
|
||||||
|
WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_NOPARENTNOTIFY | WS_EX_TOOLWINDOW,
|
||||||
|
reinterpret_cast<const char*>(g_classAtom),
|
||||||
|
nullptr,
|
||||||
|
WS_DISABLED | WS_POPUP,
|
||||||
|
0, 0, 1, 1,
|
||||||
|
owner,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
void destroy(HWND hwnd)
|
if (presentationWindow)
|
||||||
{
|
{
|
||||||
PostMessage(hwnd, WM_CLOSE, 0, 0);
|
CALL_ORIG_FUNC(SetLayeredWindowAttributes)(presentationWindow, 0, 255, LWA_ALPHA);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
Overlay::ConfigWindow* getConfigWindow()
|
return presentationWindow;
|
||||||
{
|
|
||||||
return g_configWindow;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void installHooks()
|
void installHooks()
|
||||||
@ -184,35 +49,7 @@ namespace Gdi
|
|||||||
wc.lpfnWndProc = &presentationWindowProc;
|
wc.lpfnWndProc = &presentationWindowProc;
|
||||||
wc.hInstance = Dll::g_currentModule;
|
wc.hInstance = Dll::g_currentModule;
|
||||||
wc.lpszClassName = "DDrawCompatPresentationWindow";
|
wc.lpszClassName = "DDrawCompatPresentationWindow";
|
||||||
CALL_ORIG_FUNC(RegisterClassA)(&wc);
|
g_classAtom = CALL_ORIG_FUNC(RegisterClassA)(&wc);
|
||||||
|
|
||||||
g_presentationWindowThread = Dll::createThread(presentationWindowThreadProc, &g_presentationWindowThreadId,
|
|
||||||
THREAD_PRIORITY_TIME_CRITICAL, CREATE_SUSPENDED);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isPresentationWindow(HWND hwnd)
|
|
||||||
{
|
|
||||||
return GetWindowThreadProcessId(hwnd, nullptr) == g_presentationWindowThreadId;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isThreadReady()
|
|
||||||
{
|
|
||||||
return g_isThreadReady;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setWindowPos(HWND hwnd, const WINDOWPOS& wp)
|
|
||||||
{
|
|
||||||
sendMessageBlocking(hwnd, WM_SETPRESENTATIONWINDOWPOS, 0, reinterpret_cast<WPARAM>(&wp));
|
|
||||||
}
|
|
||||||
|
|
||||||
void setWindowRgn(HWND hwnd, HRGN rgn)
|
|
||||||
{
|
|
||||||
sendMessageBlocking(hwnd, WM_SETPRESENTATIONWINDOWRGN, reinterpret_cast<WPARAM>(rgn), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void startThread()
|
|
||||||
{
|
|
||||||
ResumeThread(g_presentationWindowThread);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,23 +2,11 @@
|
|||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
|
||||||
namespace Overlay
|
|
||||||
{
|
|
||||||
class ConfigWindow;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Gdi
|
namespace Gdi
|
||||||
{
|
{
|
||||||
namespace PresentationWindow
|
namespace PresentationWindow
|
||||||
{
|
{
|
||||||
HWND create(HWND owner, WNDPROC wndProc = nullptr);
|
HWND create(HWND owner);
|
||||||
void destroy(HWND hwnd);
|
|
||||||
Overlay::ConfigWindow* getConfigWindow();
|
|
||||||
bool isPresentationWindow(HWND hwnd);
|
|
||||||
bool isThreadReady();
|
|
||||||
void setWindowPos(HWND hwnd, const WINDOWPOS& wp);
|
|
||||||
void setWindowRgn(HWND hwnd, HRGN rgn);
|
|
||||||
void startThread();
|
|
||||||
|
|
||||||
void installHooks();
|
void installHooks();
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
#include <DDraw/Surfaces/PrimarySurface.h>
|
#include <DDraw/Surfaces/PrimarySurface.h>
|
||||||
#include <Gdi/CompatDc.h>
|
#include <Gdi/CompatDc.h>
|
||||||
#include <Gdi/Cursor.h>
|
#include <Gdi/Cursor.h>
|
||||||
#include <Gdi/PresentationWindow.h>
|
#include <Gdi/GuiThread.h>
|
||||||
#include <Gdi/ScrollBar.h>
|
#include <Gdi/ScrollBar.h>
|
||||||
#include <Gdi/ScrollFunctions.h>
|
#include <Gdi/ScrollFunctions.h>
|
||||||
#include <Gdi/TitleBar.h>
|
#include <Gdi/TitleBar.h>
|
||||||
@ -319,7 +319,7 @@ namespace
|
|||||||
if (wp.x + wp.cx > mr.right)
|
if (wp.x + wp.cx > mr.right)
|
||||||
{
|
{
|
||||||
HWND parent = GetNextWindow(wp.hwnd, GW_HWNDNEXT);
|
HWND parent = GetNextWindow(wp.hwnd, GW_HWNDNEXT);
|
||||||
while (Gdi::PresentationWindow::isPresentationWindow(parent))
|
while (Gdi::GuiThread::isGuiThreadWindow(parent))
|
||||||
{
|
{
|
||||||
parent = GetNextWindow(parent, GW_HWNDNEXT);
|
parent = GetNextWindow(parent, GW_HWNDNEXT);
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include <Gdi/Cursor.h>
|
#include <Gdi/Cursor.h>
|
||||||
#include <Gdi/Dc.h>
|
#include <Gdi/Dc.h>
|
||||||
#include <Gdi/Gdi.h>
|
#include <Gdi/Gdi.h>
|
||||||
|
#include <Gdi/GuiThread.h>
|
||||||
#include <Gdi/PresentationWindow.h>
|
#include <Gdi/PresentationWindow.h>
|
||||||
#include <Gdi/ScrollBar.h>
|
#include <Gdi/ScrollBar.h>
|
||||||
#include <Gdi/ScrollFunctions.h>
|
#include <Gdi/ScrollFunctions.h>
|
||||||
@ -39,7 +40,6 @@ namespace
|
|||||||
WindowProc getWindowProc(HWND hwnd);
|
WindowProc getWindowProc(HWND hwnd);
|
||||||
bool isTopLevelWindow(HWND hwnd);
|
bool isTopLevelWindow(HWND hwnd);
|
||||||
bool isUser32ScrollBar(HWND hwnd);
|
bool isUser32ScrollBar(HWND hwnd);
|
||||||
void onCreateWindow(HWND hwnd);
|
|
||||||
void onDestroyWindow(HWND hwnd);
|
void onDestroyWindow(HWND hwnd);
|
||||||
void onGetMinMaxInfo(MINMAXINFO& mmi);
|
void onGetMinMaxInfo(MINMAXINFO& mmi);
|
||||||
void onInitMenuPopup(HMENU menu);
|
void onInitMenuPopup(HMENU menu);
|
||||||
@ -95,12 +95,15 @@ namespace
|
|||||||
case WM_ACTIVATEAPP:
|
case WM_ACTIVATEAPP:
|
||||||
if (!wParam)
|
if (!wParam)
|
||||||
{
|
{
|
||||||
auto configWindow = Gdi::PresentationWindow::getConfigWindow();
|
Gdi::GuiThread::execute([&]()
|
||||||
if (configWindow)
|
{
|
||||||
{
|
auto configWindow = Gdi::GuiThread::getConfigWindow();
|
||||||
configWindow->setVisible(false);
|
if (configWindow)
|
||||||
}
|
{
|
||||||
CALL_ORIG_FUNC(ClipCursor)(nullptr);
|
configWindow->setVisible(false);
|
||||||
|
}
|
||||||
|
CALL_ORIG_FUNC(ClipCursor)(nullptr);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -202,40 +205,6 @@ namespace
|
|||||||
IsWindowUnicode(hwnd) ? it->second.wndProcW : it->second.wndProcA);
|
IsWindowUnicode(hwnd) ? it->second.wndProcW : it->second.wndProcA);
|
||||||
}
|
}
|
||||||
|
|
||||||
void onCreateWindow(HWND hwnd)
|
|
||||||
{
|
|
||||||
LOG_FUNC("onCreateWindow", hwnd);
|
|
||||||
|
|
||||||
{
|
|
||||||
Compat::ScopedSrwLockExclusive lock(g_windowProcSrwLock);
|
|
||||||
if (g_windowProc.find(hwnd) != g_windowProc.end())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto wndProcA = reinterpret_cast<WNDPROC>(CALL_ORIG_FUNC(GetWindowLongA)(hwnd, GWL_WNDPROC));
|
|
||||||
auto wndProcW = reinterpret_cast<WNDPROC>(CALL_ORIG_FUNC(GetWindowLongW)(hwnd, GWL_WNDPROC));
|
|
||||||
g_windowProc[hwnd] = { wndProcA, wndProcW };
|
|
||||||
setWindowProc(hwnd, ddcWindowProcA, ddcWindowProcW);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isTopLevelWindow(hwnd))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
char className[64] = {};
|
|
||||||
GetClassName(hwnd, className, sizeof(className));
|
|
||||||
if (std::string(className) == "CompatWindowDesktopReplacement")
|
|
||||||
{
|
|
||||||
// Disable VirtualizeDesktopPainting shim
|
|
||||||
SendNotifyMessage(hwnd, WM_CLOSE, 0, 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Gdi::Window::updateAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
void onDestroyWindow(HWND hwnd)
|
void onDestroyWindow(HWND hwnd)
|
||||||
{
|
{
|
||||||
if (isTopLevelWindow(hwnd))
|
if (isTopLevelWindow(hwnd))
|
||||||
@ -415,9 +384,9 @@ namespace
|
|||||||
switch (event)
|
switch (event)
|
||||||
{
|
{
|
||||||
case EVENT_OBJECT_CREATE:
|
case EVENT_OBJECT_CREATE:
|
||||||
if (OBJID_WINDOW == idObject && !Gdi::PresentationWindow::isPresentationWindow(hwnd))
|
if (OBJID_WINDOW == idObject)
|
||||||
{
|
{
|
||||||
onCreateWindow(hwnd);
|
Gdi::WinProc::onCreateWindow(hwnd);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -511,10 +480,40 @@ namespace Gdi
|
|||||||
|
|
||||||
void onCreateWindow(HWND hwnd)
|
void onCreateWindow(HWND hwnd)
|
||||||
{
|
{
|
||||||
if (PresentationWindow::isThreadReady())
|
LOG_FUNC("onCreateWindow", hwnd);
|
||||||
|
if (!GuiThread::isReady() || GuiThread::isGuiThreadWindow(hwnd))
|
||||||
{
|
{
|
||||||
::onCreateWindow(hwnd);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
Compat::ScopedSrwLockExclusive lock(g_windowProcSrwLock);
|
||||||
|
if (g_windowProc.find(hwnd) != g_windowProc.end())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto wndProcA = reinterpret_cast<WNDPROC>(CALL_ORIG_FUNC(GetWindowLongA)(hwnd, GWL_WNDPROC));
|
||||||
|
auto wndProcW = reinterpret_cast<WNDPROC>(CALL_ORIG_FUNC(GetWindowLongW)(hwnd, GWL_WNDPROC));
|
||||||
|
g_windowProc[hwnd] = { wndProcA, wndProcW };
|
||||||
|
setWindowProc(hwnd, ddcWindowProcA, ddcWindowProcW);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isTopLevelWindow(hwnd))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char className[64] = {};
|
||||||
|
GetClassName(hwnd, className, sizeof(className));
|
||||||
|
if (std::string(className) == "CompatWindowDesktopReplacement")
|
||||||
|
{
|
||||||
|
// Disable VirtualizeDesktopPainting shim
|
||||||
|
SendNotifyMessage(hwnd, WM_CLOSE, 0, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Gdi::Window::updateAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
void watchWindowPosChanges(WindowPosChangeNotifyFunc notifyFunc)
|
void watchWindowPosChanges(WindowPosChangeNotifyFunc notifyFunc)
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include <D3dDdi/ScopedCriticalSection.h>
|
#include <D3dDdi/ScopedCriticalSection.h>
|
||||||
#include <DDraw/RealPrimarySurface.h>
|
#include <DDraw/RealPrimarySurface.h>
|
||||||
#include <Gdi/Gdi.h>
|
#include <Gdi/Gdi.h>
|
||||||
|
#include <Gdi/GuiThread.h>
|
||||||
#include <Gdi/PresentationWindow.h>
|
#include <Gdi/PresentationWindow.h>
|
||||||
#include <Gdi/VirtualScreen.h>
|
#include <Gdi/VirtualScreen.h>
|
||||||
#include <Gdi/Window.h>
|
#include <Gdi/Window.h>
|
||||||
@ -249,7 +250,7 @@ namespace
|
|||||||
DWORD processId = 0;
|
DWORD processId = 0;
|
||||||
GetWindowThreadProcessId(hwnd, &processId);
|
GetWindowThreadProcessId(hwnd, &processId);
|
||||||
if (processId != context.processId ||
|
if (processId != context.processId ||
|
||||||
Gdi::PresentationWindow::isPresentationWindow(hwnd))
|
Gdi::GuiThread::isGuiThreadWindow(hwnd))
|
||||||
{
|
{
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -277,7 +278,7 @@ namespace
|
|||||||
}
|
}
|
||||||
else if (it->second.presentationWindow)
|
else if (it->second.presentationWindow)
|
||||||
{
|
{
|
||||||
Gdi::PresentationWindow::destroy(it->second.presentationWindow);
|
Gdi::GuiThread::destroyWindow(it->second.presentationWindow);
|
||||||
it->second.presentationWindow = nullptr;
|
it->second.presentationWindow = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -351,7 +352,7 @@ namespace
|
|||||||
{
|
{
|
||||||
if (setPresentationWindowRgn)
|
if (setPresentationWindowRgn)
|
||||||
{
|
{
|
||||||
Gdi::PresentationWindow::setWindowRgn(it->second.presentationWindow, it->second.windowRegion);
|
Gdi::GuiThread::setWindowRgn(it->second.presentationWindow, it->second.windowRegion);
|
||||||
}
|
}
|
||||||
|
|
||||||
WINDOWPOS wp = {};
|
WINDOWPOS wp = {};
|
||||||
@ -379,7 +380,11 @@ namespace
|
|||||||
wp.flags |= SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER;
|
wp.flags |= SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER;
|
||||||
}
|
}
|
||||||
|
|
||||||
Gdi::PresentationWindow::setWindowPos(it->second.presentationWindow, wp);
|
Gdi::GuiThread::execute([&]()
|
||||||
|
{
|
||||||
|
CALL_ORIG_FUNC(SetWindowPos)(it->second.presentationWindow,
|
||||||
|
wp.hwndInsertAfter, wp.x, wp.y, wp.cx, wp.cy, wp.flags);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -524,7 +529,7 @@ namespace Gdi
|
|||||||
}
|
}
|
||||||
|
|
||||||
RECT wr = {};
|
RECT wr = {};
|
||||||
auto configWindow = PresentationWindow::getConfigWindow();
|
auto configWindow = GuiThread::getConfigWindow();
|
||||||
if (configWindow && configWindow->isVisible())
|
if (configWindow && configWindow->isVisible())
|
||||||
{
|
{
|
||||||
GetWindowRect(configWindow->getWindow(), &wr);
|
GetWindowRect(configWindow->getWindow(), &wr);
|
||||||
@ -550,7 +555,7 @@ namespace Gdi
|
|||||||
void updateAll()
|
void updateAll()
|
||||||
{
|
{
|
||||||
LOG_FUNC("Window::updateAll");
|
LOG_FUNC("Window::updateAll");
|
||||||
if (!Gdi::PresentationWindow::isThreadReady())
|
if (!GuiThread::isReady())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -571,7 +576,7 @@ namespace Gdi
|
|||||||
{
|
{
|
||||||
if (it->second.presentationWindow)
|
if (it->second.presentationWindow)
|
||||||
{
|
{
|
||||||
Gdi::PresentationWindow::destroy(it->second.presentationWindow);
|
GuiThread::destroyWindow(it->second.presentationWindow);
|
||||||
}
|
}
|
||||||
it = g_windows.erase(it);
|
it = g_windows.erase(it);
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include <Common/Log.h>
|
#include <Common/Log.h>
|
||||||
#include <Dll/Dll.h>
|
#include <Dll/Dll.h>
|
||||||
#include <DDraw/RealPrimarySurface.h>
|
#include <DDraw/RealPrimarySurface.h>
|
||||||
|
#include <Gdi/GuiThread.h>
|
||||||
#include <Gdi/PresentationWindow.h>
|
#include <Gdi/PresentationWindow.h>
|
||||||
#include <Input/Input.h>
|
#include <Input/Input.h>
|
||||||
#include <Overlay/Window.h>
|
#include <Overlay/Window.h>
|
||||||
@ -21,9 +22,6 @@ namespace
|
|||||||
void* context;
|
void* context;
|
||||||
};
|
};
|
||||||
|
|
||||||
const UINT WM_USER_HOTKEY = WM_USER;
|
|
||||||
const UINT WM_USER_RESET_HOOK = WM_USER + 1;
|
|
||||||
|
|
||||||
HANDLE g_bmpArrow = nullptr;
|
HANDLE g_bmpArrow = nullptr;
|
||||||
SIZE g_bmpArrowSize = {};
|
SIZE g_bmpArrowSize = {};
|
||||||
Overlay::Window* g_capture = nullptr;
|
Overlay::Window* g_capture = nullptr;
|
||||||
@ -31,7 +29,6 @@ namespace
|
|||||||
HWND g_cursorWindow = nullptr;
|
HWND g_cursorWindow = nullptr;
|
||||||
std::map<Input::HotKey, HotKeyData> g_hotKeys;
|
std::map<Input::HotKey, HotKeyData> g_hotKeys;
|
||||||
RECT g_monitorRect = {};
|
RECT g_monitorRect = {};
|
||||||
DWORD g_inputThreadId = 0;
|
|
||||||
HHOOK g_keyboardHook = nullptr;
|
HHOOK g_keyboardHook = nullptr;
|
||||||
HHOOK g_mouseHook = nullptr;
|
HHOOK g_mouseHook = nullptr;
|
||||||
|
|
||||||
@ -65,72 +62,22 @@ namespace
|
|||||||
return CALL_ORIG_FUNC(DefWindowProcA)(hwnd, uMsg, wParam, lParam);
|
return CALL_ORIG_FUNC(DefWindowProcA)(hwnd, uMsg, wParam, lParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned WINAPI inputThreadProc(LPVOID /*lpParameter*/)
|
|
||||||
{
|
|
||||||
g_inputThreadId = GetCurrentThreadId();
|
|
||||||
g_bmpArrow = CALL_ORIG_FUNC(LoadImageA)(Dll::g_currentModule, "BMP_ARROW", IMAGE_BITMAP, 0, 0, 0);
|
|
||||||
|
|
||||||
BITMAP bm = {};
|
|
||||||
GetObject(g_bmpArrow, sizeof(bm), &bm);
|
|
||||||
g_bmpArrowSize = { bm.bmWidth, bm.bmHeight };
|
|
||||||
|
|
||||||
g_keyboardHook = CALL_ORIG_FUNC(SetWindowsHookExA)(WH_KEYBOARD_LL, &lowLevelKeyboardProc, Dll::g_currentModule, 0);
|
|
||||||
|
|
||||||
MSG msg = {};
|
|
||||||
while (GetMessage(&msg, nullptr, 0, 0))
|
|
||||||
{
|
|
||||||
if (msg.message == WM_TIMER && !msg.hwnd && msg.lParam)
|
|
||||||
{
|
|
||||||
reinterpret_cast<TIMERPROC>(msg.lParam)(nullptr, WM_TIMER, msg.wParam, 0);
|
|
||||||
}
|
|
||||||
if (!msg.hwnd)
|
|
||||||
{
|
|
||||||
if (WM_USER_HOTKEY == msg.message)
|
|
||||||
{
|
|
||||||
DWORD pid = 0;
|
|
||||||
GetWindowThreadProcessId(GetForegroundWindow(), &pid);
|
|
||||||
if (GetCurrentProcessId() == pid)
|
|
||||||
{
|
|
||||||
auto it = std::find_if(g_hotKeys.begin(), g_hotKeys.end(),
|
|
||||||
[&](const auto& v) { return v.first.vk == msg.wParam; });
|
|
||||||
if (it != g_hotKeys.end())
|
|
||||||
{
|
|
||||||
it->second.action(it->second.context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (WM_USER_RESET_HOOK == msg.message)
|
|
||||||
{
|
|
||||||
if (msg.wParam == WH_KEYBOARD_LL)
|
|
||||||
{
|
|
||||||
UnhookWindowsHookEx(g_keyboardHook);
|
|
||||||
g_keyboardHook = CALL_ORIG_FUNC(SetWindowsHookExA)(
|
|
||||||
WH_KEYBOARD_LL, &lowLevelKeyboardProc, Dll::g_currentModule, 0);
|
|
||||||
}
|
|
||||||
else if (msg.wParam == WH_MOUSE_LL && g_mouseHook)
|
|
||||||
{
|
|
||||||
UnhookWindowsHookEx(g_mouseHook);
|
|
||||||
g_mouseHook = CALL_ORIG_FUNC(SetWindowsHookExA)(
|
|
||||||
WH_MOUSE_LL, &lowLevelMouseProc, Dll::g_currentModule, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TranslateMessage(&msg);
|
|
||||||
DispatchMessage(&msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
LRESULT CALLBACK lowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
|
LRESULT CALLBACK lowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
if (HC_ACTION == nCode && (WM_KEYDOWN == wParam || WM_SYSKEYDOWN == wParam))
|
if (HC_ACTION == nCode && (WM_KEYDOWN == wParam || WM_SYSKEYDOWN == wParam))
|
||||||
{
|
{
|
||||||
auto llHook = reinterpret_cast<const KBDLLHOOKSTRUCT*>(lParam);
|
DWORD pid = 0;
|
||||||
PostThreadMessage(GetCurrentThreadId(), WM_USER_HOTKEY, llHook->vkCode, llHook->scanCode);
|
GetWindowThreadProcessId(GetForegroundWindow(), &pid);
|
||||||
|
if (GetCurrentProcessId() == pid)
|
||||||
|
{
|
||||||
|
auto llHook = reinterpret_cast<const KBDLLHOOKSTRUCT*>(lParam);
|
||||||
|
auto it = std::find_if(g_hotKeys.begin(), g_hotKeys.end(),
|
||||||
|
[&](const auto& v) { return v.first.vk == llHook->vkCode; });
|
||||||
|
if (it != g_hotKeys.end())
|
||||||
|
{
|
||||||
|
it->second.action(it->second.context);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return CallNextHookEx(nullptr, nCode, wParam, lParam);
|
return CallNextHookEx(nullptr, nCode, wParam, lParam);
|
||||||
}
|
}
|
||||||
@ -174,6 +121,32 @@ namespace
|
|||||||
return CallNextHookEx(nullptr, nCode, wParam, lParam);
|
return CallNextHookEx(nullptr, nCode, wParam, lParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void resetKeyboardHook()
|
||||||
|
{
|
||||||
|
Gdi::GuiThread::execute([]()
|
||||||
|
{
|
||||||
|
if (g_keyboardHook)
|
||||||
|
{
|
||||||
|
UnhookWindowsHookEx(g_keyboardHook);
|
||||||
|
}
|
||||||
|
g_keyboardHook = CALL_ORIG_FUNC(SetWindowsHookExA)(
|
||||||
|
WH_KEYBOARD_LL, &lowLevelKeyboardProc, Dll::g_currentModule, 0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void resetMouseHook()
|
||||||
|
{
|
||||||
|
Gdi::GuiThread::execute([]()
|
||||||
|
{
|
||||||
|
if (g_mouseHook)
|
||||||
|
{
|
||||||
|
UnhookWindowsHookEx(g_mouseHook);
|
||||||
|
}
|
||||||
|
g_mouseHook = CALL_ORIG_FUNC(SetWindowsHookExA)(
|
||||||
|
WH_MOUSE_LL, &lowLevelMouseProc, Dll::g_currentModule, 0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void setCursorPos(POINT cp)
|
void setCursorPos(POINT cp)
|
||||||
{
|
{
|
||||||
g_cursorPos = cp;
|
g_cursorPos = cp;
|
||||||
@ -191,9 +164,16 @@ namespace
|
|||||||
}
|
}
|
||||||
|
|
||||||
HHOOK result = origSetWindowsHookEx(idHook, lpfn, hmod, dwThreadId);
|
HHOOK result = origSetWindowsHookEx(idHook, lpfn, hmod, dwThreadId);
|
||||||
if (result && g_inputThreadId && (WH_KEYBOARD_LL == idHook || WH_MOUSE_LL == idHook))
|
if (result)
|
||||||
{
|
{
|
||||||
PostThreadMessage(g_inputThreadId, WM_USER_RESET_HOOK, idHook, 0);
|
if (WH_KEYBOARD_LL == idHook)
|
||||||
|
{
|
||||||
|
resetKeyboardHook();
|
||||||
|
}
|
||||||
|
else if (WH_MOUSE_LL == idHook && g_mouseHook)
|
||||||
|
{
|
||||||
|
resetMouseHook();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -235,16 +215,22 @@ namespace Input
|
|||||||
|
|
||||||
void installHooks()
|
void installHooks()
|
||||||
{
|
{
|
||||||
|
g_bmpArrow = CALL_ORIG_FUNC(LoadImageA)(Dll::g_currentModule, "BMP_ARROW", IMAGE_BITMAP, 0, 0, 0);
|
||||||
|
|
||||||
|
BITMAP bm = {};
|
||||||
|
GetObject(g_bmpArrow, sizeof(bm), &bm);
|
||||||
|
g_bmpArrowSize = { bm.bmWidth, bm.bmHeight };
|
||||||
|
|
||||||
HOOK_FUNCTION(user32, SetWindowsHookExA, setWindowsHookExA);
|
HOOK_FUNCTION(user32, SetWindowsHookExA, setWindowsHookExA);
|
||||||
HOOK_FUNCTION(user32, SetWindowsHookExW, setWindowsHookExW);
|
HOOK_FUNCTION(user32, SetWindowsHookExW, setWindowsHookExW);
|
||||||
}
|
}
|
||||||
|
|
||||||
void registerHotKey(const HotKey& hotKey, std::function<void(void*)> action, void* context)
|
void registerHotKey(const HotKey& hotKey, std::function<void(void*)> action, void* context)
|
||||||
{
|
{
|
||||||
static HANDLE thread = Dll::createThread(&inputThreadProc, nullptr, THREAD_PRIORITY_TIME_CRITICAL);
|
g_hotKeys[hotKey] = { action, context };
|
||||||
if (thread)
|
if (!g_keyboardHook)
|
||||||
{
|
{
|
||||||
g_hotKeys[hotKey] = { action, context };
|
resetKeyboardHook();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,7 +241,8 @@ namespace Input
|
|||||||
{
|
{
|
||||||
if (!g_mouseHook)
|
if (!g_mouseHook)
|
||||||
{
|
{
|
||||||
g_cursorWindow = Gdi::PresentationWindow::create(window->getWindow(), &cursorWindowProc);
|
g_cursorWindow = Gdi::PresentationWindow::create(window->getWindow());
|
||||||
|
CALL_ORIG_FUNC(SetWindowLongA)(g_cursorWindow, GWL_WNDPROC, reinterpret_cast<LONG>(&cursorWindowProc));
|
||||||
CALL_ORIG_FUNC(SetLayeredWindowAttributes)(g_cursorWindow, RGB(0xFF, 0xFF, 0xFF), 0, LWA_COLORKEY);
|
CALL_ORIG_FUNC(SetLayeredWindowAttributes)(g_cursorWindow, RGB(0xFF, 0xFF, 0xFF), 0, LWA_COLORKEY);
|
||||||
|
|
||||||
MONITORINFO mi = {};
|
MONITORINFO mi = {};
|
||||||
@ -266,17 +253,16 @@ namespace Input
|
|||||||
RECT r = window->getRect();
|
RECT r = window->getRect();
|
||||||
g_cursorPos = { (r.left + r.right) / 2, (r.top + r.bottom) / 2 };
|
g_cursorPos = { (r.left + r.right) / 2, (r.top + r.bottom) / 2 };
|
||||||
CALL_ORIG_FUNC(SetWindowPos)(g_cursorWindow, HWND_TOPMOST, g_cursorPos.x, g_cursorPos.y,
|
CALL_ORIG_FUNC(SetWindowPos)(g_cursorWindow, HWND_TOPMOST, g_cursorPos.x, g_cursorPos.y,
|
||||||
g_bmpArrowSize.cx, g_bmpArrowSize.cy, SWP_NOACTIVATE | SWP_NOSENDCHANGING);
|
g_bmpArrowSize.cx, g_bmpArrowSize.cy, SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_SHOWWINDOW);
|
||||||
ShowWindow(g_cursorWindow, SW_SHOW);
|
|
||||||
|
|
||||||
g_mouseHook = CALL_ORIG_FUNC(SetWindowsHookExA)(WH_MOUSE_LL, &lowLevelMouseProc, Dll::g_currentModule, 0);
|
resetMouseHook();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (g_mouseHook)
|
else if (g_mouseHook)
|
||||||
{
|
{
|
||||||
UnhookWindowsHookEx(g_mouseHook);
|
UnhookWindowsHookEx(g_mouseHook);
|
||||||
g_mouseHook = nullptr;
|
g_mouseHook = nullptr;
|
||||||
PostMessage(g_cursorWindow, WM_CLOSE, 0, 0);
|
Gdi::GuiThread::destroyWindow(g_cursorWindow);
|
||||||
g_cursorWindow = nullptr;
|
g_cursorWindow = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include <Dll/Dll.h>
|
#include <Dll/Dll.h>
|
||||||
#include <DDraw/RealPrimarySurface.h>
|
#include <DDraw/RealPrimarySurface.h>
|
||||||
#include <DDraw/Surfaces/PrimarySurface.h>
|
#include <DDraw/Surfaces/PrimarySurface.h>
|
||||||
|
#include <Gdi/GuiThread.h>
|
||||||
#include <Gdi/PresentationWindow.h>
|
#include <Gdi/PresentationWindow.h>
|
||||||
#include <Input/Input.h>
|
#include <Input/Input.h>
|
||||||
#include <Overlay/Control.h>
|
#include <Overlay/Control.h>
|
||||||
@ -46,12 +47,14 @@ namespace Overlay
|
|||||||
{
|
{
|
||||||
Window::Window(Window* parentWindow, const RECT& rect, const Input::HotKey& hotKey)
|
Window::Window(Window* parentWindow, const RECT& rect, const Input::HotKey& hotKey)
|
||||||
: Control(nullptr, rect, WS_BORDER)
|
: Control(nullptr, rect, WS_BORDER)
|
||||||
, m_hwnd(Gdi::PresentationWindow::create(parentWindow ? parentWindow->m_hwnd : nullptr, &staticWindowProc))
|
, m_hwnd(Gdi::PresentationWindow::create(parentWindow ? parentWindow->m_hwnd : nullptr))
|
||||||
, m_parentWindow(parentWindow)
|
, m_parentWindow(parentWindow)
|
||||||
, m_transparency(25)
|
, m_transparency(25)
|
||||||
{
|
{
|
||||||
g_windows.emplace(m_hwnd, *this);
|
g_windows.emplace(m_hwnd, *this);
|
||||||
|
CALL_ORIG_FUNC(SetWindowLongA)(m_hwnd, GWL_WNDPROC, reinterpret_cast<LONG>(&staticWindowProc));
|
||||||
setTransparency(m_transparency);
|
setTransparency(m_transparency);
|
||||||
|
|
||||||
if (0 != hotKey.vk)
|
if (0 != hotKey.vk)
|
||||||
{
|
{
|
||||||
Input::registerHotKey(hotKey, &toggleWindow, this);
|
Input::registerHotKey(hotKey, &toggleWindow, this);
|
||||||
@ -60,7 +63,7 @@ namespace Overlay
|
|||||||
|
|
||||||
Window::~Window()
|
Window::~Window()
|
||||||
{
|
{
|
||||||
Gdi::PresentationWindow::destroy(m_hwnd);
|
Gdi::GuiThread::destroyWindow(m_hwnd);
|
||||||
g_windows.erase(m_hwnd);
|
g_windows.erase(m_hwnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,7 +125,7 @@ namespace Overlay
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto capture = Input::getCapture();
|
auto capture = Input::getCapture();
|
||||||
if (capture != this && capture->m_parentWindow == this)
|
if (capture && capture != this && capture->m_parentWindow == this)
|
||||||
{
|
{
|
||||||
capture->setVisible(false);
|
capture->setVisible(false);
|
||||||
}
|
}
|
||||||
@ -133,7 +136,12 @@ namespace Overlay
|
|||||||
|
|
||||||
LRESULT CALLBACK Window::staticWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
LRESULT CALLBACK Window::staticWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
return g_windows.find(hwnd)->second.windowProc(uMsg, wParam, lParam);
|
auto it = g_windows.find(hwnd);
|
||||||
|
if (it != g_windows.end())
|
||||||
|
{
|
||||||
|
return it->second.windowProc(uMsg, wParam, lParam);
|
||||||
|
}
|
||||||
|
return CALL_ORIG_FUNC(DefWindowProcA)(hwnd, uMsg, wParam, lParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::updatePos()
|
void Window::updatePos()
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include <DDraw/DirectDraw.h>
|
#include <DDraw/DirectDraw.h>
|
||||||
#include <DDraw/ScopedThreadLock.h>
|
#include <DDraw/ScopedThreadLock.h>
|
||||||
#include <Gdi/Gdi.h>
|
#include <Gdi/Gdi.h>
|
||||||
|
#include <Gdi/GuiThread.h>
|
||||||
#include <Gdi/VirtualScreen.h>
|
#include <Gdi/VirtualScreen.h>
|
||||||
#include <Win32/DisplayMode.h>
|
#include <Win32/DisplayMode.h>
|
||||||
|
|
||||||
@ -672,7 +673,7 @@ namespace
|
|||||||
{
|
{
|
||||||
DWORD pid = 0;
|
DWORD pid = 0;
|
||||||
GetWindowThreadProcessId(hwnd, &pid);
|
GetWindowThreadProcessId(hwnd, &pid);
|
||||||
if (GetCurrentProcessId() == pid)
|
if (GetCurrentProcessId() == pid && !Gdi::GuiThread::isGuiThreadWindow(hwnd))
|
||||||
{
|
{
|
||||||
SendNotifyMessage(hwnd, WM_DISPLAYCHANGE, 0, lParam);
|
SendNotifyMessage(hwnd, WM_DISPLAYCHANGE, 0, lParam);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user