From 6850fc449cb002ff1c1ad78018c2b81391eac911 Mon Sep 17 00:00:00 2001 From: narzoul Date: Sat, 19 Mar 2016 21:41:04 +0100 Subject: [PATCH] Moved WM_ERASEBKGND handling to DefWindowProc Unfortunately, Edit and ListBox controls don't seem to handle WM_ERASEBKGND through DefWindowProc, so their window procedures need additional hooking. --- DDrawCompat/CompatGdi.cpp | 8 ++++ DDrawCompat/CompatGdi.h | 1 + DDrawCompat/CompatGdiPaintHandlers.cpp | 65 ++++++++++++++++++++++++++ DDrawCompat/CompatGdiWinProc.cpp | 22 --------- 4 files changed, 74 insertions(+), 22 deletions(-) diff --git a/DDrawCompat/CompatGdi.cpp b/DDrawCompat/CompatGdi.cpp index 59497dc..584f5ae 100644 --- a/DDrawCompat/CompatGdi.cpp +++ b/DDrawCompat/CompatGdi.cpp @@ -273,6 +273,14 @@ namespace CompatGdi } } + void hookWndProc(LPCSTR className, WNDPROC &oldWndProc, WNDPROC newWndProc) + { + HWND hwnd = CreateWindow(className, nullptr, 0, 0, 0, 0, 0, nullptr, nullptr, nullptr, 0); + oldWndProc = reinterpret_cast( + SetClassLongPtr(hwnd, GCLP_WNDPROC, reinterpret_cast(newWndProc))); + DestroyWindow(hwnd); + } + void installHooks() { InitializeCriticalSection(&g_gdiCriticalSection); diff --git a/DDrawCompat/CompatGdi.h b/DDrawCompat/CompatGdi.h index 633348f..6e5b6aa 100644 --- a/DDrawCompat/CompatGdi.h +++ b/DDrawCompat/CompatGdi.h @@ -47,6 +47,7 @@ namespace CompatGdi reinterpret_cast(getOrigFuncPtr()), newFuncPtr); } + void hookWndProc(LPCSTR className, WNDPROC &oldWndProc, WNDPROC newWndProc); void installHooks(); void invalidate(const RECT* rect); void updatePalette(); diff --git a/DDrawCompat/CompatGdiPaintHandlers.cpp b/DDrawCompat/CompatGdiPaintHandlers.cpp index e4ff5f3..c92ef35 100644 --- a/DDrawCompat/CompatGdiPaintHandlers.cpp +++ b/DDrawCompat/CompatGdiPaintHandlers.cpp @@ -10,9 +10,15 @@ namespace { LRESULT WINAPI defWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, WNDPROC origDefWindowProc, const char* funcName); + LRESULT WINAPI eraseBackgroundProc( + HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, WNDPROC origWndProc, const char* wndProcName); + LRESULT onEraseBackground(HWND hwnd, HDC dc, WNDPROC origWndProc); LRESULT onNcPaint(HWND hwnd, WPARAM wParam, WNDPROC origWndProc); LRESULT onPrint(HWND hwnd, UINT msg, HDC dc, LONG flags, WNDPROC origWndProc); + WNDPROC g_origEditWndProc = nullptr; + WNDPROC g_origListBoxWndProc = nullptr; + LRESULT WINAPI defDlgProcA(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam) { return defWindowProc(hdlg, msg, wParam, lParam, CALL_ORIG_GDI(DefDlgProcA), "defDlgProcA"); @@ -36,6 +42,10 @@ namespace switch (msg) { + case WM_ERASEBKGND: + result = onEraseBackground(hwnd, reinterpret_cast(wParam), origDefWindowProc); + break; + case WM_NCPAINT: result = onNcPaint(hwnd, wParam, origDefWindowProc); break; @@ -64,6 +74,58 @@ namespace return defWindowProc(hwnd, msg, wParam, lParam, CALL_ORIG_GDI(DefWindowProcW), "defWindowProcW"); } + LRESULT WINAPI editWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) + { + return eraseBackgroundProc(hwnd, msg, wParam, lParam, g_origEditWndProc, "editWndProc"); + } + + LRESULT WINAPI eraseBackgroundProc( + HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, WNDPROC origWndProc, const char* wndProcName) + { + Compat::LogEnter(wndProcName, hwnd, msg, wParam, lParam); + + LPARAM result = 0; + if (WM_ERASEBKGND == msg) + { + result = onEraseBackground(hwnd, reinterpret_cast(wParam), origWndProc); + } + else + { + result = origWndProc(hwnd, msg, wParam, lParam); + } + + Compat::LogLeave(wndProcName, hwnd, msg, wParam, lParam) << result; + return result; + } + + LRESULT WINAPI listBoxWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) + { + return eraseBackgroundProc(hwnd, msg, wParam, lParam, g_origListBoxWndProc, "listBoxWndProc"); + } + + LRESULT onEraseBackground(HWND hwnd, HDC dc, WNDPROC origWndProc) + { + if (!hwnd || !CompatGdi::beginGdiRendering()) + { + return origWndProc(hwnd, WM_ERASEBKGND, reinterpret_cast(dc) , 0); + } + + LRESULT result = 0; + HDC compatDc = CompatGdiDc::getDc(dc); + if (compatDc) + { + result = origWndProc(hwnd, WM_ERASEBKGND, reinterpret_cast(compatDc), 0); + CompatGdiDc::releaseDc(dc); + } + else + { + result = origWndProc(hwnd, WM_ERASEBKGND, reinterpret_cast(dc), 0); + } + + CompatGdi::endGdiRendering(); + return result; + } + LRESULT onNcPaint(HWND hwnd, WPARAM wParam, WNDPROC origWndProc) { if (!hwnd || !CompatGdi::beginGdiRendering()) @@ -122,6 +184,9 @@ namespace CompatGdiPaintHandlers { void installHooks() { + CompatGdi::hookWndProc("Edit", g_origEditWndProc, &editWndProc); + CompatGdi::hookWndProc("ListBox", g_origListBoxWndProc, &listBoxWndProc); + DetourTransactionBegin(); HOOK_GDI_FUNCTION(user32, DefWindowProcA, defWindowProcA); HOOK_GDI_FUNCTION(user32, DefWindowProcW, defWindowProcW); diff --git a/DDrawCompat/CompatGdiWinProc.cpp b/DDrawCompat/CompatGdiWinProc.cpp index 6cda9d8..da3e6ad 100644 --- a/DDrawCompat/CompatGdiWinProc.cpp +++ b/DDrawCompat/CompatGdiWinProc.cpp @@ -18,7 +18,6 @@ namespace std::unordered_map g_prevWindowRect; void disableDwmAttributes(HWND hwnd); - void eraseBackground(HWND hwnd, HDC dc); void onWindowPosChanged(HWND hwnd); void removeDropShadow(HWND hwnd); @@ -39,13 +38,6 @@ namespace CompatGdi::GdiScopedThreadLock lock; g_prevWindowRect.erase(ret->hwnd); } - else if (WM_ERASEBKGND == ret->message) - { - if (0 != ret->lResult) - { - eraseBackground(ret->hwnd, reinterpret_cast(ret->wParam)); - } - } else if (WM_WINDOWPOSCHANGED == ret->message) { onWindowPosChanged(ret->hwnd); @@ -85,20 +77,6 @@ namespace &disableTransitions, sizeof(disableTransitions)); } - void eraseBackground(HWND hwnd, HDC dc) - { - if (CompatGdi::beginGdiRendering()) - { - HDC compatDc = CompatGdiDc::getDc(dc); - if (compatDc) - { - SendMessage(hwnd, WM_ERASEBKGND, reinterpret_cast(compatDc), 0); - CompatGdiDc::releaseDc(dc); - } - CompatGdi::endGdiRendering(); - } - } - LRESULT CALLBACK mouseProc(int nCode, WPARAM wParam, LPARAM lParam) { if (HC_ACTION == nCode)