From be411f5b8ad7783625c50134df683ee4a254bb56 Mon Sep 17 00:00:00 2001 From: Dwayne Robinson Date: Thu, 17 Mar 2022 14:46:31 -0700 Subject: [PATCH] Fix attribute value edit height and colmun list width for high DPI --- resource/MainWindow.manifest | 9 +++-- source/MainWindow.h | 26 +++++++++++++ source/MainWindow.ixx | 71 ++++++++++++++---------------------- 3 files changed, 59 insertions(+), 47 deletions(-) diff --git a/resource/MainWindow.manifest b/resource/MainWindow.manifest index 5d36583..b53405b 100644 --- a/resource/MainWindow.manifest +++ b/resource/MainWindow.manifest @@ -13,7 +13,7 @@ - + @@ -21,15 +21,16 @@ - + - + - true + True/PM + PerMonitorV2,PerMonitor true diff --git a/source/MainWindow.h b/source/MainWindow.h index 4c35d34..0fad74a 100644 --- a/source/MainWindow.h +++ b/source/MainWindow.h @@ -4,6 +4,31 @@ #pragma once +struct WindowDpiScaler +{ + int32_t dpiX = 96; + int32_t dpiY = 96; + + void UpdateDpi(HWND hwnd) + { + // Ideally we'd support multiple monitors of varying DPI's... + // + // HMONITOR monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); + // HRESULT GetDpiForMonitor(honitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY); + // + // But GetDpiForMonitor is unavailable on Windows 7. + // So hopefully an HDC suitable for the current window is good enough: + + HDC hdc = GetDC(hwnd); + dpiX = GetDeviceCaps(hdc, LOGPIXELSX); + dpiY = GetDeviceCaps(hdc, LOGPIXELSY); + ReleaseDC(hwnd, hdc); + } + + int32_t ScaleSizeX(int value) {return value * dpiX / 96;}; + int32_t ScaleSizeY(int value) {return value * dpiY / 96;}; +}; + class MainWindow { public: @@ -165,6 +190,7 @@ class MainWindow std::u16string selectedAttributeValue_; std::u16string previousSettingsFilePath_; TextEscapeMode textEscapeMode_ = TextEscapeModeNone; + WindowDpiScaler dpiScaler_; std::vector drawableObjects_; }; diff --git a/source/MainWindow.ixx b/source/MainWindow.ixx index 94ae3a1..c9987c0 100644 --- a/source/MainWindow.ixx +++ b/source/MainWindow.ixx @@ -1,34 +1,6 @@ -/* --Custom font fallback --Custom font collection --EDIT/RichEdit --Show red attribute on parse error -?Character glyph map -?App translucency -+Rendering mode -+GDI AddFontMemResource -+Add font open dialog for font file -+Get all characters -+Add font selection dialog -+Hit test canvas -+Pan scroll canvas -+Font fallback enable/disable -+Store settings -+Load settings -+Transform drawable objects -+Context menu on drawable objects right-click -+Drawable object absolute placement -+Draw labels -+Reflow drawable objects -+GDI+ DrawString/MeasureString -+GDI+ DrawDriverString -+Show red box on drawing error -+Draw object background colors and object together -+Fix user32 DrawText for vertical -+Save selected font file -*/ -//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- // History: 2015-06-19 Dwayne Robinson - Created +// 2022-03-17 Updated for high DPI //---------------------------------------------------------------------------- #if USE_CPP_MODULES @@ -279,6 +251,10 @@ MainWindow::DialogProcResult CALLBACK MainWindow::DialogProc(HWND hwnd, UINT mes Resize(IddMainWindow); break; + case WM_DPICHANGED: + dpiScaler_.UpdateDpi(hwnd); + break; + case WM_KEYDOWN: TranslateAccelerator(hwnd, g_accelTable, &Application::g_msg); break; @@ -467,6 +443,8 @@ INT_PTR MainWindow::InitializeMainDialog() DefWindowProc(hwnd_, WM_SETICON, ICON_BIG, LPARAM(LoadIcon(Application::g_hModule, MAKEINTRESOURCE(1)))); SetWindowText(hwnd_, BUILD_TITLE_STRING); + dpiScaler_.UpdateDpi(hwnd_); // Must be done before resizing. + Edit_LimitText(GetWindowFromId(hwnd_, IdcLog), 1048576); // Subclass the values edit box for a few reasons. @@ -586,7 +564,7 @@ void MainWindow::InitializeDrawableObjectsListView() // columns to data arrays (including strings) and enumerations than // simple numeric values. lc.iSubItem = attribute.id; - lc.cx = (attribute.IsTypeArray() || attribute.id == 0) ? 120 : 80; + lc.cx = dpiScaler_.ScaleSizeX((attribute.IsTypeArray() || attribute.id == 0) ? 120 : 80); lc.pszText = const_cast(ToWChar(attribute.display)); ListView_InsertColumn(listViewHwnd, lc.iSubItem, &lc); } @@ -652,8 +630,8 @@ void MainWindow::UpdateDrawableObjectsListView() void MainWindow::InitializeAttributesListView() { const static ListViewColumnInfo columnInfo[] = { - { 0, 120, u"Attribute" }, - { 1, 400, u"Value" }, + { 0, dpiScaler_.ScaleSizeX(120), u"Attribute" }, + { 1, dpiScaler_.ScaleSizeX(400), u"Value" }, }; auto listViewHwnd = GetWindowFromId(hwnd_, IdcAttributesList); ListView_SetExtendedListViewStyle(listViewHwnd, LVS_EX_LABELTIP | LVS_EX_DOUBLEBUFFER | LVS_EX_HEADERDRAGDROP | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_HEADERINALLVIEWS); @@ -709,8 +687,8 @@ void MainWindow::FillAttributesListView() void MainWindow::InitializeAttributeValuesListView() { const static ListViewColumnInfo columnInfo[] = { - { 0, 120, u"Name" }, - { 1, 400, u"Value" }, + { 0, dpiScaler_.ScaleSizeX(120), u"Name" }, + { 1, dpiScaler_.ScaleSizeX(400), u"Value" }, }; auto listViewHwnd = GetWindowFromId(hwnd_, IdcAttributeValuesList); ListView_SetExtendedListViewStyle(listViewHwnd, LVS_EX_LABELTIP | LVS_EX_DOUBLEBUFFER | LVS_EX_HEADERDRAGDROP | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_HEADERINALLVIEWS); @@ -3060,9 +3038,12 @@ void MainWindow::Resize(int id) hwnd = hwnd_; GetClientRect(hwnd, &clientRect); if (IsRectEmpty(&clientRect)) + { return; // Avoid unnecessary resizing logic if minimized. + } - InflateRect(&clientRect, -spacing, -spacing); + auto inflatedSpacing = dpiScaler_.ScaleSizeX(spacing); + InflateRect(&clientRect, -inflatedSpacing, -inflatedSpacing); WindowPosition windowPositions[] = { /* 00 */ WindowPosition(GetWindowFromId(hwnd, IdcDrawableObjectListLoad), PositionOptionsAlignTop), @@ -3100,12 +3081,14 @@ void MainWindow::Resize(int id) WindowPosition& windowPositionAttributeValuesList = windowPositions[22]; // Apply initial overall resizing. - WindowPosition::ReflowGrid(windowPositions, uint32_t(countof(windowPositions)), clientRect, spacing, 0, PositionOptionsNone); - windowPositionDrawableObjectsList.ClampRect({0x7FFF,340}); - windowPositionAttributesList.ClampRect({340,340}); - windowPositionAttributeValuesList.ClampRect({340,340}); - windowPositionEditText.ClampRect({0x7FFF,160}); - WindowPosition::ReflowGrid(windowPositions, uint32_t(countof(windowPositions)), clientRect, spacing, 0, PositionOptionsNone); + const int32_t attributeListWidth = dpiScaler_.ScaleSizeX(340); + const int32_t attributeListHeight = dpiScaler_.ScaleSizeY(340); + WindowPosition::ReflowGrid(windowPositions, uint32_t(countof(windowPositions)), clientRect, inflatedSpacing, 0, PositionOptionsNone); + windowPositionDrawableObjectsList.ClampRect({0x7FFF,attributeListWidth}); + windowPositionAttributesList.ClampRect({attributeListHeight,attributeListWidth}); + windowPositionAttributeValuesList.ClampRect({attributeListHeight,attributeListWidth}); + windowPositionEditText.ClampRect({0x7FFF, dpiScaler_.ScaleSizeY(160)}); + WindowPosition::ReflowGrid(windowPositions, uint32_t(countof(windowPositions)), clientRect, inflatedSpacing, 0, PositionOptionsNone); // Resize the objects edit and list controls. RECT attributesRect = windowPositionAttributesList.rect; @@ -3119,9 +3102,11 @@ void MainWindow::Resize(int id) #if 0 // todo::: enable slider for variable fonts. windowPositionAttributeValuesSlider.options &= ~PositionOptionsIgnored; #endif + windowPositionAttributeValuesList.SetOptions(PositionOptionsFillHeight, PositionOptionsAlignVMask | PositionOptionsUseSlackHeight); WindowPosition::ReflowGrid(&windowPositionAttributeValuesEdit, 3, attributeValuesRect, /*spacing*/0, 0, PositionOptionsFlowVertical | PositionOptionsUnwrapped); - windowPositionAttributeValuesEdit.ClampRect({0x7FFF, (GetWindowStyle(windowPositionAttributeValuesEdit.hwnd) & ES_MULTILINE) ? 48*3/2 : 12*3/2}); + int windowPositionAttributeValuesEditHeight = (GetWindowStyle(windowPositionAttributeValuesEdit.hwnd) & ES_MULTILINE) ? 48*3/2 : 12*3/2; + windowPositionAttributeValuesEdit.ClampRect({0x7FFF, dpiScaler_.ScaleSizeX(windowPositionAttributeValuesEditHeight)}); WindowPosition::ReflowGrid(&windowPositionAttributeValuesEdit, 3, attributeValuesRect, /*spacing*/0, 0, PositionOptionsFlowVertical | PositionOptionsUnwrapped); WindowPosition::Update(windowPositions, uint32_t(countof(windowPositions)));