Scale the x/y/width/height of theme controls according to the DPI.
Sean Hall committed
Jul 6, 2020 at 16:07 UTC
2e0773ed3169889f6246271ef6fffe6f8ce16f89
2 files changed
+87
-25
src/dutil/inc/thmutil.h
+5
@@ -143,6 +143,10 @@ struct THEME_CONTROL
143
LPWSTR sczText;
144
LPWSTR sczTooltip;
145
LPWSTR sczNote; // optional text for command link
146
+ int nDefaultDpiX;
147
+ int nDefaultDpiY;
148
+ int nDefaultDpiHeight;
149
+ int nDefaultDpiWidth;
150
int nX;
151
int nY;
152
int nHeight;
@@ -250,6 +254,7 @@ struct THEME
254
WORD wId;
255
256
BOOL fAutoResize;
257
+ BOOL fForceResize;
258
259
DWORD dwStyle;
260
DWORD dwFontId;
src/dutil/thmutil.cpp
+82
-25
@@ -313,8 +313,8 @@ static const THEME_CONTROL* FindControlFromHWnd(
313
__in_opt const THEME_CONTROL* pParentControl = NULL
314
);
315
static void GetControlDimensions(
316
- __in const RECT* prcParent,
316
__in const THEME_CONTROL* pControl,
317
+ __in const RECT* prcParent,
318
__out int* piWidth,
319
__out int* piHeight,
320
__out int* piX,
@@ -364,6 +364,15 @@ static void ScaleTheme(
364
__in int x,
365
__in int y
366
);
367
+static void ScaleControls(
368
+ __in DWORD cControls,
369
+ __in THEME_CONTROL* rgControls,
370
+ __in UINT nDpi
371
+ );
372
+static void ScaleControl(
373
+ __in THEME_CONTROL* pControl,
374
+ __in UINT nDpi
375
+ );
376
static void GetControls(
377
__in THEME* pTheme,
378
__in_opt THEME_CONTROL* pParentControl,
@@ -885,8 +894,9 @@ extern "C" LRESULT CALLBACK ThemeDefWindowProc(
894
break;
895
896
case WM_SIZE:
888
- if (pTheme->fAutoResize)
897
+ if (pTheme->fAutoResize || pTheme->fForceResize)
898
{
899
+ pTheme->fForceResize = FALSE;
900
::GetClientRect(pTheme->hwndParent, &rcParent);
901
ResizeControls(pTheme->cControls, pTheme->rgControls, &rcParent);
902
return 0;
@@ -2540,10 +2550,10 @@ static HRESULT ParseControls(
2550
2551
if (fBillboardSizing)
2552
{
2543
- pControl->nX = 0;
2544
- pControl->nY = 0;
2545
- pControl->nWidth = -0;
2546
- pControl->nHeight = 0;
2553
+ pControl->nX = pControl->nDefaultDpiX = 0;
2554
+ pControl->nY = pControl->nDefaultDpiY = 0;
2555
+ pControl->nWidth = pControl->nDefaultDpiWidth = 0;
2556
+ pControl->nHeight = pControl->nDefaultDpiHeight = 0;
2557
}
2558
2559
if (pPage)
@@ -2616,33 +2626,41 @@ static HRESULT ParseControl(
2626
2627
if (!fSkipDimensions)
2628
{
2619
- hr = XmlGetAttributeNumber(pixn, L"X", reinterpret_cast<DWORD*>(&pControl->nX));
2629
+ hr = XmlGetAttributeNumber(pixn, L"X", &dwValue);
2630
if (S_FALSE == hr)
2631
{
2632
hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
2633
}
2634
ThmExitOnFailure(hr, "Failed to find control X attribute.");
2635
2626
- hr = XmlGetAttributeNumber(pixn, L"Y", reinterpret_cast<DWORD*>(&pControl->nY));
2636
+ pControl->nX = pControl->nDefaultDpiX = dwValue;
2637
+
2638
+ hr = XmlGetAttributeNumber(pixn, L"Y", &dwValue);
2639
if (S_FALSE == hr)
2640
{
2641
hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
2642
}
2643
ThmExitOnFailure(hr, "Failed to find control Y attribute.");
2644
2633
- hr = XmlGetAttributeNumber(pixn, L"Height", reinterpret_cast<DWORD*>(&pControl->nHeight));
2645
+ pControl->nY = pControl->nDefaultDpiY = dwValue;
2646
+
2647
+ hr = XmlGetAttributeNumber(pixn, L"Height", &dwValue);
2648
if (S_FALSE == hr)
2649
{
2650
hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
2651
}
2652
ThmExitOnFailure(hr, "Failed to find control Height attribute.");
2653
2640
- hr = XmlGetAttributeNumber(pixn, L"Width", reinterpret_cast<DWORD*>(&pControl->nWidth));
2654
+ pControl->nHeight = pControl->nDefaultDpiHeight = dwValue;
2655
+
2656
+ hr = XmlGetAttributeNumber(pixn, L"Width", &dwValue);
2657
if (S_FALSE == hr)
2658
{
2659
hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
2660
}
2661
ThmExitOnFailure(hr, "Failed to find control Width attribute.");
2662
+
2663
+ pControl->nWidth = pControl->nDefaultDpiWidth = dwValue;
2664
}
2665
2666
// Parse the optional background resource image.
@@ -4203,6 +4221,8 @@ static BOOL OnDpiChanged(
4221
ExitFunction();
4222
}
4223
4224
+
4225
+ pTheme->fForceResize = !pTheme->fAutoResize;
4226
ScaleTheme(pTheme, nDpi, pRect->left, pRect->top);
4227
4228
LExit:
@@ -4319,18 +4339,18 @@ static const THEME_CONTROL* FindControlFromHWnd(
4339
}
4340
4341
static void GetControlDimensions(
4322
- __in const RECT* prcParent,
4342
__in const THEME_CONTROL* pControl,
4343
+ __in const RECT* prcParent,
4344
__out int* piWidth,
4345
__out int* piHeight,
4346
__out int* piX,
4347
__out int* piY
4348
)
4349
{
4330
- *piWidth = pControl->nWidth < 1 ? pControl->nX < 0 ? prcParent->right + pControl->nWidth : prcParent->right + pControl->nWidth - pControl->nX : pControl->nWidth;
4331
- *piHeight = pControl->nHeight < 1 ? pControl->nY < 0 ? prcParent->bottom + pControl->nHeight : prcParent->bottom + pControl->nHeight - pControl->nY : pControl->nHeight;
4332
- *piX = pControl->nX < 0 ? prcParent->right + pControl->nX - *piWidth : pControl->nX;
4333
- *piY = pControl->nY < 0 ? prcParent->bottom + pControl->nY - *piHeight : pControl->nY;
4350
+ *piWidth = pControl->nWidth + (0 < pControl->nWidth ? 0 : prcParent->right - max(0, pControl->nX));
4351
+ *piHeight = pControl->nHeight + (0 < pControl->nHeight ? 0 : prcParent->bottom - max(0, pControl->nY));
4352
+ *piX = pControl->nX + (-1 < pControl->nX ? 0 : prcParent->right - *piWidth);
4353
+ *piY = pControl->nY + (-1 < pControl->nY ? 0 : prcParent->bottom - *piHeight);
4354
}
4355
4356
static HRESULT SizeListViewColumns(
@@ -4752,6 +4772,10 @@ static HRESULT LoadControls(
4772
DWORD cControls = 0;
4773
THEME_CONTROL* rgControls = NULL;
4774
HWND hwndParent = pParentControl ? pParentControl->hWnd : pTheme->hwndParent;
4775
+ int w = 0;
4776
+ int h = 0;
4777
+ int x = 0;
4778
+ int y = 0;
4779
4780
GetControls(pTheme, pParentControl, cControls, rgControls);
4781
::GetClientRect(hwndParent, &rcParent);
@@ -4910,8 +4934,7 @@ static HRESULT LoadControls(
4934
4935
pControl->wId = wControlId;
4936
4913
- int w, h, x, y;
4914
- GetControlDimensions(&rcParent, pControl, &w, &h, &x, &y);
4937
+ GetControlDimensions(pControl, &rcParent, &w, &h, &x, &y);
4938
4939
BOOL fVisible = pControl->dwStyle & WS_VISIBLE;
4940
BOOL fDisabled = pControl->dwStyle & WS_DISABLED;
@@ -5198,22 +5221,22 @@ static HRESULT LocalizeControl(
5221
5222
if (LOC_CONTROL_NOT_SET != pLocControl->nX)
5223
{
5201
- pControl->nX = pLocControl->nX;
5224
+ pControl->nDefaultDpiX = pLocControl->nX;
5225
}
5226
5227
if (LOC_CONTROL_NOT_SET != pLocControl->nY)
5228
{
5206
- pControl->nY = pLocControl->nY;
5229
+ pControl->nDefaultDpiY = pLocControl->nY;
5230
}
5231
5232
if (LOC_CONTROL_NOT_SET != pLocControl->nWidth)
5233
{
5211
- pControl->nWidth = pLocControl->nWidth;
5234
+ pControl->nDefaultDpiWidth = pLocControl->nWidth;
5235
}
5236
5237
if (LOC_CONTROL_NOT_SET != pLocControl->nHeight)
5238
{
5216
- pControl->nHeight = pLocControl->nHeight;
5239
+ pControl->nDefaultDpiHeight = pLocControl->nHeight;
5240
}
5241
5242
if (pLocControl->wzText && *pLocControl->wzText)
@@ -5304,10 +5327,14 @@ static void ResizeControl(
5327
__in const RECT* prcParent
5328
)
5329
{
5307
- int w, h, x, y;
5330
+ int w = 0;
5331
+ int h = 0;
5332
+ int x = 0;
5333
+ int y = 0;
5334
+ RECT rcControl = { };
5335
5309
- GetControlDimensions(prcParent, pControl, &w, &h, &x, &y);
5310
- ::MoveWindow(pControl->hWnd, x, y, w, h, TRUE);
5336
+ GetControlDimensions(pControl, prcParent, &w, &h, &x, &y);
5337
+ ::SetWindowPos(pControl->hWnd, NULL, x, y, w, h, SWP_NOACTIVATE | SWP_NOZORDER);
5338
5339
#ifdef DEBUG
5340
if (THEME_CONTROL_TYPE_BUTTON == pControl->type)
@@ -5333,7 +5360,6 @@ static void ResizeControl(
5360
5361
if (pControl->cControls)
5362
{
5336
- RECT rcControl = { };
5363
::GetClientRect(pControl->hWnd, &rcControl);
5364
ResizeControls(pControl->cControls, pControl->rgControls, &rcControl);
5365
}
@@ -5353,9 +5379,40 @@ static void ScaleTheme(
5379
pTheme->nMinimumHeight = DpiuScaleValue(pTheme->nDefaultDpiMinimumHeight, pTheme->nDpi);
5380
pTheme->nMinimumWidth = DpiuScaleValue(pTheme->nDefaultDpiMinimumWidth, pTheme->nDpi);
5381
5382
+ ScaleControls(pTheme->cControls, pTheme->rgControls, pTheme->nDpi);
5383
+
5384
::SetWindowPos(pTheme->hwndParent, NULL, x, y, pTheme->nWidth, pTheme->nHeight, SWP_NOACTIVATE | SWP_NOZORDER);
5385
}
5386
5387
+static void ScaleControls(
5388
+ __in DWORD cControls,
5389
+ __in THEME_CONTROL* rgControls,
5390
+ __in UINT nDpi
5391
+ )
5392
+{
5393
+ for (DWORD i = 0; i < cControls; ++i)
5394
+ {
5395
+ THEME_CONTROL* pControl = rgControls + i;
5396
+ ScaleControl(pControl, nDpi);
5397
+ }
5398
+}
5399
+
5400
+static void ScaleControl(
5401
+ __in THEME_CONTROL* pControl,
5402
+ __in UINT nDpi
5403
+ )
5404
+{
5405
+ pControl->nWidth = DpiuScaleValue(pControl->nDefaultDpiWidth, nDpi);
5406
+ pControl->nHeight = DpiuScaleValue(pControl->nDefaultDpiHeight, nDpi);
5407
+ pControl->nX = DpiuScaleValue(pControl->nDefaultDpiX, nDpi);
5408
+ pControl->nY = DpiuScaleValue(pControl->nDefaultDpiY, nDpi);
5409
+
5410
+ if (pControl->cControls)
5411
+ {
5412
+ ScaleControls(pControl->cControls, pControl->rgControls, nDpi);
5413
+ }
5414
+}
5415
+
5416
static void UnloadControls(
5417
__in DWORD cControls,
5418
__in THEME_CONTROL* rgControls