aboutsummaryrefslogtreecommitdiff
path: root/src/libs/dutil
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/dutil')
-rw-r--r--src/libs/dutil/WixToolset.DUtil/inc/thmutil.h34
-rw-r--r--src/libs/dutil/WixToolset.DUtil/thmutil.cpp302
2 files changed, 247 insertions, 89 deletions
diff --git a/src/libs/dutil/WixToolset.DUtil/inc/thmutil.h b/src/libs/dutil/WixToolset.DUtil/inc/thmutil.h
index dc554219..9557c11c 100644
--- a/src/libs/dutil/WixToolset.DUtil/inc/thmutil.h
+++ b/src/libs/dutil/WixToolset.DUtil/inc/thmutil.h
@@ -103,6 +103,14 @@ typedef enum _WM_THMUTIL
103 // wparam is THEME_LOADINGCONTROL_ARGS* and lparam is THEME_LOADINGCONTROL_RESULTS*. 103 // wparam is THEME_LOADINGCONTROL_ARGS* and lparam is THEME_LOADINGCONTROL_RESULTS*.
104 // Return code is TRUE if it was processed. 104 // Return code is TRUE if it was processed.
105 WM_THMUTIL_LOADING_CONTROL = WM_APP - 1, 105 WM_THMUTIL_LOADING_CONTROL = WM_APP - 1,
106 // Sent when WM_COMMAND is received for a control.
107 // wparam is THEME_CONTROLWMCOMMAND_ARGS* and lparam is THEME_CONTROLWMCOMMAND_RESULTS*.
108 // Return code is TRUE if it was processed.
109 WM_THMUTIL_CONTROL_WM_COMMAND = WM_APP - 2,
110 // Sent when WM_NOTIFY is received for a control.
111 // wparam is THEME_CONTROLWMNOTIFY_ARGS* and lparam is THEME_CONTROLWMNOTIFY_RESULTS*.
112 // Return code is TRUE to prevent further processing of the message.
113 WM_THMUTIL_CONTROL_WM_NOTIFY = WM_APP - 3,
106} WM_THMUTIL; 114} WM_THMUTIL;
107 115
108struct THEME_COLUMN 116struct THEME_COLUMN
@@ -397,6 +405,32 @@ struct THEME
397 LPVOID pvVariableContext; 405 LPVOID pvVariableContext;
398}; 406};
399 407
408typedef struct _THEME_CONTROLWMCOMMAND_ARGS
409{
410 DWORD cbSize;
411 WPARAM wParam;
412 const THEME_CONTROL* pThemeControl;
413} THEME_CONTROLWMCOMMAND_ARGS;
414
415typedef struct _THEME_CONTROLWMCOMMAND_RESULTS
416{
417 DWORD cbSize;
418 LRESULT lResult;
419} THEME_CONTROLWMCOMMAND_RESULTS;
420
421typedef struct _THEME_CONTROLWMNOTIFY_ARGS
422{
423 DWORD cbSize;
424 LPNMHDR lParam;
425 const THEME_CONTROL* pThemeControl;
426} THEME_CONTROLWMNOTIFY_ARGS;
427
428typedef struct _THEME_CONTROLWMNOTIFY_RESULTS
429{
430 DWORD cbSize;
431 LRESULT lResult;
432} THEME_CONTROLWMNOTIFY_RESULTS;
433
400typedef struct _THEME_LOADINGCONTROL_ARGS 434typedef struct _THEME_LOADINGCONTROL_ARGS
401{ 435{
402 DWORD cbSize; 436 DWORD cbSize;
diff --git a/src/libs/dutil/WixToolset.DUtil/thmutil.cpp b/src/libs/dutil/WixToolset.DUtil/thmutil.cpp
index d796bbaf..a3c5d80c 100644
--- a/src/libs/dutil/WixToolset.DUtil/thmutil.cpp
+++ b/src/libs/dutil/WixToolset.DUtil/thmutil.cpp
@@ -421,12 +421,10 @@ static void CALLBACK OnBillboardTimer(
421 ); 421 );
422static void OnBrowseDirectory( 422static void OnBrowseDirectory(
423 __in THEME* pTheme, 423 __in THEME* pTheme,
424 __in HWND hWnd,
425 __in const THEME_ACTION* pAction 424 __in const THEME_ACTION* pAction
426 ); 425 );
427static BOOL OnButtonClicked( 426static BOOL OnButtonClicked(
428 __in THEME* pTheme, 427 __in THEME* pTheme,
429 __in HWND hWnd,
430 __in const THEME_CONTROL* pControl 428 __in const THEME_CONTROL* pControl
431 ); 429 );
432static BOOL OnDpiChanged( 430static BOOL OnDpiChanged(
@@ -434,20 +432,37 @@ static BOOL OnDpiChanged(
434 __in WPARAM wParam, 432 __in WPARAM wParam,
435 __in LPARAM lParam 433 __in LPARAM lParam
436 ); 434 );
435static BOOL OnHypertextClicked(
436 __in THEME* pTheme,
437 __in const THEME_CONTROL* pThemeControl,
438 __in PNMLINK pnmlink
439 );
437static void OnNcCreate( 440static void OnNcCreate(
438 __in THEME* pTheme, 441 __in THEME* pTheme,
439 __in HWND hWnd, 442 __in HWND hWnd,
440 __in LPARAM lParam 443 __in LPARAM lParam
441 ); 444 );
442static HRESULT OnRichEditEnLink( 445static BOOL OnNotifyEnLink(
443 __in LPARAM lParam, 446 __in THEME* pTheme,
444 __in HWND hWndRichEdit, 447 __in const THEME_CONTROL* pThemeControl,
445 __in HWND hWnd 448 __in ENLINK* link
446 ); 449 );
447static BOOL ControlIsType( 450static BOOL OnNotifyEnMsgFilter(
448 __in const THEME* pTheme, 451 __in THEME* pTheme,
449 __in DWORD dwControl, 452 __in const THEME_CONTROL* pThemeControl,
450 __in THEME_CONTROL_TYPE type 453 __in MSGFILTER* msgFilter
454 );
455static BOOL OnWmCommand(
456 __in THEME* pTheme,
457 __in WPARAM wParam,
458 __in const THEME_CONTROL* pThemeControl,
459 __inout LRESULT* plResult
460 );
461static BOOL OnWmNotify(
462 __in THEME* pTheme,
463 __in LPNMHDR lParam,
464 __in const THEME_CONTROL* pThemeControl,
465 __inout LRESULT* plResult
451 ); 466 );
452static const THEME_CONTROL* FindControlFromHWnd( 467static const THEME_CONTROL* FindControlFromHWnd(
453 __in const THEME* pTheme, 468 __in const THEME* pTheme,
@@ -5089,7 +5104,6 @@ static void CALLBACK OnBillboardTimer(
5089 5104
5090static void OnBrowseDirectory( 5105static void OnBrowseDirectory(
5091 __in THEME* pTheme, 5106 __in THEME* pTheme,
5092 __in HWND hWnd,
5093 __in const THEME_ACTION* pAction 5107 __in const THEME_ACTION* pAction
5094 ) 5108 )
5095{ 5109{
@@ -5098,7 +5112,7 @@ static void OnBrowseDirectory(
5098 BROWSEINFOW browseInfo = { }; 5112 BROWSEINFOW browseInfo = { };
5099 PIDLIST_ABSOLUTE pidl = NULL; 5113 PIDLIST_ABSOLUTE pidl = NULL;
5100 5114
5101 browseInfo.hwndOwner = hWnd; 5115 browseInfo.hwndOwner = pTheme->hwndParent;
5102 browseInfo.pszDisplayName = wzPath; 5116 browseInfo.pszDisplayName = wzPath;
5103 browseInfo.lpszTitle = pTheme->sczCaption; 5117 browseInfo.lpszTitle = pTheme->sczCaption;
5104 browseInfo.ulFlags = BIF_RETURNONLYFSDIRS | BIF_USENEWUI; 5118 browseInfo.ulFlags = BIF_RETURNONLYFSDIRS | BIF_USENEWUI;
@@ -5148,7 +5162,6 @@ LExit:
5148 5162
5149static BOOL OnButtonClicked( 5163static BOOL OnButtonClicked(
5150 __in THEME* pTheme, 5164 __in THEME* pTheme,
5151 __in HWND hWnd,
5152 __in const THEME_CONTROL* pControl 5165 __in const THEME_CONTROL* pControl
5153 ) 5166 )
5154{ 5167{
@@ -5191,11 +5204,11 @@ static BOOL OnButtonClicked(
5191 switch (pChosenAction->type) 5204 switch (pChosenAction->type)
5192 { 5205 {
5193 case THEME_ACTION_TYPE_BROWSE_DIRECTORY: 5206 case THEME_ACTION_TYPE_BROWSE_DIRECTORY:
5194 OnBrowseDirectory(pTheme, hWnd, pChosenAction); 5207 OnBrowseDirectory(pTheme, pChosenAction);
5195 break; 5208 break;
5196 5209
5197 case THEME_ACTION_TYPE_CLOSE_WINDOW: 5210 case THEME_ACTION_TYPE_CLOSE_WINDOW:
5198 ::SendMessageW(hWnd, WM_CLOSE, 0, 0); 5211 ::SendMessageW(pTheme->hwndParent, WM_CLOSE, 0, 0);
5199 break; 5212 break;
5200 5213
5201 case THEME_ACTION_TYPE_CHANGE_PAGE: 5214 case THEME_ACTION_TYPE_CHANGE_PAGE:
@@ -5272,6 +5285,25 @@ LExit:
5272 return !fIgnored; 5285 return !fIgnored;
5273} 5286}
5274 5287
5288static BOOL OnHypertextClicked(
5289 __in THEME* pTheme,
5290 __in const THEME_CONTROL* /*pThemeControl*/,
5291 __in PNMLINK pnmlink
5292 )
5293{
5294 BOOL fProcessed = FALSE;
5295 HRESULT hr = S_OK;
5296 LITEM litem = pnmlink->item;
5297
5298 hr = ShelExec(litem.szUrl, NULL, L"open", NULL, SW_SHOWDEFAULT, pTheme->hwndParent, NULL);
5299 ThmExitOnFailure(hr, "Failed to launch hypertext link: %ls", litem.szUrl);
5300
5301 fProcessed = TRUE;
5302
5303LExit:
5304 return fProcessed;
5305}
5306
5275static void OnNcCreate( 5307static void OnNcCreate(
5276 __in THEME* pTheme, 5308 __in THEME* pTheme,
5277 __in HWND hWnd, 5309 __in HWND hWnd,
@@ -5291,63 +5323,185 @@ static void OnNcCreate(
5291 } 5323 }
5292} 5324}
5293 5325
5294static HRESULT OnRichEditEnLink( 5326static BOOL OnNotifyEnLink(
5295 __in LPARAM lParam, 5327 __in THEME* pTheme,
5296 __in HWND hWndRichEdit, 5328 __in const THEME_CONTROL* pThemeControl,
5297 __in HWND hWnd 5329 __in ENLINK* link
5298 ) 5330 )
5299{ 5331{
5332 BOOL fProcessed = FALSE;
5300 HRESULT hr = S_OK; 5333 HRESULT hr = S_OK;
5301 LPWSTR sczLink = NULL; 5334 LPWSTR sczLink = NULL;
5302 ENLINK* link = reinterpret_cast<ENLINK*>(lParam); 5335 TEXTRANGEW tr = { };
5303 5336
5304 switch (link->msg) 5337 // Hyperlink clicks from rich-edit control.
5338 if (THEME_CONTROL_TYPE_RICHEDIT == pThemeControl->type)
5305 { 5339 {
5306 case WM_LBUTTONDOWN: 5340 switch (link->msg)
5307 { 5341 {
5308 hr = StrAlloc(&sczLink, link->chrg.cpMax - link->chrg.cpMin + 2); 5342 case WM_LBUTTONDOWN:
5309 ThmExitOnFailure(hr, "Failed to allocate string for link."); 5343 hr = StrAlloc(&sczLink, (SIZE_T)2 + link->chrg.cpMax - link->chrg.cpMin);
5344 ThmExitOnFailure(hr, "Failed to allocate string for link.");
5310 5345
5311 TEXTRANGEW tr; 5346 tr.chrg.cpMin = link->chrg.cpMin;
5312 tr.chrg.cpMin = link->chrg.cpMin; 5347 tr.chrg.cpMax = link->chrg.cpMax;
5313 tr.chrg.cpMax = link->chrg.cpMax; 5348 tr.lpstrText = sczLink;
5314 tr.lpstrText = sczLink;
5315 5349
5316 if (0 < ::SendMessageW(hWndRichEdit, EM_GETTEXTRANGE, 0, reinterpret_cast<LPARAM>(&tr))) 5350 if (0 < ::SendMessageW(pThemeControl->hWnd, EM_GETTEXTRANGE, 0, reinterpret_cast<LPARAM>(&tr)))
5317 { 5351 {
5318 hr = ShelExec(sczLink, NULL, L"open", NULL, SW_SHOWDEFAULT, hWnd, NULL); 5352 hr = ShelExec(sczLink, NULL, L"open", NULL, SW_SHOWDEFAULT, pTheme->hwndParent, NULL);
5319 ThmExitOnFailure(hr, "Failed to launch link: %ls", sczLink); 5353 ThmExitOnFailure(hr, "Failed to launch link: %ls", sczLink);
5354
5355 fProcessed = TRUE;
5356 }
5357
5358 break;
5359
5360 case WM_SETCURSOR:
5361 ::SetCursor(vhCursorHand);
5362 fProcessed = TRUE;
5363
5364 break;
5320 } 5365 }
5321 5366 }
5322 break; 5367
5368LExit:
5369 ReleaseStr(sczLink);
5370
5371 return fProcessed;
5372}
5373
5374static BOOL OnNotifyEnMsgFilter(
5375 __in THEME* pTheme,
5376 __in const THEME_CONTROL* pThemeControl,
5377 __in MSGFILTER* msgFilter
5378 )
5379{
5380 BOOL fProcessed = FALSE;
5381
5382 // Tab/Shift+Tab support for rich-edit control.
5383 if (THEME_CONTROL_TYPE_RICHEDIT == pThemeControl->type)
5384 {
5385 switch (msgFilter->msg)
5386 {
5387 case WM_KEYDOWN:
5388 if (VK_TAB == msgFilter->wParam)
5389 {
5390 BOOL fShift = 0x8000 & ::GetKeyState(VK_SHIFT);
5391 HWND hwndFocus = ::GetNextDlgTabItem(pTheme->hwndParent, pThemeControl->hWnd, fShift);
5392 ::SetFocus(hwndFocus);
5393
5394 fProcessed = TRUE;
5395 }
5396 break;
5323 } 5397 }
5398 }
5399
5400 return fProcessed;
5401}
5324 5402
5325 case WM_SETCURSOR: 5403static BOOL OnWmCommand(
5326 ::SetCursor(vhCursorHand); 5404 __in THEME* pTheme,
5405 __in WPARAM wParam,
5406 __in const THEME_CONTROL* pThemeControl,
5407 __inout LRESULT* plResult
5408 )
5409{
5410 BOOL fProcessed = FALSE;
5411 THEME_CONTROLWMCOMMAND_ARGS args = { };
5412 THEME_CONTROLWMCOMMAND_RESULTS results = { };
5413
5414 args.cbSize = sizeof(args);
5415 args.wParam = wParam;
5416 args.pThemeControl = pThemeControl;
5417
5418 results.cbSize = sizeof(results);
5419 results.lResult = *plResult;
5420
5421 if (::SendMessageW(pTheme->hwndParent, WM_THMUTIL_CONTROL_WM_COMMAND, reinterpret_cast<WPARAM>(&args), reinterpret_cast<LPARAM>(&results)))
5422 {
5423 fProcessed = TRUE;
5424 *plResult = results.lResult;
5425 ExitFunction();
5426 }
5427
5428 switch (HIWORD(wParam))
5429 {
5430 case BN_CLICKED:
5431 if (OnButtonClicked(pTheme, pThemeControl))
5432 {
5433 fProcessed = TRUE;
5434 *plResult = 0;
5435 ExitFunction();
5436 }
5327 break; 5437 break;
5328 } 5438 }
5329 5439
5330LExit: 5440LExit:
5331 ReleaseStr(sczLink); 5441 return fProcessed;
5332
5333 return hr;
5334} 5442}
5335 5443
5336static BOOL ControlIsType( 5444static BOOL OnWmNotify(
5337 __in const THEME* pTheme, 5445 __in THEME* pTheme,
5338 __in DWORD dwControl, 5446 __in LPNMHDR lParam,
5339 __in const THEME_CONTROL_TYPE type 5447 __in const THEME_CONTROL* pThemeControl,
5448 __inout LRESULT* plResult
5340 ) 5449 )
5341{ 5450{
5342 BOOL fIsType = FALSE; 5451 BOOL fProcessed = FALSE;
5343 HWND hWnd = ::GetDlgItem(pTheme->hwndParent, dwControl); 5452 THEME_CONTROLWMNOTIFY_ARGS args = { };
5344 if (hWnd) 5453 THEME_CONTROLWMNOTIFY_RESULTS results = { };
5454
5455 args.cbSize = sizeof(args);
5456 args.lParam = lParam;
5457 args.pThemeControl = pThemeControl;
5458
5459 results.cbSize = sizeof(results);
5460 results.lResult = *plResult;
5461
5462 if (::SendMessageW(pTheme->hwndParent, WM_THMUTIL_CONTROL_WM_NOTIFY, reinterpret_cast<WPARAM>(&args), reinterpret_cast<LPARAM>(&results)))
5345 { 5463 {
5346 const THEME_CONTROL* pControl = FindControlFromHWnd(pTheme, hWnd); 5464 fProcessed = TRUE;
5347 fIsType = (pControl && type == pControl->type); 5465 *plResult = results.lResult;
5466 ExitFunction();
5348 } 5467 }
5349 5468
5350 return fIsType; 5469 switch (lParam->code)
5470 {
5471 case EN_MSGFILTER:
5472 if (OnNotifyEnMsgFilter(pTheme, pThemeControl, reinterpret_cast<MSGFILTER*>(lParam)))
5473 {
5474 fProcessed = TRUE;
5475 *plResult = 1;
5476 ExitFunction();
5477 }
5478 break;
5479
5480 case EN_LINK:
5481 if (OnNotifyEnLink(pTheme, pThemeControl, reinterpret_cast<ENLINK*>(lParam)))
5482 {
5483 fProcessed = TRUE;
5484 *plResult = 1;
5485 ExitFunction();
5486 }
5487
5488 case NM_CLICK: __fallthrough;
5489 case NM_RETURN:
5490 switch (pThemeControl->type)
5491 {
5492 case THEME_CONTROL_TYPE_HYPERTEXT:
5493 // Clicks on a hypertext/syslink control.
5494 if (OnHypertextClicked(pTheme, pThemeControl, reinterpret_cast<PNMLINK>(lParam)))
5495 {
5496 fProcessed = TRUE;
5497 *plResult = 1;
5498 ExitFunction();
5499 }
5500 }
5501 }
5502
5503LExit:
5504 return fProcessed;
5351} 5505}
5352 5506
5353static const THEME_CONTROL* FindControlFromHWnd( 5507static const THEME_CONTROL* FindControlFromHWnd(
@@ -5780,6 +5934,9 @@ static LRESULT CALLBACK ControlGroupDefWindowProc(
5780 __in LPARAM lParam 5934 __in LPARAM lParam
5781 ) 5935 )
5782{ 5936{
5937 LRESULT lres = 0;
5938 const THEME_CONTROL* pThemeControl = NULL;
5939
5783 if (pTheme) 5940 if (pTheme)
5784 { 5941 {
5785 switch (uMsg) 5942 switch (uMsg)
@@ -5827,55 +5984,22 @@ static LRESULT CALLBACK ControlGroupDefWindowProc(
5827 if (lParam) 5984 if (lParam)
5828 { 5985 {
5829 LPNMHDR pnmhdr = reinterpret_cast<LPNMHDR>(lParam); 5986 LPNMHDR pnmhdr = reinterpret_cast<LPNMHDR>(lParam);
5830 switch (pnmhdr->code) 5987 pThemeControl = FindControlFromHWnd(pTheme, pnmhdr->hwndFrom);
5988 if (pThemeControl && OnWmNotify(pTheme, pnmhdr, pThemeControl, &lres))
5831 { 5989 {
5832 // Tab/Shift+Tab support for rich-edit control. 5990 return lres;
5833 case EN_MSGFILTER:
5834 {
5835 MSGFILTER* msgFilter = reinterpret_cast<MSGFILTER*>(lParam);
5836 if (WM_KEYDOWN == msgFilter->msg && VK_TAB == msgFilter->wParam)
5837 {
5838 BOOL fShift = 0x8000 & ::GetKeyState(VK_SHIFT);
5839 HWND hwndFocus = ::GetNextDlgTabItem(hWnd, msgFilter->nmhdr.hwndFrom, fShift);
5840 ::SetFocus(hwndFocus);
5841 return 1;
5842 }
5843 break;
5844 }
5845
5846 // Hyperlink clicks from rich-edit control.
5847 case EN_LINK:
5848 return SUCCEEDED(OnRichEditEnLink(lParam, pnmhdr->hwndFrom, hWnd));
5849
5850 // Clicks on a hypertext/syslink control.
5851 case NM_CLICK: __fallthrough;
5852 case NM_RETURN:
5853 if (ControlIsType(pTheme, static_cast<DWORD>(pnmhdr->idFrom), THEME_CONTROL_TYPE_HYPERTEXT))
5854 {
5855 PNMLINK pnmlink = reinterpret_cast<PNMLINK>(lParam);
5856 LITEM litem = pnmlink->item;
5857 ShelExec(litem.szUrl, NULL, L"open", NULL, SW_SHOWDEFAULT, hWnd, NULL);
5858 return 1;
5859 }
5860
5861 return 0;
5862 } 5991 }
5863 } 5992 }
5864 break; 5993 break;
5865 5994
5866 case WM_COMMAND: 5995 case WM_COMMAND:
5867 switch (HIWORD(wParam)) 5996 if (lParam)
5868 { 5997 {
5869 case BN_CLICKED: 5998 pThemeControl = FindControlFromHWnd(pTheme, (HWND)lParam);
5870 if (lParam) 5999 if (pThemeControl && OnWmCommand(pTheme, wParam, pThemeControl, &lres))
5871 { 6000 {
5872 const THEME_CONTROL* pControl = FindControlFromHWnd(pTheme, (HWND)lParam); 6001 return lres;
5873 if (pControl && OnButtonClicked(pTheme, hWnd, pControl))
5874 {
5875 return 0;
5876 }
5877 } 6002 }
5878 break;
5879 } 6003 }
5880 break; 6004 break;
5881 } 6005 }