1
0
mirror of https://github.com/narzoul/DDrawCompat synced 2024-12-30 08:55:36 +01:00

Added WM_PAINT handling for popup menus

This commit is contained in:
narzoul 2016-03-20 22:58:51 +01:00
parent 91a158020a
commit 7c06d9440b
3 changed files with 111 additions and 18 deletions

View File

@ -87,7 +87,7 @@ namespace
MoveToEx(compatDc.dc, currentPos.x, currentPos.y, nullptr);
}
BOOL CALLBACK excludeClipRectsForOverlappingWindows(HWND hwnd, LPARAM lParam)
BOOL CALLBACK excludeClipRectForOverlappingWindow(HWND hwnd, LPARAM lParam)
{
auto excludeClipRectsData = reinterpret_cast<ExcludeClipRectsData*>(lParam);
if (hwnd == excludeClipRectsData->rootWnd)
@ -107,30 +107,58 @@ namespace
return TRUE;
}
void setClippingRegion(HDC compatDc, HDC origDc, POINT& origin)
void excludeClipRectsForOverlappingWindows(
HWND hwnd, bool isMenuWindow, HDC compatDc, const POINT& origin)
{
HRGN clipRgn = CreateRectRgn(0, 0, 0, 0);
const bool isEmptyClipRgn = 1 != GetRandomRgn(origDc, clipRgn, SYSRGN);
SelectClipRgn(compatDc, isEmptyClipRgn ? nullptr : clipRgn);
DeleteObject(clipRgn);
HRGN origClipRgn = CreateRectRgn(0, 0, 0, 0);
if (1 == GetClipRgn(origDc, origClipRgn))
ExcludeClipRectsData excludeClipRectsData = { compatDc, origin, GetAncestor(hwnd, GA_ROOT) };
if (!isMenuWindow)
{
OffsetRgn(origClipRgn, origin.x, origin.y);
ExtSelectClipRgn(compatDc, origClipRgn, RGN_AND);
EnumWindows(&excludeClipRectForOverlappingWindow,
reinterpret_cast<LPARAM>(&excludeClipRectsData));
}
DeleteObject(origClipRgn);
if (!isEmptyClipRgn)
HWND menuWindow = FindWindow(reinterpret_cast<LPCSTR>(0x8000), nullptr);
while (menuWindow && menuWindow != hwnd)
{
HWND hwnd = WindowFromDC(origDc);
if (hwnd)
excludeClipRectForOverlappingWindow(
menuWindow, reinterpret_cast<LPARAM>(&excludeClipRectsData));
menuWindow = FindWindowEx(nullptr, menuWindow, reinterpret_cast<LPCSTR>(0x8000), nullptr);
}
}
void setClippingRegion(HDC compatDc, HDC origDc, const POINT& origin)
{
const HWND hwnd = WindowFromDC(origDc);
const bool isMenuWindow = hwnd && 0x8000 == GetClassLongPtr(hwnd, GCW_ATOM);
if (isMenuWindow)
{
RECT windowRect = {};
GetWindowRect(hwnd, &windowRect);
HRGN windowRgn = CreateRectRgnIndirect(&windowRect);
SelectClipRgn(compatDc, windowRgn);
DeleteObject(windowRgn);
}
else
{
HRGN clipRgn = CreateRectRgn(0, 0, 0, 0);
const bool isEmptyClipRgn = 1 != GetRandomRgn(origDc, clipRgn, SYSRGN);
SelectClipRgn(compatDc, isEmptyClipRgn ? nullptr : clipRgn);
DeleteObject(clipRgn);
HRGN origClipRgn = CreateRectRgn(0, 0, 0, 0);
if (1 == GetClipRgn(origDc, origClipRgn))
{
ExcludeClipRectsData excludeClipRectsData = { compatDc, origin, GetAncestor(hwnd, GA_ROOT) };
EnumWindows(&excludeClipRectsForOverlappingWindows,
reinterpret_cast<LPARAM>(&excludeClipRectsData));
OffsetRgn(origClipRgn, origin.x, origin.y);
ExtSelectClipRgn(compatDc, origClipRgn, RGN_AND);
}
DeleteObject(origClipRgn);
}
if (hwnd)
{
excludeClipRectsForOverlappingWindows(hwnd, isMenuWindow, compatDc, origin);
}
}
}

View File

