Skip to content

Commit

Permalink
Bug, AdjustWindowRectExForDpi行为适配系统,DPI为0时返回失败,且修复边框大小可能返回不正确大小
Browse files Browse the repository at this point in the history
  • Loading branch information
mingkuang-Chuyu committed Jun 30, 2024
1 parent b679d0d commit a2d7a26
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 21 deletions.
71 changes: 50 additions & 21 deletions src/Thunks/user32.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
65 changes: 65 additions & 0 deletions src/YY-Thunks.UnitTest/User32.UnitTest.cpp
Original file line number Diff line number Diff line change
@@ -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));
}
};
}
1 change: 1 addition & 0 deletions src/YY-Thunks.UnitTest/YY-Thunks.UnitTest.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@
<ClCompile Include="api-ms-win-core-threadpool.UnitTest.cpp" />
<ClCompile Include="PropSys.UnitTest.cpp" />
<ClCompile Include="shell32.UnitTest.cpp" />
<ClCompile Include="User32.UnitTest.cpp" />
<ClCompile Include="weak.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
Expand Down
3 changes: 3 additions & 0 deletions src/YY-Thunks.UnitTest/YY-Thunks.UnitTest.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@
<ClCompile Include="api-ms-win-core-winrt-string.UnitTest.cpp">
<Filter>源文件\UnitTest</Filter>
</ClCompile>
<ClCompile Include="User32.UnitTest.cpp">
<Filter>源文件\UnitTest</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h">
Expand Down

0 comments on commit a2d7a26

Please sign in to comment.