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
+