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\Dc.h" />
|
||||
<ClInclude Include="Gdi\DcFunctions.h" />
|
||||
<ClInclude Include="Gdi\GuiThread.h" />
|
||||
<ClInclude Include="Gdi\Icon.h" />
|
||||
<ClInclude Include="Gdi\Metrics.h" />
|
||||
<ClInclude Include="Gdi\PresentationWindow.h" />
|
||||
@ -401,6 +402,7 @@
|
||||
<ClCompile Include="Gdi\Caret.cpp" />
|
||||
<ClCompile Include="Gdi\Dc.cpp" />
|
||||
<ClCompile Include="Gdi\DcFunctions.cpp" />
|
||||
<ClCompile Include="Gdi\GuiThread.cpp" />
|
||||
<ClCompile Include="Gdi\Icon.cpp" />
|
||||
<ClCompile Include="Gdi\Metrics.cpp" />
|
||||
<ClCompile Include="Gdi\PresentationWindow.cpp" />
|
||||
@ -454,4 +456,4 @@
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
@ -513,6 +513,9 @@
|
||||
<ClInclude Include="Common\Rect.h">
|
||||
<Filter>Header Files\Common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Gdi\GuiThread.h">
|
||||
<Filter>Header Files\Gdi</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Gdi\Gdi.cpp">
|
||||
@ -809,6 +812,9 @@
|
||||
<ClCompile Include="Common\Rect.cpp">
|
||||
<Filter>Source Files\Common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Gdi\GuiThread.cpp">
|
||||
<Filter>Source Files\Gdi</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="DDrawCompat.rc">
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <Direct3d/Hooks.h>
|
||||
#include <Dll/Dll.h>
|
||||
#include <Gdi/Gdi.h>
|
||||
#include <Gdi/GuiThread.h>
|
||||
#include <Gdi/PresentationWindow.h>
|
||||
#include <Gdi/VirtualScreen.h>
|
||||
#include <Input/Input.h>
|
||||
@ -113,7 +114,7 @@ namespace
|
||||
Compat::Log() << "Installing GDI hooks";
|
||||
Gdi::installHooks();
|
||||
Compat::closeDbgEng();
|
||||
Gdi::PresentationWindow::startThread();
|
||||
Gdi::GuiThread::start();
|
||||
Compat::Log() << "Finished installing hooks";
|
||||
isAlreadyInstalled = true;
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <Gdi/DcFunctions.h>
|
||||
#include <Gdi/Font.h>
|
||||
#include <Gdi/Gdi.h>
|
||||
#include <Gdi/GuiThread.h>
|
||||
#include <Gdi/Icon.h>
|
||||
#include <Gdi/Metrics.h>
|
||||
#include <Gdi/Palette.h>
|
||||
@ -74,6 +75,7 @@ namespace Gdi
|
||||
Caret::installHooks();
|
||||
Cursor::installHooks();
|
||||
Font::installHooks();
|
||||
WinProc::installHooks();
|
||||
}
|
||||
|
||||
bool isDisplayDc(HDC dc)
|
||||
@ -90,7 +92,7 @@ namespace Gdi
|
||||
|
||||
void redrawWindow(HWND hwnd, HRGN rgn)
|
||||
{
|
||||
if (!IsWindowVisible(hwnd) || IsIconic(hwnd) || PresentationWindow::isPresentationWindow(hwnd))
|
||||
if (!IsWindowVisible(hwnd) || IsIconic(hwnd) || GuiThread::isGuiThreadWindow(hwnd))
|
||||
{
|
||||
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)
|
||||
{
|
||||
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();
|
||||
if (activeWindow == dcWindow || IsChild(activeWindow, dcWindow))
|
||||
|
@ -1,160 +1,17 @@
|
||||
#include <Common/Hook.h>
|
||||
#include <Common/Log.h>
|
||||
#include <D3dDdi/ScopedCriticalSection.h>
|
||||
#include <Dll/Dll.h>
|
||||
#include <Gdi/GuiThread.h>
|
||||
#include <Gdi/PresentationWindow.h>
|
||||
#include <Gdi/WinProc.h>
|
||||
#include <Overlay/ConfigWindow.h>
|
||||
#include <Win32/DisplayMode.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
const UINT WM_CREATEPRESENTATIONWINDOW = WM_USER;
|
||||
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));
|
||||
}
|
||||
ATOM g_classAtom = 0;
|
||||
|
||||
LRESULT CALLBACK presentationWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
LOG_FUNC("presentationWindowProc", Compat::WindowMessageStruct(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;
|
||||
return CALL_ORIG_FUNC(DefWindowProcA)(hwnd, uMsg, wParam, lParam);
|
||||
}
|
||||
}
|
||||
|
||||
@ -162,20 +19,28 @@ namespace Gdi
|
||||
{
|
||||
namespace PresentationWindow
|
||||
{
|
||||
HWND create(HWND owner, WNDPROC wndProc)
|
||||
HWND create(HWND owner)
|
||||
{
|
||||
return reinterpret_cast<HWND>(sendMessageBlocking(g_messageWindow, WM_CREATEPRESENTATIONWINDOW,
|
||||
reinterpret_cast<WPARAM>(owner), reinterpret_cast<LPARAM>(wndProc)));
|
||||
}
|
||||
HWND presentationWindow = nullptr;
|
||||
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)
|
||||
{
|
||||
PostMessage(hwnd, WM_CLOSE, 0, 0);
|
||||
}
|
||||
|
||||
Overlay::ConfigWindow* getConfigWindow()
|
||||
{
|
||||
return g_configWindow;
|
||||
if (presentationWindow)
|
||||
{
|
||||
CALL_ORIG_FUNC(SetLayeredWindowAttributes)(presentationWindow, 0, 255, LWA_ALPHA);
|
||||
}
|
||||
});
|
||||
return presentationWindow;
|
||||
}
|
||||
|
||||
void installHooks()
|
||||
@ -184,35 +49,7 @@ namespace Gdi
|
||||
wc.lpfnWndProc = &presentationWindowProc;
|
||||
wc.hInstance = Dll::g_currentModule;
|
||||
wc.lpszClassName = "DDrawCompatPresentationWindow";
|
||||
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);
|
||||
g_classAtom = CALL_ORIG_FUNC(RegisterClassA)(&wc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,23 +2,11 @@
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
namespace Overlay
|
||||
{
|
||||
class ConfigWindow;
|
||||
}
|
||||
|
||||
namespace Gdi
|
||||
{
|
||||
namespace PresentationWindow
|
||||
{
|
||||
HWND create(HWND owner, WNDPROC wndProc = nullptr);
|
||||
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();
|
||||
HWND create(HWND owner);
|
||||
|
||||
void installHooks();
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include <DDraw/Surfaces/PrimarySurface.h>
|
||||
#include <Gdi/CompatDc.h>
|
||||
#include <Gdi/Cursor.h>
|
||||
#include <Gdi/PresentationWindow.h>
|
||||
#include <Gdi/GuiThread.h>
|
||||
#include <Gdi/ScrollBar.h>
|
||||
#include <Gdi/ScrollFunctions.h>
|
||||
#include <Gdi/TitleBar.h>
|
||||
@ -319,7 +319,7 @@ namespace
|
||||
if (wp.x + wp.cx > mr.right)
|
||||
{
|
||||
HWND parent = GetNextWindow(wp.hwnd, GW_HWNDNEXT);
|
||||
while (Gdi::PresentationWindow::isPresentationWindow(parent))
|
||||
while (Gdi::GuiThread::isGuiThreadWindow(parent))
|
||||
{
|
||||
parent = GetNextWindow(parent, GW_HWNDNEXT);
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <Gdi/Cursor.h>
|
||||
#include <Gdi/Dc.h>
|
||||
#include <Gdi/Gdi.h>
|
||||
#include <Gdi/GuiThread.h>
|
||||
#include <Gdi/PresentationWindow.h>
|
||||
#include <Gdi/ScrollBar.h>
|
||||
#include <Gdi/ScrollFunctions.h>
|
||||
@ -39,7 +40,6 @@ namespace
|
||||
WindowProc getWindowProc(HWND hwnd);
|
||||
bool isTopLevelWindow(HWND hwnd);
|
||||
bool isUser32ScrollBar(HWND hwnd);
|
||||
void onCreateWindow(HWND hwnd);
|
||||
void onDestroyWindow(HWND hwnd);
|
||||
void onGetMinMaxInfo(MINMAXINFO& mmi);
|
||||
void onInitMenuPopup(HMENU menu);
|
||||
@ -95,12 +95,15 @@ namespace
|
||||
case WM_ACTIVATEAPP:
|
||||
if (!wParam)
|
||||
{
|
||||
auto configWindow = Gdi::PresentationWindow::getConfigWindow();
|
||||
if (configWindow)
|
||||
{
|
||||
configWindow->setVisible(false);
|
||||
}
|
||||
CALL_ORIG_FUNC(ClipCursor)(nullptr);
|
||||
Gdi::GuiThread::execute([&]()
|
||||
{
|
||||
auto configWindow = Gdi::GuiThread::getConfigWindow();
|
||||
if (configWindow)
|
||||
{
|
||||
configWindow->setVisible(false);
|
||||
}
|
||||
CALL_ORIG_FUNC(ClipCursor)(nullptr);
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
||||
@ -202,40 +205,6 @@ namespace
|
||||
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)
|
||||
{
|
||||
if (isTopLevelWindow(hwnd))
|
||||
@ -415,9 +384,9 @@ namespace
|
||||
switch (event)
|
||||
{
|
||||
case EVENT_OBJECT_CREATE:
|
||||
if (OBJID_WINDOW == idObject && !Gdi::PresentationWindow::isPresentationWindow(hwnd))
|
||||
if (OBJID_WINDOW == idObject)
|
||||
{
|
||||
onCreateWindow(hwnd);
|
||||
Gdi::WinProc::onCreateWindow(hwnd);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -511,10 +480,40 @@ namespace Gdi
|
||||
|
||||
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)
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <D3dDdi/ScopedCriticalSection.h>
|
||||
#include <DDraw/RealPrimarySurface.h>
|
||||
#include <Gdi/Gdi.h>
|
||||
#include <Gdi/GuiThread.h>
|
||||
#include <Gdi/PresentationWindow.h>
|
||||
#include <Gdi/VirtualScreen.h>
|
||||
#include <Gdi/Window.h>
|
||||
@ -249,7 +250,7 @@ namespace
|
||||
DWORD processId = 0;
|
||||
GetWindowThreadProcessId(hwnd, &processId);
|
||||
if (processId != context.processId ||
|
||||
Gdi::PresentationWindow::isPresentationWindow(hwnd))
|
||||
Gdi::GuiThread::isGuiThreadWindow(hwnd))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
@ -277,7 +278,7 @@ namespace
|
||||
}
|
||||
else if (it->second.presentationWindow)
|
||||
{
|
||||
Gdi::PresentationWindow::destroy(it->second.presentationWindow);
|
||||
Gdi::GuiThread::destroyWindow(it->second.presentationWindow);
|
||||
it->second.presentationWindow = nullptr;
|
||||
}
|
||||
}
|
||||
@ -351,7 +352,7 @@ namespace
|
||||
{
|
||||
if (setPresentationWindowRgn)
|
||||
{
|
||||
Gdi::PresentationWindow::setWindowRgn(it->second.presentationWindow, it->second.windowRegion);
|
||||
Gdi::GuiThread::setWindowRgn(it->second.presentationWindow, it->second.windowRegion);
|
||||
}
|
||||
|
||||
WINDOWPOS wp = {};
|
||||
@ -379,7 +380,11 @@ namespace
|
||||
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;
|
||||
@ -524,7 +529,7 @@ namespace Gdi
|
||||
}
|
||||
|
||||
RECT wr = {};
|
||||
auto configWindow = PresentationWindow::getConfigWindow();
|
||||
auto configWindow = GuiThread::getConfigWindow();
|
||||
if (configWindow && configWindow->isVisible())
|
||||
{
|
||||
GetWindowRect(configWindow->getWindow(), &wr);
|
||||
@ -550,7 +555,7 @@ namespace Gdi
|
||||
void updateAll()
|
||||
{
|
||||
LOG_FUNC("Window::updateAll");
|
||||
if (!Gdi::PresentationWindow::isThreadReady())
|
||||
if (!GuiThread::isReady())
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -571,7 +576,7 @@ namespace Gdi
|
||||
{
|
||||
if (it->second.presentationWindow)
|
||||
{
|
||||
Gdi::PresentationWindow::destroy(it->second.presentationWindow);
|
||||
GuiThread::destroyWindow(it->second.presentationWindow);
|
||||
}
|
||||
it = g_windows.erase(it);
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <Common/Log.h>
|
||||
#include <Dll/Dll.h>
|
||||
#include <DDraw/RealPrimarySurface.h>
|
||||
#include <Gdi/GuiThread.h>
|
||||
#include <Gdi/PresentationWindow.h>
|
||||
#include <Input/Input.h>
|
||||
#include <Overlay/Window.h>
|
||||
@ -21,9 +22,6 @@ namespace
|
||||
void* context;
|
||||
};
|
||||
|
||||
const UINT WM_USER_HOTKEY = WM_USER;
|
||||
const UINT WM_USER_RESET_HOOK = WM_USER + 1;
|
||||
|
||||
HANDLE g_bmpArrow = nullptr;
|
||||
SIZE g_bmpArrowSize = {};
|
||||
Overlay::Window* g_capture = nullptr;
|
||||
@ -31,7 +29,6 @@ namespace
|
||||
HWND g_cursorWindow = nullptr;
|
||||
std::map<Input::HotKey, HotKeyData> g_hotKeys;
|
||||
RECT g_monitorRect = {};
|
||||
DWORD g_inputThreadId = 0;
|
||||
HHOOK g_keyboardHook = nullptr;
|
||||
HHOOK g_mouseHook = nullptr;
|
||||
|
||||
@ -65,72 +62,22 @@ namespace
|
||||
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)
|
||||
{
|
||||
if (HC_ACTION == nCode && (WM_KEYDOWN == wParam || WM_SYSKEYDOWN == wParam))
|
||||
{
|
||||
auto llHook = reinterpret_cast<const KBDLLHOOKSTRUCT*>(lParam);
|
||||
PostThreadMessage(GetCurrentThreadId(), WM_USER_HOTKEY, llHook->vkCode, llHook->scanCode);
|
||||
DWORD pid = 0;
|
||||
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);
|
||||
}
|
||||
@ -174,6 +121,32 @@ namespace
|
||||
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)
|
||||
{
|
||||
g_cursorPos = cp;
|
||||
@ -191,9 +164,16 @@ namespace
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@ -235,16 +215,22 @@ namespace Input
|
||||
|
||||
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, SetWindowsHookExW, setWindowsHookExW);
|
||||
}
|
||||
|
||||
void registerHotKey(const HotKey& hotKey, std::function<void(void*)> action, void* context)
|
||||
{
|
||||
static HANDLE thread = Dll::createThread(&inputThreadProc, nullptr, THREAD_PRIORITY_TIME_CRITICAL);
|
||||
if (thread)
|
||||
g_hotKeys[hotKey] = { action, context };
|
||||
if (!g_keyboardHook)
|
||||
{
|
||||
g_hotKeys[hotKey] = { action, context };
|
||||
resetKeyboardHook();
|
||||
}
|
||||
}
|
||||
|
||||
@ -255,7 +241,8 @@ namespace Input
|
||||
{
|
||||
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);
|
||||
|
||||
MONITORINFO mi = {};
|
||||
@ -266,17 +253,16 @@ namespace Input
|
||||
RECT r = window->getRect();
|
||||
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,
|
||||
g_bmpArrowSize.cx, g_bmpArrowSize.cy, SWP_NOACTIVATE | SWP_NOSENDCHANGING);
|
||||
ShowWindow(g_cursorWindow, SW_SHOW);
|
||||
g_bmpArrowSize.cx, g_bmpArrowSize.cy, SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_SHOWWINDOW);
|
||||
|
||||
g_mouseHook = CALL_ORIG_FUNC(SetWindowsHookExA)(WH_MOUSE_LL, &lowLevelMouseProc, Dll::g_currentModule, 0);
|
||||
resetMouseHook();
|
||||
}
|
||||
}
|
||||
else if (g_mouseHook)
|
||||
{
|
||||
UnhookWindowsHookEx(g_mouseHook);
|
||||
g_mouseHook = nullptr;
|
||||
PostMessage(g_cursorWindow, WM_CLOSE, 0, 0);
|
||||
Gdi::GuiThread::destroyWindow(g_cursorWindow);
|
||||
g_cursorWindow = nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <Dll/Dll.h>
|
||||
#include <DDraw/RealPrimarySurface.h>
|
||||
#include <DDraw/Surfaces/PrimarySurface.h>
|
||||
#include <Gdi/GuiThread.h>
|
||||
#include <Gdi/PresentationWindow.h>
|
||||
#include <Input/Input.h>
|
||||
#include <Overlay/Control.h>
|
||||
@ -46,12 +47,14 @@ namespace Overlay
|
||||
{
|
||||
Window::Window(Window* parentWindow, const RECT& rect, const Input::HotKey& hotKey)
|
||||
: 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_transparency(25)
|
||||
{
|
||||
g_windows.emplace(m_hwnd, *this);
|
||||
CALL_ORIG_FUNC(SetWindowLongA)(m_hwnd, GWL_WNDPROC, reinterpret_cast<LONG>(&staticWindowProc));
|
||||
setTransparency(m_transparency);
|
||||
|
||||
if (0 != hotKey.vk)
|
||||
{
|
||||
Input::registerHotKey(hotKey, &toggleWindow, this);
|
||||
@ -60,7 +63,7 @@ namespace Overlay
|
||||
|
||||
Window::~Window()
|
||||
{
|
||||
Gdi::PresentationWindow::destroy(m_hwnd);
|
||||
Gdi::GuiThread::destroyWindow(m_hwnd);
|
||||
g_windows.erase(m_hwnd);
|
||||
}
|
||||
|
||||
@ -122,7 +125,7 @@ namespace Overlay
|
||||
else
|
||||
{
|
||||
auto capture = Input::getCapture();
|
||||
if (capture != this && capture->m_parentWindow == this)
|
||||
if (capture && capture != this && capture->m_parentWindow == this)
|
||||
{
|
||||
capture->setVisible(false);
|
||||
}
|
||||
@ -133,7 +136,12 @@ namespace Overlay
|
||||
|
||||
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()
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <DDraw/DirectDraw.h>
|
||||
#include <DDraw/ScopedThreadLock.h>
|
||||
#include <Gdi/Gdi.h>
|
||||
#include <Gdi/GuiThread.h>
|
||||
#include <Gdi/VirtualScreen.h>
|
||||
#include <Win32/DisplayMode.h>
|
||||
|
||||
@ -672,7 +673,7 @@ namespace
|
||||
{
|
||||
DWORD pid = 0;
|
||||
GetWindowThreadProcessId(hwnd, &pid);
|
||||
if (GetCurrentProcessId() == pid)
|
||||
if (GetCurrentProcessId() == pid && !Gdi::GuiThread::isGuiThreadWindow(hwnd))
|
||||
{
|
||||
SendNotifyMessage(hwnd, WM_DISPLAYCHANGE, 0, lParam);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user