diff --git a/DDrawCompat/DDrawCompat.vcxproj b/DDrawCompat/DDrawCompat.vcxproj
index 8d80be5..c122075 100644
--- a/DDrawCompat/DDrawCompat.vcxproj
+++ b/DDrawCompat/DDrawCompat.vcxproj
@@ -221,6 +221,7 @@
+
@@ -294,6 +295,7 @@
+
diff --git a/DDrawCompat/DDrawCompat.vcxproj.filters b/DDrawCompat/DDrawCompat.vcxproj.filters
index d4ec640..3aa806d 100644
--- a/DDrawCompat/DDrawCompat.vcxproj.filters
+++ b/DDrawCompat/DDrawCompat.vcxproj.filters
@@ -399,6 +399,9 @@
Header Files\Gdi
+
+ Header Files\Gdi
+
@@ -614,5 +617,8 @@
Source Files\Gdi
+
+ Source Files\Gdi
+
\ No newline at end of file
diff --git a/DDrawCompat/Gdi/Gdi.cpp b/DDrawCompat/Gdi/Gdi.cpp
index e1a1a67..a12b587 100644
--- a/DDrawCompat/Gdi/Gdi.cpp
+++ b/DDrawCompat/Gdi/Gdi.cpp
@@ -6,9 +6,9 @@
#include
#include
#include
+#include
#include
#include
-#include
#include
namespace
@@ -38,9 +38,9 @@ namespace Gdi
{
DcFunctions::installHooks();
Palette::installHooks();
+ PresentationWindow::installHooks();
ScrollFunctions::installHooks();
User32WndProcs::installHooks();
- Window::installHooks();
WinProc::installHooks();
Caret::installHooks();
Font::installHooks();
@@ -59,7 +59,7 @@ namespace Gdi
void redrawWindow(HWND hwnd, HRGN rgn)
{
- if (!IsWindowVisible(hwnd) || IsIconic(hwnd) || Window::isPresentationWindow(hwnd))
+ if (!IsWindowVisible(hwnd) || IsIconic(hwnd) || PresentationWindow::isPresentationWindow(hwnd))
{
return;
}
@@ -89,8 +89,8 @@ namespace Gdi
void uninstallHooks()
{
Caret::uninstallHooks();
+ PresentationWindow::uninstallHooks();
WinProc::uninstallHooks();
- Window::uninstallHooks();
Dc::dllProcessDetach();
DcCache::dllProcessDetach();
}
diff --git a/DDrawCompat/Gdi/PresentationWindow.cpp b/DDrawCompat/Gdi/PresentationWindow.cpp
new file mode 100644
index 0000000..80bb889
--- /dev/null
+++ b/DDrawCompat/Gdi/PresentationWindow.cpp
@@ -0,0 +1,185 @@
+#include
+#include
+#include
+#include
+
+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;
+ DWORD g_presentationWindowThreadId = 0;
+ HWND g_messageWindow = nullptr;
+
+ 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(
+ Compat::getProcAddress(GetModuleHandle("user32"), "CreateWindowExA"));
+
+ HWND owner = reinterpret_cast(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)
+ {
+ CALL_ORIG_FUNC(SetLayeredWindowAttributes)(presentationWindow, 0, 255, LWA_ALPHA);
+ }
+
+ return LOG_RESULT(reinterpret_cast(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)
+ {
+ LOG_FUNC("presentationWindowProc", Compat::WindowMessageStruct(hwnd, uMsg, wParam, lParam));
+
+ switch (uMsg)
+ {
+ case WM_SETPRESENTATIONWINDOWPOS:
+ {
+ const auto& wp = *reinterpret_cast(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(wParam), nullptr, RGN_COPY);
+ }
+ return SetWindowRgn(hwnd, rgn, FALSE);
+ }
+ }
+
+ return CALL_ORIG_FUNC(DefWindowProc)(hwnd, uMsg, wParam, lParam);
+ }
+
+ DWORD WINAPI presentationWindowThreadProc(LPVOID /*lpParameter*/)
+ {
+ SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
+
+ WNDCLASS wc = {};
+ wc.lpfnWndProc = &messageWindowProc;
+ wc.hInstance = Dll::g_currentModule;
+ wc.lpszClassName = "DDrawCompatMessageWindow";
+ RegisterClass(&wc);
+
+ g_messageWindow = CreateWindow(
+ "DDrawCompatMessageWindow", nullptr, 0, 0, 0, 0, 0, HWND_MESSAGE, nullptr, nullptr, nullptr);
+ if (!g_messageWindow)
+ {
+ return 0;
+ }
+
+ 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;
+ }
+}
+
+namespace Gdi
+{
+ namespace PresentationWindow
+ {
+ HWND create(HWND owner)
+ {
+ return reinterpret_cast(sendMessageBlocking(
+ g_messageWindow, WM_CREATEPRESENTATIONWINDOW, reinterpret_cast(owner), 0));
+ }
+
+ void destroy(HWND hwnd)
+ {
+ sendMessageBlocking(hwnd, WM_CLOSE, 0, 0);
+ }
+
+ void installHooks()
+ {
+ WNDCLASS wc = {};
+ wc.lpfnWndProc = &presentationWindowProc;
+ wc.hInstance = Dll::g_currentModule;
+ wc.lpszClassName = "DDrawCompatPresentationWindow";
+ RegisterClass(&wc);
+
+ g_presentationWindowThread = CreateThread(
+ nullptr, 0, &presentationWindowThreadProc, nullptr, 0, &g_presentationWindowThreadId);
+
+ int i = 0;
+ while (!g_messageWindow && i < 1000)
+ {
+ Sleep(1);
+ ++i;
+ }
+
+ if (!g_messageWindow)
+ {
+ Compat::Log() << "ERROR: Failed to create a message-only window";
+ }
+ }
+
+ bool isPresentationWindow(HWND hwnd)
+ {
+ return GetWindowThreadProcessId(hwnd, nullptr) == g_presentationWindowThreadId;
+ }
+
+ void setWindowPos(HWND hwnd, const WINDOWPOS& wp)
+ {
+ sendMessageBlocking(hwnd, WM_SETPRESENTATIONWINDOWPOS, 0, reinterpret_cast(&wp));
+ }
+
+ void setWindowRgn(HWND hwnd, HRGN rgn)
+ {
+ sendMessageBlocking(hwnd, WM_SETPRESENTATIONWINDOWRGN, reinterpret_cast(rgn), 0);
+ }
+
+ void uninstallHooks()
+ {
+ if (g_presentationWindowThread)
+ {
+ sendMessageBlocking(g_messageWindow, WM_CLOSE, 0, 0);
+ if (WAIT_OBJECT_0 != WaitForSingleObject(g_presentationWindowThread, 1000))
+ {
+ TerminateThread(g_presentationWindowThread, 0);
+ Compat::Log() << "The presentation window thread was terminated forcefully";
+ }
+ }
+ }
+ }
+}
diff --git a/DDrawCompat/Gdi/PresentationWindow.h b/DDrawCompat/Gdi/PresentationWindow.h
new file mode 100644
index 0000000..93102a4
--- /dev/null
+++ b/DDrawCompat/Gdi/PresentationWindow.h
@@ -0,0 +1,18 @@
+#pragma once
+
+#include
+
+namespace Gdi
+{
+ namespace PresentationWindow
+ {
+ HWND create(HWND owner);
+ void destroy(HWND hwnd);
+ bool isPresentationWindow(HWND hwnd);
+ void setWindowPos(HWND hwnd, const WINDOWPOS& wp);
+ void setWindowRgn(HWND hwnd, HRGN rgn);
+
+ void installHooks();
+ void uninstallHooks();
+ }
+}
diff --git a/DDrawCompat/Gdi/WinProc.cpp b/DDrawCompat/Gdi/WinProc.cpp
index 0c79867..7e79422 100644
--- a/DDrawCompat/Gdi/WinProc.cpp
+++ b/DDrawCompat/Gdi/WinProc.cpp
@@ -9,12 +9,13 @@
#include
#include
#include
-#include
+#include
#include
#include
#include
#include
#include
+#include
namespace
{
@@ -171,7 +172,7 @@ namespace
DWORD /*dwEventThread*/,
DWORD /*dwmsEventTime*/)
{
- if (OBJID_WINDOW == idObject && !Gdi::Window::isPresentationWindow(hwnd))
+ if (OBJID_WINDOW == idObject && !Gdi::PresentationWindow::isPresentationWindow(hwnd))
{
onCreateWindow(hwnd);
}
diff --git a/DDrawCompat/Gdi/Window.cpp b/DDrawCompat/Gdi/Window.cpp
index 95d9ec5..e8940a8 100644
--- a/DDrawCompat/Gdi/Window.cpp
+++ b/DDrawCompat/Gdi/Window.cpp
@@ -4,12 +4,11 @@
#include
-#include
#include
#include
#include
#include
-#include
+#include
#include
#include
@@ -50,14 +49,8 @@ namespace
}
};
- const UINT WM_CREATEPRESENTATIONWINDOW = WM_USER;
- const UINT WM_SETPRESENTATIONWINDOWPOS = WM_USER + 1;
- const UINT WM_SETPRESENTATIONWINDOWRGN = WM_USER + 2;
const RECT REGION_OVERRIDE_MARKER_RECT = { 32000, 32000, 32001, 32001 };
- HANDLE g_presentationWindowThread = nullptr;
- DWORD g_presentationWindowThreadId = 0;
- HWND g_messageWindow = nullptr;
std::map g_windows;
std::vector g_windowZOrder;
@@ -102,107 +95,6 @@ namespace
return rgn;
}
- 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(
- Compat::getProcAddress(GetModuleHandle("user32"), "CreateWindowExA"));
-
- HWND owner = reinterpret_cast(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)
- {
- CALL_ORIG_FUNC(SetLayeredWindowAttributes)(presentationWindow, 0, 255, LWA_ALPHA);
- }
-
- return reinterpret_cast(presentationWindow);
- }
-
- case WM_DESTROY:
- PostQuitMessage(0);
- return 0;
-
- default:
- return CALL_ORIG_FUNC(DefWindowProc)(hwnd, uMsg, wParam, lParam);
- }
- }
-
- 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(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(wParam), nullptr, RGN_COPY);
- }
- return SetWindowRgn(hwnd, rgn, FALSE);
- }
- }
-
- return CALL_ORIG_FUNC(DefWindowProc)(hwnd, uMsg, wParam, lParam);
- }
-
- DWORD WINAPI presentationWindowThreadProc(LPVOID /*lpParameter*/)
- {
- SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
-
- WNDCLASS wc = {};
- wc.lpfnWndProc = &messageWindowProc;
- wc.hInstance = Dll::g_currentModule;
- wc.lpszClassName = "DDrawCompatMessageWindow";
- RegisterClass(&wc);
-
- g_messageWindow = CreateWindow(
- "DDrawCompatMessageWindow", nullptr, 0, 0, 0, 0, 0, HWND_MESSAGE, nullptr, nullptr, nullptr);
- if (!g_messageWindow)
- {
- return 0;
- }
-
- 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;
- }
-
void updatePosition(Window& window, const RECT& oldWindowRect, const RECT& oldClientRect,
const Gdi::Region& oldVisibleRegion)
{
@@ -286,8 +178,8 @@ namespace
DWORD processId = 0;
GetWindowThreadProcessId(hwnd, &processId);
- if (GetWindowThreadProcessId(hwnd, &processId) == g_presentationWindowThreadId ||
- processId != context.processId)
+ if (processId != context.processId ||
+ Gdi::PresentationWindow::isPresentationWindow(hwnd))
{
return TRUE;
}
@@ -310,13 +202,12 @@ namespace
it->second.isVisibleRegionChanged = isVisible;
if (!isLayered)
{
- it->second.presentationWindow = reinterpret_cast(
- sendMessageBlocking(g_messageWindow, WM_CREATEPRESENTATIONWINDOW, reinterpret_cast(hwnd), 0));
+ it->second.presentationWindow = Gdi::PresentationWindow::create(hwnd);
setPresentationWindowRgn = true;
}
else if (it->second.presentationWindow)
{
- sendMessageBlocking(it->second.presentationWindow, WM_CLOSE, 0, 0);
+ Gdi::PresentationWindow::destroy(it->second.presentationWindow);
it->second.presentationWindow = nullptr;
}
}
@@ -382,9 +273,7 @@ namespace
{
if (setPresentationWindowRgn)
{
- HRGN rgn = it->second.windowRegion;
- sendMessageBlocking(it->second.presentationWindow, WM_SETPRESENTATIONWINDOWRGN,
- reinterpret_cast(rgn), 0);
+ Gdi::PresentationWindow::setWindowRgn(it->second.presentationWindow, it->second.windowRegion);
}
WINDOWPOS wp = {};
@@ -412,8 +301,7 @@ namespace
wp.flags |= SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER;
}
- sendMessageBlocking(it->second.presentationWindow, WM_SETPRESENTATIONWINDOWPOS,
- 0, reinterpret_cast(&wp));
+ Gdi::PresentationWindow::setWindowPos(it->second.presentationWindow, wp);
}
}
return TRUE;
@@ -424,35 +312,6 @@ namespace Gdi
{
namespace Window
{
- void installHooks()
- {
- WNDCLASS wc = {};
- wc.lpfnWndProc = &presentationWindowProc;
- wc.hInstance = Dll::g_currentModule;
- wc.lpszClassName = "DDrawCompatPresentationWindow";
- RegisterClass(&wc);
-
- g_presentationWindowThread = CreateThread(
- nullptr, 0, &presentationWindowThreadProc, nullptr, 0, &g_presentationWindowThreadId);
-
- int i = 0;
- while (!g_messageWindow && i < 1000)
- {
- Sleep(1);
- ++i;
- }
-
- if (!g_messageWindow)
- {
- Compat::Log() << "ERROR: Failed to create a message-only window";
- }
- }
-
- bool isPresentationWindow(HWND hwnd)
- {
- return g_presentationWindowThreadId == GetWindowThreadProcessId(hwnd, nullptr);
- }
-
void onStyleChanged(HWND hwnd, WPARAM wParam)
{
if (GWL_EXSTYLE == wParam)
@@ -655,7 +514,7 @@ namespace Gdi
{
if (it->second.presentationWindow)
{
- sendMessageBlocking(it->second.presentationWindow, WM_CLOSE, 0, 0);
+ Gdi::PresentationWindow::destroy(it->second.presentationWindow);
}
it = g_windows.erase(it);
}
@@ -695,18 +554,5 @@ namespace Gdi
}
}
}
-
- void uninstallHooks()
- {
- if (g_presentationWindowThread)
- {
- sendMessageBlocking(g_messageWindow, WM_CLOSE, 0, 0);
- if (WAIT_OBJECT_0 != WaitForSingleObject(g_presentationWindowThread, 1000))
- {
- TerminateThread(g_presentationWindowThread, 0);
- Compat::Log() << "The presentation window thread was terminated forcefully";
- }
- }
- }
}
}
diff --git a/DDrawCompat/Gdi/Window.h b/DDrawCompat/Gdi/Window.h
index 654febd..38bb546 100644
--- a/DDrawCompat/Gdi/Window.h
+++ b/DDrawCompat/Gdi/Window.h
@@ -9,7 +9,6 @@ namespace Gdi
{
namespace Window
{
- bool isPresentationWindow(HWND hwnd);
void onStyleChanged(HWND hwnd, WPARAM wParam);
void onSyncPaint(HWND hwnd);
void present(CompatRef dst, CompatRef src,
@@ -18,8 +17,5 @@ namespace Gdi
void presentLayered(CompatRef dst, POINT offset);
void updateAll();
void updateLayeredWindowInfo(HWND hwnd, COLORREF colorKey, BYTE alpha);
-
- void installHooks();
- void uninstallHooks();
}
}