mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Update original DC's current position after redirection
Fixes incorrectly drawn frames around Mig Alley's controls (issue #12).
This commit is contained in:
parent
9b3e900faf
commit
4104540c14
@ -17,7 +17,7 @@ namespace
|
|||||||
class CompatDc
|
class CompatDc
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CompatDc(HDC dc) : m_origDc(dc), m_compatDc(Gdi::Dc::getDc(dc, false))
|
CompatDc(HDC dc) : m_origDc(dc), m_compatDc(Gdi::Dc::getDc(dc, false))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,11 +56,42 @@ namespace
|
|||||||
std::unordered_map<void*, const char*> g_funcNames;
|
std::unordered_map<void*, const char*> g_funcNames;
|
||||||
thread_local bool g_redirectToDib = true;
|
thread_local bool g_redirectToDib = true;
|
||||||
|
|
||||||
template <typename OrigFuncPtr, OrigFuncPtr origFunc, typename... Params>
|
|
||||||
HDC getDestinationDc(Params... params);
|
|
||||||
|
|
||||||
HRGN getWindowRegion(HWND hwnd);
|
HRGN getWindowRegion(HWND hwnd);
|
||||||
|
|
||||||
|
#define CREATE_DC_FUNC_ATTRIBUTE(attribute) \
|
||||||
|
template <typename OrigFuncPtr, OrigFuncPtr origFunc> \
|
||||||
|
bool attribute() \
|
||||||
|
{ \
|
||||||
|
return false; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SET_DC_FUNC_ATTRIBUTE(attribute, func) \
|
||||||
|
template <> \
|
||||||
|
bool attribute<decltype(&func), &func>() \
|
||||||
|
{ \
|
||||||
|
return true; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SET_TEXT_DC_FUNC_ATTRIBUTE(attribute, func) \
|
||||||
|
SET_DC_FUNC_ATTRIBUTE(attribute, func##A) \
|
||||||
|
SET_DC_FUNC_ATTRIBUTE(attribute, func##W)
|
||||||
|
|
||||||
|
CREATE_DC_FUNC_ATTRIBUTE(isPositionUpdated);
|
||||||
|
SET_DC_FUNC_ATTRIBUTE(isPositionUpdated, AngleArc);
|
||||||
|
SET_DC_FUNC_ATTRIBUTE(isPositionUpdated, ArcTo);
|
||||||
|
SET_DC_FUNC_ATTRIBUTE(isPositionUpdated, LineTo);
|
||||||
|
SET_DC_FUNC_ATTRIBUTE(isPositionUpdated, PolyBezierTo);
|
||||||
|
SET_DC_FUNC_ATTRIBUTE(isPositionUpdated, PolyDraw);
|
||||||
|
SET_DC_FUNC_ATTRIBUTE(isPositionUpdated, PolylineTo);
|
||||||
|
SET_TEXT_DC_FUNC_ATTRIBUTE(isPositionUpdated, ExtTextOut);
|
||||||
|
SET_TEXT_DC_FUNC_ATTRIBUTE(isPositionUpdated, PolyTextOut);
|
||||||
|
SET_TEXT_DC_FUNC_ATTRIBUTE(isPositionUpdated, TabbedTextOut);
|
||||||
|
SET_TEXT_DC_FUNC_ATTRIBUTE(isPositionUpdated, TextOut);
|
||||||
|
|
||||||
|
CREATE_DC_FUNC_ATTRIBUTE(isReadOnly);
|
||||||
|
SET_DC_FUNC_ATTRIBUTE(isReadOnly, GetDIBits);
|
||||||
|
SET_DC_FUNC_ATTRIBUTE(isReadOnly, GetPixel);
|
||||||
|
|
||||||
BOOL WINAPI GdiDrawStream(HDC, DWORD, DWORD) { return FALSE; }
|
BOOL WINAPI GdiDrawStream(HDC, DWORD, DWORD) { return FALSE; }
|
||||||
BOOL WINAPI PolyPatBlt(HDC, DWORD, DWORD, DWORD, DWORD) { return FALSE; }
|
BOOL WINAPI PolyPatBlt(HDC, DWORD, DWORD, DWORD, DWORD) { return FALSE; }
|
||||||
|
|
||||||
@ -106,23 +137,28 @@ namespace
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename OrigFuncPtr, OrigFuncPtr origFunc, typename Result, typename... Params>
|
template <typename OrigFuncPtr, OrigFuncPtr origFunc, typename Result, typename... Params>
|
||||||
Result WINAPI compatGdiDcFunc(Params... params)
|
Result WINAPI compatGdiDcFunc(HDC hdc, Params... params)
|
||||||
{
|
{
|
||||||
#ifdef DEBUGLOGS
|
#ifdef DEBUGLOGS
|
||||||
LOG_FUNC(g_funcNames[origFunc], params...);
|
LOG_FUNC(g_funcNames[origFunc], hdc, params...);
|
||||||
#else
|
|
||||||
LOG_FUNC("", params...);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (hasDisplayDcArg(params...))
|
if (hasDisplayDcArg(hdc, params...))
|
||||||
{
|
{
|
||||||
D3dDdi::ScopedCriticalSection lock;
|
D3dDdi::ScopedCriticalSection lock;
|
||||||
const bool isReadOnlyAccess = !hasDisplayDcArg(getDestinationDc<OrigFuncPtr, origFunc>(params...));
|
Gdi::AccessGuard accessGuard(isReadOnly<OrigFuncPtr, origFunc>() ? Gdi::ACCESS_READ : Gdi::ACCESS_WRITE);
|
||||||
Gdi::AccessGuard accessGuard(isReadOnlyAccess ? Gdi::ACCESS_READ : Gdi::ACCESS_WRITE);
|
CompatDc compatDc(hdc);
|
||||||
return LOG_RESULT(Compat::getOrigFuncPtr<OrigFuncPtr, origFunc>()(replaceDc(params)...));
|
Result result = Compat::getOrigFuncPtr<OrigFuncPtr, origFunc>()(compatDc, replaceDc(params)...);
|
||||||
|
if (isPositionUpdated<OrigFuncPtr, origFunc>() && result)
|
||||||
|
{
|
||||||
|
POINT currentPos = {};
|
||||||
|
GetCurrentPositionEx(compatDc, ¤tPos);
|
||||||
|
MoveToEx(hdc, currentPos.x, currentPos.y, nullptr);
|
||||||
|
}
|
||||||
|
return LOG_RESULT(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
return LOG_RESULT(Compat::getOrigFuncPtr<OrigFuncPtr, origFunc>()(params...));
|
return LOG_RESULT(Compat::getOrigFuncPtr<OrigFuncPtr, origFunc>()(hdc, params...));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
@ -155,7 +191,15 @@ namespace
|
|||||||
{
|
{
|
||||||
D3dDdi::ScopedCriticalSection lock;
|
D3dDdi::ScopedCriticalSection lock;
|
||||||
Gdi::AccessGuard accessGuard(Gdi::ACCESS_WRITE);
|
Gdi::AccessGuard accessGuard(Gdi::ACCESS_WRITE);
|
||||||
return LOG_RESULT(CALL_ORIG_FUNC(ExtTextOutW)(replaceDc(hdc), x, y, options, lprect, lpString, c, lpDx));
|
CompatDc compatDc(hdc);
|
||||||
|
BOOL result = CALL_ORIG_FUNC(ExtTextOutW)(compatDc, x, y, options, lprect, lpString, c, lpDx);
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
POINT currentPos = {};
|
||||||
|
GetCurrentPositionEx(compatDc, ¤tPos);
|
||||||
|
MoveToEx(hdc, currentPos.x, currentPos.y, nullptr);
|
||||||
|
}
|
||||||
|
return LOG_RESULT(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -210,6 +254,18 @@ namespace
|
|||||||
return LOG_RESULT(CALL_ORIG_FUNC(createDiscardableBitmap)(hdc, nWidth, nHeight));
|
return LOG_RESULT(CALL_ORIG_FUNC(createDiscardableBitmap)(hdc, nWidth, nHeight));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL WINAPI drawCaption(HWND hwnd, HDC hdc, const RECT* lprect, UINT flags)
|
||||||
|
{
|
||||||
|
LOG_FUNC("DrawCaption", hwnd, hdc, lprect, flags);
|
||||||
|
if (Gdi::isDisplayDc(hdc))
|
||||||
|
{
|
||||||
|
D3dDdi::ScopedCriticalSection lock;
|
||||||
|
Gdi::AccessGuard accessGuard(Gdi::ACCESS_WRITE);
|
||||||
|
return LOG_RESULT(CALL_ORIG_FUNC(DrawCaption)(hwnd, replaceDc(hdc), lprect, flags));
|
||||||
|
}
|
||||||
|
return LOG_RESULT(CALL_ORIG_FUNC(DrawCaption)(hwnd, hdc, lprect, flags));
|
||||||
|
}
|
||||||
|
|
||||||
BOOL CALLBACK excludeRgnForOverlappingWindow(HWND hwnd, LPARAM lParam)
|
BOOL CALLBACK excludeRgnForOverlappingWindow(HWND hwnd, LPARAM lParam)
|
||||||
{
|
{
|
||||||
auto& args = *reinterpret_cast<ExcludeRgnForOverlappingWindowArgs*>(lParam);
|
auto& args = *reinterpret_cast<ExcludeRgnForOverlappingWindowArgs*>(lParam);
|
||||||
@ -235,7 +291,7 @@ namespace
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename OrigFuncPtr, OrigFuncPtr origFunc, typename Result, typename... Params>
|
template <typename OrigFuncPtr, OrigFuncPtr origFunc, typename Result, typename... Params>
|
||||||
OrigFuncPtr getCompatGdiDcFuncPtr(FuncPtr<Result, Params...>)
|
OrigFuncPtr getCompatGdiDcFuncPtr(FuncPtr<Result, HDC, Params...>)
|
||||||
{
|
{
|
||||||
return &compatGdiDcFunc<OrigFuncPtr, origFunc, Result, Params...>;
|
return &compatGdiDcFunc<OrigFuncPtr, origFunc, Result, Params...>;
|
||||||
}
|
}
|
||||||
@ -246,42 +302,6 @@ namespace
|
|||||||
return &compatGdiTextDcFunc<OrigFuncPtr, origFunc, Result, Params...>;
|
return &compatGdiTextDcFunc<OrigFuncPtr, origFunc, Result, Params...>;
|
||||||
}
|
}
|
||||||
|
|
||||||
HDC getFirstDc()
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... Params>
|
|
||||||
HDC getFirstDc(HDC dc, Params...)
|
|
||||||
{
|
|
||||||
return dc;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename FirstParam, typename... Params>
|
|
||||||
HDC getFirstDc(FirstParam, Params... params)
|
|
||||||
{
|
|
||||||
return getFirstDc(params...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename OrigFuncPtr, OrigFuncPtr origFunc, typename... Params>
|
|
||||||
HDC getDestinationDc(Params... params)
|
|
||||||
{
|
|
||||||
return getFirstDc(params...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
HDC getDestinationDc<decltype(&GetDIBits), &GetDIBits>(
|
|
||||||
HDC, HBITMAP, UINT, UINT, LPVOID, LPBITMAPINFO, UINT)
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
HDC getDestinationDc<decltype(&GetPixel), &GetPixel>(HDC, int, int)
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRGN getWindowRegion(HWND hwnd)
|
HRGN getWindowRegion(HWND hwnd)
|
||||||
{
|
{
|
||||||
RECT wr = {};
|
RECT wr = {};
|
||||||
@ -454,8 +474,8 @@ namespace
|
|||||||
hookGdiDcFunction<decltype(&func), &func>(#module, #func)
|
hookGdiDcFunction<decltype(&func), &func>(#module, #func)
|
||||||
|
|
||||||
#define HOOK_GDI_TEXT_DC_FUNCTION(module, func) \
|
#define HOOK_GDI_TEXT_DC_FUNCTION(module, func) \
|
||||||
hookGdiTextDcFunction<decltype(&func##A), &func##A>(#module, #func "A"); \
|
HOOK_GDI_DC_FUNCTION(module, func##A); \
|
||||||
hookGdiTextDcFunction<decltype(&func##W), &func##W>(#module, #func "W")
|
HOOK_GDI_DC_FUNCTION(module, func##W)
|
||||||
|
|
||||||
namespace Gdi
|
namespace Gdi
|
||||||
{
|
{
|
||||||
@ -541,7 +561,7 @@ namespace Gdi
|
|||||||
HOOK_GDI_DC_FUNCTION(gdi32, PolyPolyline);
|
HOOK_GDI_DC_FUNCTION(gdi32, PolyPolyline);
|
||||||
|
|
||||||
// Painting and drawing functions
|
// Painting and drawing functions
|
||||||
HOOK_GDI_DC_FUNCTION(user32, DrawCaption);
|
HOOK_FUNCTION(user32, DrawCaption, drawCaption);
|
||||||
HOOK_GDI_DC_FUNCTION(user32, DrawEdge);
|
HOOK_GDI_DC_FUNCTION(user32, DrawEdge);
|
||||||
HOOK_GDI_DC_FUNCTION(user32, DrawFocusRect);
|
HOOK_GDI_DC_FUNCTION(user32, DrawFocusRect);
|
||||||
HOOK_GDI_DC_FUNCTION(user32, DrawFrameControl);
|
HOOK_GDI_DC_FUNCTION(user32, DrawFrameControl);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user