@joebigelow / wix / commits / 2e0773ed

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