@ -13,11 +13,14 @@ namespace
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 onMenuPaint(HWND hwnd, WNDPROC origWndProc);
LRESULT onNcPaint(HWND hwnd, WPARAM wParam, WNDPROC origWndProc);
LRESULT onPaint(HWND hwnd, WNDPROC origWndProc);
LRESULT onPrint(HWND hwnd, UINT msg, HDC dc, LONG flags, WNDPROC origWndProc);
WNDPROC g_origEditWndProc = nullptr;
WNDPROC g_origListBoxWndProc = nullptr;
WNDPROC g_origMenuWndProc = nullptr;
WNDPROC g_origScrollBarWndProc = nullptr;
LRESULT WINAPI defDlgProcA(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam)
@ -104,6 +107,26 @@ namespace
return eraseBackgroundProc(hwnd, msg, wParam, lParam, g_origListBoxWndProc, "listBoxWndProc");
}
LRESULT WINAPI menuWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
Compat::LogEnter("menuWndProc", hwnd, msg, wParam, lParam);
LRESULT result = 0;
switch (msg)
{
case WM_PAINT:
result = onMenuPaint(hwnd, g_origMenuWndProc);
break;
default:
result = g_origMenuWndProc(hwnd, msg, wParam, lParam);
break;
}
Compat::LogLeave("menuWndProc", hwnd, msg, wParam, lParam) << result;
return result;
}
LRESULT onEraseBackground(HWND hwnd, HDC dc, WNDPROC origWndProc)
{
if (!hwnd || !CompatGdi::beginGdiRendering())
@ -157,6 +180,32 @@ namespace
return 0;
}
LRESULT onMenuPaint(HWND hwnd, WNDPROC origWndProc)
{
if (!hwnd || !CompatGdi::beginGdiRendering())
{
return origWndProc(hwnd, WM_PAINT, 0, 0);
}
HDC dc = GetWindowDC(hwnd);
HDC compatDc = CompatGdiDc::getDc(dc);
if (compatDc)
{
origWndProc(hwnd, WM_PRINT, reinterpret_cast<WPARAM>(compatDc),
PRF_NONCLIENT | PRF_ERASEBKGND | PRF_CLIENT);
ValidateRect(hwnd, nullptr);
CompatGdiDc::releaseDc(dc);
}
else
{
origWndProc(hwnd, WM_PAINT, 0, 0);
}
ReleaseDC(hwnd, dc);
CompatGdi::endGdiRendering();
return 0;
}
LRESULT onPaint(HWND hwnd, WNDPROC origWndProc)
{
if (!hwnd || !CompatGdi::beginGdiRendering())
@ -242,6 +291,7 @@ namespace CompatGdiPaintHandlers
{
CompatGdi::hookWndProc("Edit", g_origEditWndProc, &editWndProc);
CompatGdi::hookWndProc("ListBox", g_origListBoxWndProc, &listBoxWndProc);
CompatGdi::hookWndProc("#32768", g_origMenuWndProc, &menuWndProc);
CompatGdi::hookWndProc("ScrollBar", g_origScrollBarWndProc, &scrollBarWndProc);
DetourTransactionBegin();

View File

@ -18,6 +18,7 @@ namespace
std::unordered_map<HWND, RECT> g_prevWindowRect;
void disableDwmAttributes(HWND hwnd);
void onMenuSelect();
void onWindowPosChanged(HWND hwnd);
void removeDropShadow(HWND hwnd);
@ -55,6 +56,10 @@ namespace
CompatGdiScrollFunctions::updateScrolledWindow(reinterpret_cast<HWND>(ret->lParam));
}
}
else if (WM_MENUSELECT == ret->message)
{
onMenuSelect();
}
else if (BM_SETSTYLE == ret->message)
{
RedrawWindow(ret->hwnd, nullptr, nullptr, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE);
@ -131,6 +136,16 @@ namespace
}
}
void onMenuSelect()
{
HWND menuWindow = FindWindow(reinterpret_cast<LPCSTR>(0x8000), nullptr);
while (menuWindow)
{
RedrawWindow(menuWindow, nullptr, nullptr, RDW_INVALIDATE);
menuWindow = FindWindowEx(nullptr, menuWindow, reinterpret_cast<LPCSTR>(0x8000), nullptr);
}
}
void onWindowPosChanged(HWND hwnd)
{
CompatGdi::GdiScopedThreadLock lock;