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:
parent
91a158020a
commit
7c06d9440b
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user