diff --git a/src/Thunks/user32.hpp b/src/Thunks/user32.hpp index e851936..52cb5df 100644 --- a/src/Thunks/user32.hpp +++ b/src/Thunks/user32.hpp @@ -335,40 +335,69 @@ namespace YY::Thunks BOOL, WINAPI, AdjustWindowRectExForDpi, - _Inout_ LPRECT lpRect, - _In_ DWORD dwStyle, - _In_ BOOL bMenu, - _In_ DWORD dwExStyle, - _In_ UINT dpi + _Inout_ LPRECT _pRect, + _In_ DWORD _fStyle, + _In_ BOOL _bMenu, + _In_ DWORD _fExStyle, + _In_ UINT _uDpi ) { - if (auto const pAdjustWindowRectExForDpi = try_get_AdjustWindowRectExForDpi()) + if (auto const _pfnAdjustWindowRectExForDpi = try_get_AdjustWindowRectExForDpi()) { - return pAdjustWindowRectExForDpi(lpRect, dwStyle, bMenu, dwExStyle, dpi); + return _pfnAdjustWindowRectExForDpi(_pRect, _fStyle, _bMenu, _fExStyle, _uDpi); } - RECT FrameRect = {}; - - if (!AdjustWindowRectEx(&FrameRect, dwStyle, bMenu, dwExStyle)) + if (_uDpi == 0ul) { + SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } - auto nDpiX = internal::GetDpiForSystemDownlevel(); - - if (nDpiX != dpi) + RECT _DeltaRect = {}; + if (!AdjustWindowRectEx(&_DeltaRect, _fStyle, _bMenu, _fExStyle)) { - FrameRect.left = MulDiv(FrameRect.left, dpi, nDpiX); - FrameRect.top = MulDiv(FrameRect.top, dpi, nDpiX); - FrameRect.right = MulDiv(FrameRect.right, dpi, nDpiX); - FrameRect.bottom = MulDiv(FrameRect.bottom, dpi, nDpiX); + return FALSE; } - lpRect->left += FrameRect.left; - lpRect->top += FrameRect.top; - lpRect->right += FrameRect.right; - lpRect->bottom += FrameRect.bottom; + const auto _uBaseDpi = internal::GetDpiForSystemDownlevel(); + if (_uBaseDpi != _uDpi) + { + RECT _DlgFrameRect = {}; + if (_fStyle & (WS_THICKFRAME | WS_DLGFRAME)) + { + AdjustWindowRectEx(&_DlgFrameRect, WS_DLGFRAME, FALSE, 0); + if (_bMenu || (_fStyle & WS_CAPTION) == WS_CAPTION) + { + const auto _nSystemBorderWidth = GetSystemMetrics(SM_CXBORDER); + _DlgFrameRect.top -= _nSystemBorderWidth; + } + } + else if (_fStyle & WS_BORDER) + { + AdjustWindowRectEx(&_DlgFrameRect, WS_BORDER, FALSE, 0); + if (_bMenu || (_fStyle & WS_CAPTION) == WS_CAPTION) + { + // 特殊优化,不在调用 GetSystemMetrics(SM_CXBORDER) + // 毕竟理论上 _DlgFrameRect.top == -GetSystemMetrics(SM_CXBORDER) + _DlgFrameRect.top += _DlgFrameRect.top; + } + } + + _DeltaRect.left -= _DlgFrameRect.left; + _DeltaRect.top -= _DlgFrameRect.top; + _DeltaRect.right -= _DlgFrameRect.right; + _DeltaRect.bottom -= _DlgFrameRect.bottom; + + _DeltaRect.left = MulDiv(_DeltaRect.left, _uDpi, _uBaseDpi) + _DlgFrameRect.left; + _DeltaRect.top = MulDiv(_DeltaRect.top, _uDpi, _uBaseDpi) + _DlgFrameRect.top; + _DeltaRect.right = MulDiv(_DeltaRect.right, _uDpi, _uBaseDpi) + _DlgFrameRect.right; + _DeltaRect.bottom = MulDiv(_DeltaRect.bottom, _uDpi, _uBaseDpi) + _DlgFrameRect.bottom; + } + _pRect->left += _DeltaRect.left; + _pRect->top += _DeltaRect.top; + _pRect->right += _DeltaRect.right; + _pRect->bottom += _DeltaRect.bottom; return TRUE; } #endif diff --git a/src/YY-Thunks.UnitTest/User32.UnitTest.cpp b/src/YY-Thunks.UnitTest/User32.UnitTest.cpp new file mode 100644 index 0000000..383051e --- /dev/null +++ b/src/YY-Thunks.UnitTest/User32.UnitTest.cpp @@ -0,0 +1,65 @@ +#include "pch.h" +#include "Thunks/user32.hpp" + +namespace User32 +{ + TEST_CLASS(AdjustWindowRectExForDpi) + { + AwaysNullGuard Guard; + + public: + AdjustWindowRectExForDpi() + { + Guard |= YY::Thunks::aways_null_try_get_AdjustWindowRectExForDpi; + } + + TEST_METHOD(常规测试) + { + struct TestItem + { + DWORD fStyle; + BOOL bMenu; + DWORD fExStyle; + UINT uDpi; + }; + + static constexpr const TestItem kTestItems[] = + { + { WS_DLGFRAME, TRUE, 0, USER_DEFAULT_SCREEN_DPI }, + { WS_DLGFRAME, TRUE, 0, USER_DEFAULT_SCREEN_DPI * 2 }, + { WS_DLGFRAME, FALSE, 0, USER_DEFAULT_SCREEN_DPI * 2 }, + { WS_THICKFRAME, TRUE, 0, USER_DEFAULT_SCREEN_DPI }, + { WS_THICKFRAME, TRUE, 0, USER_DEFAULT_SCREEN_DPI * 2 }, + { WS_THICKFRAME, FALSE, 0, USER_DEFAULT_SCREEN_DPI * 2 }, + { WS_THICKFRAME | WS_CAPTION, TRUE, 0, USER_DEFAULT_SCREEN_DPI * 2 }, + { WS_THICKFRAME | WS_CAPTION, FALSE, 0, USER_DEFAULT_SCREEN_DPI * 2 }, + { WS_CAPTION, TRUE, 0, USER_DEFAULT_SCREEN_DPI * 1.25 }, + { WS_CAPTION, FALSE, 0, USER_DEFAULT_SCREEN_DPI * 2 }, + { WS_OVERLAPPEDWINDOW, TRUE, 0, USER_DEFAULT_SCREEN_DPI }, + { WS_OVERLAPPEDWINDOW, TRUE, 0, USER_DEFAULT_SCREEN_DPI * 1.5 }, + { WS_OVERLAPPEDWINDOW, FALSE, 0, USER_DEFAULT_SCREEN_DPI * 2 }, + }; + + for (auto& _Item : kTestItems) + { + RECT _Current = {}; + ::AdjustWindowRectExForDpi(&_Current, _Item.fStyle, _Item.bMenu, _Item.fExStyle, _Item.uDpi); + + RECT _Target = {}; + YY::Thunks::aways_null_try_get_AdjustWindowRectExForDpi = false; + ::AdjustWindowRectExForDpi(&_Target, _Item.fStyle, _Item.bMenu, _Item.fExStyle, _Item.uDpi); + YY::Thunks::aways_null_try_get_AdjustWindowRectExForDpi = true; + + CStringW _szTarget; + CStringW _szCurrent; + Assert::AreEqual(_szTarget.GetString(), _szCurrent.GetString()); + } + } + + TEST_METHOD(畸形测试) + { + RECT _Current = {}; + Assert::IsFalse(::AdjustWindowRectExForDpi(&_Current, 0, 0, 0, 0)); + } + }; +} diff --git a/src/YY-Thunks.UnitTest/YY-Thunks.UnitTest.vcxproj b/src/YY-Thunks.UnitTest/YY-Thunks.UnitTest.vcxproj index 1bdf82a..6cca268 100644 --- a/src/YY-Thunks.UnitTest/YY-Thunks.UnitTest.vcxproj +++ b/src/YY-Thunks.UnitTest/YY-Thunks.UnitTest.vcxproj @@ -202,6 +202,7 @@ + NotUsing NotUsing diff --git a/src/YY-Thunks.UnitTest/YY-Thunks.UnitTest.vcxproj.filters b/src/YY-Thunks.UnitTest/YY-Thunks.UnitTest.vcxproj.filters index 8045d73..093ffd4 100644 --- a/src/YY-Thunks.UnitTest/YY-Thunks.UnitTest.vcxproj.filters +++ b/src/YY-Thunks.UnitTest/YY-Thunks.UnitTest.vcxproj.filters @@ -90,6 +90,9 @@ 源文件\UnitTest + + 源文件\UnitTest +