@joebigelow / wix-1 / commits / bad2e935

Add more thmutil window messages to simplify handling control events.

Sean Hall committed Oct 27, 2021 at 14:42 UTC bad2e93524f376cfeb76d5231d4b08510bdad033
9 files changed +564 -213
src/api/burn/balutil/inc/BAFunctions.h
+34
@@ -86,6 +86,8 @@ enum BA_FUNCTIONS_MESSAGE
86 BA_FUNCTIONS_MESSAGE_ONTHEMELOADED = 1024,
87 BA_FUNCTIONS_MESSAGE_WNDPROC,
88 BA_FUNCTIONS_MESSAGE_ONTHEMECONTROLLOADING,
89 + BA_FUNCTIONS_MESSAGE_ONTHEMECONTROLWMCOMMAND,
90 + BA_FUNCTIONS_MESSAGE_ONTHEMECONTROLWMNOTIFY,
91 };
92
93 typedef HRESULT(WINAPI *PFN_BA_FUNCTIONS_PROC)(
@@ -126,6 +128,38 @@ struct BA_FUNCTIONS_ONTHEMECONTROLLOADING_RESULTS
128 WORD wId;
129 };
130
131 +struct BA_FUNCTIONS_ONTHEMECONTROLWMCOMMAND_ARGS
132 +{
133 + DWORD cbSize;
134 + WPARAM wParam;
135 + LPCWSTR wzName;
136 + WORD wId;
137 + HWND hWnd;
138 +};
139 +
140 +struct BA_FUNCTIONS_ONTHEMECONTROLWMCOMMAND_RESULTS
141 +{
142 + DWORD cbSize;
143 + BOOL fProcessed;
144 + LRESULT lResult;
145 +};
146 +
147 +struct BA_FUNCTIONS_ONTHEMECONTROLWMNOTIFY_ARGS
148 +{
149 + DWORD cbSize;
150 + LPNMHDR lParam;
151 + LPCWSTR wzName;
152 + WORD wId;
153 + HWND hWnd;
154 +};
155 +
156 +struct BA_FUNCTIONS_ONTHEMECONTROLWMNOTIFY_RESULTS
157 +{
158 + DWORD cbSize;
159 + BOOL fProcessed;
160 + LRESULT lResult;
161 +};
162 +
163 struct BA_FUNCTIONS_ONTHEMELOADED_ARGS
164 {
165 DWORD cbSize;
src/api/burn/balutil/inc/BalBaseBAFunctions.h
+24
@@ -850,6 +850,30 @@ public: // IBAFunctions
850 return S_OK;
851 }
852
853 + virtual STDMETHODIMP OnThemeControlWmCommand(
854 + __in WPARAM /*wParam*/,
855 + __in LPCWSTR /*wzName*/,
856 + __in WORD /*wId*/,
857 + __in HWND /*hWnd*/,
858 + __inout BOOL* /*pfProcessed*/,
859 + __inout LRESULT* /*plResult*/
860 + )
861 + {
862 + return S_OK;
863 + }
864 +
865 + virtual STDMETHODIMP OnThemeControlWmNotify(
866 + __in LPNMHDR /*lParam*/,
867 + __in LPCWSTR /*wzName*/,
868 + __in WORD /*wId*/,
869 + __in HWND /*hWnd*/,
870 + __inout BOOL* /*pfProcessed*/,
871 + __inout LRESULT* /*plResult*/
872 + )
873 + {
874 + return S_OK;
875 + }
876 +
877 protected:
878 CBalBaseBAFunctions(
879 __in HMODULE hModule,
src/api/burn/balutil/inc/BalBaseBAFunctionsProc.h
+24
@@ -33,6 +33,24 @@ static HRESULT BalBaseBAFunctionsProcOnThemeControlLoading(
33 return pBAFunctions->OnThemeControlLoading(pArgs->wzName, &pResults->fProcessed, &pResults->wId);
34 }
35
36 +static HRESULT BalBaseBAFunctionsProcOnThemeControlWmCommand(
37 + __in IBAFunctions* pBAFunctions,
38 + __in BA_FUNCTIONS_ONTHEMECONTROLWMCOMMAND_ARGS* pArgs,
39 + __inout BA_FUNCTIONS_ONTHEMECONTROLWMCOMMAND_RESULTS* pResults
40 + )
41 +{
42 + return pBAFunctions->OnThemeControlWmCommand(pArgs->wParam, pArgs->wzName, pArgs->wId, pArgs->hWnd, &pResults->fProcessed, &pResults->lResult);
43 +}
44 +
45 +static HRESULT BalBaseBAFunctionsProcOnThemeControlWmNotify(
46 + __in IBAFunctions* pBAFunctions,
47 + __in BA_FUNCTIONS_ONTHEMECONTROLWMNOTIFY_ARGS* pArgs,
48 + __inout BA_FUNCTIONS_ONTHEMECONTROLWMNOTIFY_RESULTS* pResults
49 + )
50 +{
51 + return pBAFunctions->OnThemeControlWmNotify(pArgs->lParam, pArgs->wzName, pArgs->wId, pArgs->hWnd, &pResults->fProcessed, &pResults->lResult);
52 +}
53 +
54 /*******************************************************************
55 BalBaseBAFunctionsProc - requires pvContext to be of type IBAFunctions.
56 Provides a default mapping between the message based BAFunctions interface and
@@ -137,6 +155,12 @@ static HRESULT WINAPI BalBaseBAFunctionsProc(
155 case BA_FUNCTIONS_MESSAGE_ONTHEMECONTROLLOADING:
156 hr = BalBaseBAFunctionsProcOnThemeControlLoading(pBAFunctions, reinterpret_cast<BA_FUNCTIONS_ONTHEMECONTROLLOADING_ARGS*>(pvArgs), reinterpret_cast<BA_FUNCTIONS_ONTHEMECONTROLLOADING_RESULTS*>(pvResults));
157 break;
158 + case BA_FUNCTIONS_MESSAGE_ONTHEMECONTROLWMCOMMAND:
159 + hr = BalBaseBAFunctionsProcOnThemeControlWmCommand(pBAFunctions, reinterpret_cast<BA_FUNCTIONS_ONTHEMECONTROLWMCOMMAND_ARGS*>(pvArgs), reinterpret_cast<BA_FUNCTIONS_ONTHEMECONTROLWMCOMMAND_RESULTS*>(pvResults));
160 + break;
161 + case BA_FUNCTIONS_MESSAGE_ONTHEMECONTROLWMNOTIFY:
162 + hr = BalBaseBAFunctionsProcOnThemeControlWmNotify(pBAFunctions, reinterpret_cast<BA_FUNCTIONS_ONTHEMECONTROLWMNOTIFY_ARGS*>(pvArgs), reinterpret_cast<BA_FUNCTIONS_ONTHEMECONTROLWMNOTIFY_RESULTS*>(pvResults));
163 + break;
164 }
165 }
166
src/api/burn/balutil/inc/IBAFunctions.h
+22
@@ -39,4 +39,26 @@ DECLARE_INTERFACE_IID_(IBAFunctions, IBootstrapperApplication, "0FB445ED-17BD-49
39 __inout BOOL* pfProcessed,
40 __inout WORD* pwId
41 ) = 0;
42 +
43 + // OnThemeControlWmCommand - Called when WM_COMMAND is received for a control.
44 + //
45 + STDMETHOD(OnThemeControlWmCommand)(
46 + __in WPARAM wParam,
47 + __in LPCWSTR wzName,
48 + __in WORD wId,
49 + __in HWND hWnd,
50 + __inout BOOL* pfProcessed,
51 + __inout LRESULT* plResult
52 + ) = 0;
53 +
54 + // OnThemeControlWmNotify - Called when WM_NOTIFY is received for a control.
55 + //
56 + STDMETHOD(OnThemeControlWmNotify)(
57 + __in LPNMHDR lParam,
58 + __in LPCWSTR wzName,
59 + __in WORD wId,
60 + __in HWND hWnd,
61 + __inout BOOL* pfProcessed,
62 + __inout LRESULT* plResult
63 + ) = 0;
64 };
src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp
+152 -58
@@ -2878,65 +2878,11 @@ private:
2878 pBA->OnShowFailure();
2879 return 0;
2880
2881 - case WM_COMMAND:
2882 - switch (HIWORD(wParam))
2883 - {
2884 - case BN_CLICKED:
2885 - switch (LOWORD(wParam))
2886 - {
2887 - case WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX:
2888 - pBA->OnClickAcceptCheckbox();
2889 - return 0;
2890 -
2891 - case WIXSTDBA_CONTROL_INSTALL_BUTTON:
2892 - pBA->OnClickInstallButton();
2893 - return 0;
2894 -
2895 - case WIXSTDBA_CONTROL_REPAIR_BUTTON:
2896 - pBA->OnClickRepairButton();
2897 - return 0;
2898 -
2899 - case WIXSTDBA_CONTROL_UNINSTALL_BUTTON:
2900 - pBA->OnClickUninstallButton();
2901 - return 0;
2902 -
2903 - case WIXSTDBA_CONTROL_LAUNCH_BUTTON:
2904 - pBA->OnClickLaunchButton();
2905 - return 0;
2906 -
2907 - case WIXSTDBA_CONTROL_SUCCESS_RESTART_BUTTON: __fallthrough;
2908 - case WIXSTDBA_CONTROL_FAILURE_RESTART_BUTTON:
2909 - pBA->OnClickRestartButton();
2910 - return 0;
2911 -
2912 - case WIXSTDBA_CONTROL_PROGRESS_CANCEL_BUTTON:
2913 - pBA->OnClickCloseButton();
2914 - return 0;
2915 - }
2916 - break;
2917 - }
2918 - break;
2881 + case WM_THMUTIL_CONTROL_WM_COMMAND:
2882 + return pBA->OnThemeControlWmCommand(reinterpret_cast<THEME_CONTROLWMCOMMAND_ARGS*>(wParam), reinterpret_cast<THEME_CONTROLWMCOMMAND_RESULTS*>(lParam));
2883
2920 - case WM_NOTIFY:
2921 - if (lParam)
2922 - {
2923 - LPNMHDR pnmhdr = reinterpret_cast<LPNMHDR>(lParam);
2924 - switch (pnmhdr->code)
2925 - {
2926 - case NM_CLICK: __fallthrough;
2927 - case NM_RETURN:
2928 - switch (static_cast<DWORD>(pnmhdr->idFrom))
2929 - {
2930 - case WIXSTDBA_CONTROL_EULA_LINK:
2931 - pBA->OnClickEulaLink();
2932 - return 1;
2933 - case WIXSTDBA_CONTROL_FAILURE_LOGFILE_LINK:
2934 - pBA->OnClickLogFileLink();
2935 - return 1;
2936 - }
2937 - }
2938 - }
2939 - break;
2884 + case WM_THMUTIL_CONTROL_WM_NOTIFY:
2885 + return pBA->OnThemeControlWmNotify(reinterpret_cast<THEME_CONTROLWMNOTIFY_ARGS*>(wParam), reinterpret_cast<THEME_CONTROLWMNOTIFY_RESULTS*>(lParam));
2886 }
2887
2888 if (pBA && pBA->m_pTaskbarList && uMsg == pBA->m_uTaskbarButtonCreatedMessage)
@@ -3666,6 +3612,154 @@ private:
3612 ReleaseStr(sczLogFile);
3613 }
3614
3615 + BOOL OnThemeControlWmCommand(
3616 + __in const THEME_CONTROLWMCOMMAND_ARGS* pArgs,
3617 + __in THEME_CONTROLWMCOMMAND_RESULTS* pResults
3618 + )
3619 + {
3620 + HRESULT hr = S_OK;
3621 + BOOL fProcessed = FALSE;
3622 + BA_FUNCTIONS_ONTHEMECONTROLWMCOMMAND_ARGS themeControlWmCommandArgs = { };
3623 + BA_FUNCTIONS_ONTHEMECONTROLWMCOMMAND_RESULTS themeControlWmCommandResults = { };
3624 +
3625 + switch (HIWORD(pArgs->wParam))
3626 + {
3627 + case BN_CLICKED:
3628 + switch (pArgs->pThemeControl->wId)
3629 + {
3630 + case WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX:
3631 + OnClickAcceptCheckbox();
3632 + fProcessed = TRUE;
3633 + pResults->lResult = 0;
3634 + ExitFunction();
3635 +
3636 + case WIXSTDBA_CONTROL_INSTALL_BUTTON:
3637 + OnClickInstallButton();
3638 + fProcessed = TRUE;
3639 + pResults->lResult = 0;
3640 + ExitFunction();
3641 +
3642 + case WIXSTDBA_CONTROL_REPAIR_BUTTON:
3643 + OnClickRepairButton();
3644 + fProcessed = TRUE;
3645 + pResults->lResult = 0;
3646 + ExitFunction();
3647 +
3648 + case WIXSTDBA_CONTROL_UNINSTALL_BUTTON:
3649 + OnClickUninstallButton();
3650 + fProcessed = TRUE;
3651 + pResults->lResult = 0;
3652 + ExitFunction();
3653 +
3654 + case WIXSTDBA_CONTROL_LAUNCH_BUTTON:
3655 + OnClickLaunchButton();
3656 + fProcessed = TRUE;
3657 + pResults->lResult = 0;
3658 + ExitFunction();
3659 +
3660 + case WIXSTDBA_CONTROL_SUCCESS_RESTART_BUTTON: __fallthrough;
3661 + case WIXSTDBA_CONTROL_FAILURE_RESTART_BUTTON:
3662 + OnClickRestartButton();
3663 + fProcessed = TRUE;
3664 + pResults->lResult = 0;
3665 + ExitFunction();
3666 +
3667 + case WIXSTDBA_CONTROL_PROGRESS_CANCEL_BUTTON:
3668 + OnClickCloseButton();
3669 + fProcessed = TRUE;
3670 + pResults->lResult = 0;
3671 + ExitFunction();
3672 + }
3673 + break;
3674 + }
3675 +
3676 + if (m_pfnBAFunctionsProc)
3677 + {
3678 + themeControlWmCommandArgs.cbSize = sizeof(themeControlWmCommandArgs);
3679 + themeControlWmCommandArgs.wParam = pArgs->wParam;
3680 + themeControlWmCommandArgs.wzName = pArgs->pThemeControl->sczName;
3681 + themeControlWmCommandArgs.wId = pArgs->pThemeControl->wId;
3682 + themeControlWmCommandArgs.hWnd = pArgs->pThemeControl->hWnd;
3683 +
3684 + themeControlWmCommandResults.cbSize = sizeof(themeControlWmCommandResults);
3685 + themeControlWmCommandResults.lResult = pResults->lResult;
3686 +
3687 + hr = m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONTHEMECONTROLWMCOMMAND, &themeControlWmCommandArgs, &themeControlWmCommandResults, m_pvBAFunctionsProcContext);
3688 + if (E_NOTIMPL != hr)
3689 + {
3690 + BalExitOnFailure(hr, "BAFunctions OnThemeControlWmCommand failed.");
3691 +
3692 + if (themeControlWmCommandResults.fProcessed)
3693 + {
3694 + fProcessed = TRUE;
3695 + pResults->lResult = themeControlWmCommandResults.lResult;
3696 + ExitFunction();
3697 + }
3698 + }
3699 + }
3700 +
3701 +LExit:
3702 + return fProcessed;
3703 + }
3704 +
3705 + BOOL OnThemeControlWmNotify(
3706 + __in const THEME_CONTROLWMNOTIFY_ARGS* pArgs,
3707 + __in THEME_CONTROLWMNOTIFY_RESULTS* pResults
3708 + )
3709 + {
3710 + HRESULT hr = S_OK;
3711 + BOOL fProcessed = FALSE;
3712 + BA_FUNCTIONS_ONTHEMECONTROLWMNOTIFY_ARGS themeControlWmNotifyArgs = { };
3713 + BA_FUNCTIONS_ONTHEMECONTROLWMNOTIFY_RESULTS themeControlWmNotifyResults = { };
3714 +
3715 + switch (pArgs->lParam->code)
3716 + {
3717 + case NM_CLICK: __fallthrough;
3718 + case NM_RETURN:
3719 + switch (pArgs->pThemeControl->wId)
3720 + {
3721 + case WIXSTDBA_CONTROL_EULA_LINK:
3722 + OnClickEulaLink();
3723 + fProcessed = TRUE;
3724 + pResults->lResult = 1;
3725 + ExitFunction();
3726 + case WIXSTDBA_CONTROL_FAILURE_LOGFILE_LINK:
3727 + OnClickLogFileLink();
3728 + fProcessed = TRUE;
3729 + pResults->lResult = 1;
3730 + ExitFunction();
3731 + }
3732 + }
3733 +
3734 + if (m_pfnBAFunctionsProc)
3735 + {
3736 + themeControlWmNotifyArgs.cbSize = sizeof(themeControlWmNotifyArgs);
3737 + themeControlWmNotifyArgs.lParam = pArgs->lParam;
3738 + themeControlWmNotifyArgs.wzName = pArgs->pThemeControl->sczName;
3739 + themeControlWmNotifyArgs.wId = pArgs->pThemeControl->wId;
3740 + themeControlWmNotifyArgs.hWnd = pArgs->pThemeControl->hWnd;
3741 +
3742 + themeControlWmNotifyResults.cbSize = sizeof(themeControlWmNotifyResults);
3743 + themeControlWmNotifyResults.lResult = pResults->lResult;
3744 +
3745 + hr = m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONTHEMECONTROLWMCOMMAND, &themeControlWmNotifyArgs, &themeControlWmNotifyResults, m_pvBAFunctionsProcContext);
3746 + if (E_NOTIMPL != hr)
3747 + {
3748 + BalExitOnFailure(hr, "BAFunctions OnThemeControlWmNotify failed.");
3749 +
3750 + if (themeControlWmNotifyResults.fProcessed)
3751 + {
3752 + fProcessed = TRUE;
3753 + pResults->lResult = themeControlWmNotifyResults.lResult;
3754 + ExitFunction();
3755 + }
3756 + }
3757 + }
3758 +
3759 +LExit:
3760 + return fProcessed;
3761 + }
3762 +
3763
3764 //
3765 // SetState
src/libs/dutil/WixToolset.DUtil/inc/thmutil.h
+34
@@ -103,6 +103,14 @@ typedef enum _WM_THMUTIL
103 // wparam is THEME_LOADINGCONTROL_ARGS* and lparam is THEME_LOADINGCONTROL_RESULTS*.
104 // Return code is TRUE if it was processed.
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,
114 } WM_THMUTIL;
115
116 struct THEME_COLUMN
@@ -397,6 +405,32 @@ struct THEME
405 LPVOID pvVariableContext;
406 };
407
408 +typedef struct _THEME_CONTROLWMCOMMAND_ARGS
409 +{
410 + DWORD cbSize;
411 + WPARAM wParam;
412 + const THEME_CONTROL* pThemeControl;
413 +} THEME_CONTROLWMCOMMAND_ARGS;
414 +
415 +typedef struct _THEME_CONTROLWMCOMMAND_RESULTS
416 +{
417 + DWORD cbSize;
418 + LRESULT lResult;
419 +} THEME_CONTROLWMCOMMAND_RESULTS;
420 +
421 +typedef struct _THEME_CONTROLWMNOTIFY_ARGS
422 +{
423 + DWORD cbSize;
424 + LPNMHDR lParam;
425 + const THEME_CONTROL* pThemeControl;
426 +} THEME_CONTROLWMNOTIFY_ARGS;
427 +
428 +typedef struct _THEME_CONTROLWMNOTIFY_RESULTS
429 +{
430 + DWORD cbSize;
431 + LRESULT lResult;
432 +} THEME_CONTROLWMNOTIFY_RESULTS;
433 +
434 typedef struct _THEME_LOADINGCONTROL_ARGS
435 {
436 DWORD cbSize;
src/libs/dutil/WixToolset.DUtil/thmutil.cpp
+213 -89
@@ -421,12 +421,10 @@ static void CALLBACK OnBillboardTimer(
421 );
422 static void OnBrowseDirectory(
423 __in THEME* pTheme,
424 - __in HWND hWnd,
424 __in const THEME_ACTION* pAction
425 );
426 static BOOL OnButtonClicked(
427 __in THEME* pTheme,
429 - __in HWND hWnd,
428 __in const THEME_CONTROL* pControl
429 );
430 static BOOL OnDpiChanged(
@@ -434,20 +432,37 @@ static BOOL OnDpiChanged(
432 __in WPARAM wParam,
433 __in LPARAM lParam
434 );
435 +static BOOL OnHypertextClicked(
436 + __in THEME* pTheme,
437 + __in const THEME_CONTROL* pThemeControl,
438 + __in PNMLINK pnmlink
439 + );
440 static void OnNcCreate(
441 __in THEME* pTheme,
442 __in HWND hWnd,
443 __in LPARAM lParam
444 );
442 -static HRESULT OnRichEditEnLink(
443 - __in LPARAM lParam,
444 - __in HWND hWndRichEdit,
445 - __in HWND hWnd
445 +static BOOL OnNotifyEnLink(
446 + __in THEME* pTheme,
447 + __in const THEME_CONTROL* pThemeControl,
448 + __in ENLINK* link
449 );
447 -static BOOL ControlIsType(
448 - __in const THEME* pTheme,
449 - __in DWORD dwControl,
450 - __in THEME_CONTROL_TYPE type
450 +static BOOL OnNotifyEnMsgFilter(
451 + __in THEME* pTheme,
452 + __in const THEME_CONTROL* pThemeControl,
453 + __in MSGFILTER* msgFilter
454 + );
455 +static BOOL OnWmCommand(
456 + __in THEME* pTheme,
457 + __in WPARAM wParam,
458 + __in const THEME_CONTROL* pThemeControl,
459 + __inout LRESULT* plResult
460 + );
461 +static BOOL OnWmNotify(
462 + __in THEME* pTheme,
463 + __in LPNMHDR lParam,
464 + __in const THEME_CONTROL* pThemeControl,
465 + __inout LRESULT* plResult
466 );
467 static const THEME_CONTROL* FindControlFromHWnd(
468 __in const THEME* pTheme,
@@ -5089,7 +5104,6 @@ static void CALLBACK OnBillboardTimer(
5104
5105 static void OnBrowseDirectory(
5106 __in THEME* pTheme,
5092 - __in HWND hWnd,
5107 __in const THEME_ACTION* pAction
5108 )
5109 {
@@ -5098,7 +5112,7 @@ static void OnBrowseDirectory(
5112 BROWSEINFOW browseInfo = { };
5113 PIDLIST_ABSOLUTE pidl = NULL;
5114
5101 - browseInfo.hwndOwner = hWnd;
5115 + browseInfo.hwndOwner = pTheme->hwndParent;
5116 browseInfo.pszDisplayName = wzPath;
5117 browseInfo.lpszTitle = pTheme->sczCaption;
5118 browseInfo.ulFlags = BIF_RETURNONLYFSDIRS | BIF_USENEWUI;
@@ -5148,7 +5162,6 @@ LExit:
5162
5163 static BOOL OnButtonClicked(
5164 __in THEME* pTheme,
5151 - __in HWND hWnd,
5165 __in const THEME_CONTROL* pControl
5166 )
5167 {
@@ -5191,11 +5204,11 @@ static BOOL OnButtonClicked(
5204 switch (pChosenAction->type)
5205 {
5206 case THEME_ACTION_TYPE_BROWSE_DIRECTORY:
5194 - OnBrowseDirectory(pTheme, hWnd, pChosenAction);
5207 + OnBrowseDirectory(pTheme, pChosenAction);
5208 break;
5209
5210 case THEME_ACTION_TYPE_CLOSE_WINDOW:
5198 - ::SendMessageW(hWnd, WM_CLOSE, 0, 0);
5211 + ::SendMessageW(pTheme->hwndParent, WM_CLOSE, 0, 0);
5212 break;
5213
5214 case THEME_ACTION_TYPE_CHANGE_PAGE:
@@ -5272,6 +5285,25 @@ LExit:
5285 return !fIgnored;
5286 }
5287
5288 +static 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 +
5303 +LExit:
5304 + return fProcessed;
5305 +}
5306 +
5307 static void OnNcCreate(
5308 __in THEME* pTheme,
5309 __in HWND hWnd,
@@ -5291,63 +5323,185 @@ static void OnNcCreate(
5323 }
5324 }
5325
5294 -static HRESULT OnRichEditEnLink(
5295 - __in LPARAM lParam,
5296 - __in HWND hWndRichEdit,
5297 - __in HWND hWnd
5326 +static BOOL OnNotifyEnLink(
5327 + __in THEME* pTheme,
5328 + __in const THEME_CONTROL* pThemeControl,
5329 + __in ENLINK* link
5330 )
5331 {
5332 + BOOL fProcessed = FALSE;
5333 HRESULT hr = S_OK;
5334 LPWSTR sczLink = NULL;
5302 - ENLINK* link = reinterpret_cast<ENLINK*>(lParam);
5335 + TEXTRANGEW tr = { };
5336
5304 - switch (link->msg)
5337 + // Hyperlink clicks from rich-edit control.
5338 + if (THEME_CONTROL_TYPE_RICHEDIT == pThemeControl->type)
5339 {
5306 - case WM_LBUTTONDOWN:
5340 + switch (link->msg)
5341 {
5308 - hr = StrAlloc(&sczLink, link->chrg.cpMax - link->chrg.cpMin + 2);
5309 - ThmExitOnFailure(hr, "Failed to allocate string for link.");
5342 + case WM_LBUTTONDOWN:
5343 + hr = StrAlloc(&sczLink, (SIZE_T)2 + link->chrg.cpMax - link->chrg.cpMin);
5344 + ThmExitOnFailure(hr, "Failed to allocate string for link.");
5345
5311 - TEXTRANGEW tr;
5312 - tr.chrg.cpMin = link->chrg.cpMin;
5313 - tr.chrg.cpMax = link->chrg.cpMax;
5314 - tr.lpstrText = sczLink;
5346 + tr.chrg.cpMin = link->chrg.cpMin;
5347 + tr.chrg.cpMax = link->chrg.cpMax;
5348 + tr.lpstrText = sczLink;
5349
5316 - if (0 < ::SendMessageW(hWndRichEdit, EM_GETTEXTRANGE, 0, reinterpret_cast<LPARAM>(&tr)))
5317 - {
5318 - hr = ShelExec(sczLink, NULL, L"open", NULL, SW_SHOWDEFAULT, hWnd, NULL);
5319 - ThmExitOnFailure(hr, "Failed to launch link: %ls", sczLink);
5350 + if (0 < ::SendMessageW(pThemeControl->hWnd, EM_GETTEXTRANGE, 0, reinterpret_cast<LPARAM>(&tr)))
5351 + {
5352 + hr = ShelExec(sczLink, NULL, L"open", NULL, SW_SHOWDEFAULT, pTheme->hwndParent, NULL);
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;
5365 }
5321 -
5322 - break;
5366 + }
5367 +
5368 +LExit:
5369 + ReleaseStr(sczLink);
5370 +
5371 + return fProcessed;
5372 +}
5373 +
5374 +static 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;
5397 }
5398 + }
5399 +
5400 + return fProcessed;
5401 +}
5402
5325 - case WM_SETCURSOR:
5326 - ::SetCursor(vhCursorHand);
5403 +static BOOL OnWmCommand(
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 + }
5437 break;
5438 }
5439
5440 LExit:
5331 - ReleaseStr(sczLink);
5332 -
5333 - return hr;
5441 + return fProcessed;
5442 }
5443
5336 -static BOOL ControlIsType(
5337 - __in const THEME* pTheme,
5338 - __in DWORD dwControl,
5339 - __in const THEME_CONTROL_TYPE type
5444 +static BOOL OnWmNotify(
5445 + __in THEME* pTheme,
5446 + __in LPNMHDR lParam,
5447 + __in const THEME_CONTROL* pThemeControl,
5448 + __inout LRESULT* plResult
5449 )
5450 {
5342 - BOOL fIsType = FALSE;
5343 - HWND hWnd = ::GetDlgItem(pTheme->hwndParent, dwControl);
5344 - if (hWnd)
5451 + BOOL fProcessed = FALSE;
5452 + THEME_CONTROLWMNOTIFY_ARGS args = { };
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)))
5463 {
5346 - const THEME_CONTROL* pControl = FindControlFromHWnd(pTheme, hWnd);
5347 - fIsType = (pControl && type == pControl->type);
5464 + fProcessed = TRUE;
5465 + *plResult = results.lResult;
5466 + ExitFunction();
5467 }
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 +
5503 +LExit:
5504 + return fProcessed;
5505 }
5506
5507 static const THEME_CONTROL* FindControlFromHWnd(
@@ -5780,6 +5934,9 @@ static LRESULT CALLBACK ControlGroupDefWindowProc(
5934 __in LPARAM lParam
5935 )
5936 {
5937 + LRESULT lres = 0;
5938 + const THEME_CONTROL* pThemeControl = NULL;
5939 +
5940 if (pTheme)
5941 {
5942 switch (uMsg)
@@ -5827,55 +5984,22 @@ static LRESULT CALLBACK ControlGroupDefWindowProc(
5984 if (lParam)
5985 {
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))
5989 {
5832 - // Tab/Shift+Tab support for rich-edit control.
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;
5990 + return lres;
5991 }
5992 }
5993 break;
5994
5995 case WM_COMMAND:
5867 - switch (HIWORD(wParam))
5996 + if (lParam)
5997 {
5869 - case BN_CLICKED:
5870 - if (lParam)
5998 + pThemeControl = FindControlFromHWnd(pTheme, (HWND)lParam);
5999 + if (pThemeControl && OnWmCommand(pTheme, wParam, pThemeControl, &lres))
6000 {
5872 - const THEME_CONTROL* pControl = FindControlFromHWnd(pTheme, (HWND)lParam);
5873 - if (pControl && OnButtonClicked(pTheme, hWnd, pControl))
5874 - {
5875 - return 0;
5876 - }
6001 + return lres;
6002 }
5878 - break;
6003 }
6004 break;
6005 }
src/samples/thmviewer/thmviewer.cpp
+33 -24
@@ -52,6 +52,10 @@ static BOOL OnThemeLoadingControl(
52 __in const THEME_LOADINGCONTROL_ARGS* pArgs,
53 __in THEME_LOADINGCONTROL_RESULTS* pResults
54 );
55 +static BOOL OnThemeControlWmNotify(
56 + __in const THEME_CONTROLWMNOTIFY_ARGS* pArgs,
57 + __in THEME_CONTROLWMNOTIFY_RESULTS* pResults
58 + );
59 static void CALLBACK ThmviewerTraceError(
60 __in_z LPCSTR szFile,
61 __in int iLine,
@@ -377,32 +381,11 @@ static LRESULT CALLBACK MainWndProc(
381 ::PostQuitMessage(0);
382 break;
383
380 - case WM_NOTIFY:
381 - {
382 - NMHDR* pnmhdr = reinterpret_cast<NMHDR*>(lParam);
383 - switch (pnmhdr->code)
384 - {
385 - case TVN_SELCHANGEDW:
386 - {
387 - NMTREEVIEWW* ptv = reinterpret_cast<NMTREEVIEWW*>(lParam);
388 - ::PostThreadMessageW(vdwDisplayThreadId, WM_THMVWR_SHOWPAGE, SW_HIDE, ptv->itemOld.lParam);
389 - ::PostThreadMessageW(vdwDisplayThreadId, WM_THMVWR_SHOWPAGE, SW_SHOW, ptv->itemNew.lParam);
390 - }
391 - break;
392 -
393 - //case NM_DBLCLK:
394 - // TVITEM item = { };
395 - // item.mask = TVIF_PARAM;
396 - // item.hItem = TreeView_GetSelection(pnmhdr->hwndFrom);
397 - // TreeView_GetItem(pnmhdr->hwndFrom, &item);
398 - // ::PostThreadMessageW(vdwDisplayThreadId, WM_THMVWR_SHOWPAGE, SW_SHOW, item.lParam);
399 - // return 1;
400 - }
401 - }
402 - break;
403 -
384 case WM_THMUTIL_LOADING_CONTROL:
385 return OnThemeLoadingControl(reinterpret_cast<THEME_LOADINGCONTROL_ARGS*>(wParam), reinterpret_cast<THEME_LOADINGCONTROL_RESULTS*>(lParam));
386 +
387 + case WM_THMUTIL_CONTROL_WM_NOTIFY:
388 + return OnThemeControlWmNotify(reinterpret_cast<THEME_CONTROLWMNOTIFY_ARGS*>(wParam), reinterpret_cast<THEME_CONTROLWMNOTIFY_RESULTS*>(lParam));
389 }
390
391 return ThemeDefWindowProc(vpTheme, hWnd, uMsg, wParam, lParam);
@@ -558,3 +541,29 @@ static BOOL OnThemeLoadingControl(
541 pResults->hr = S_OK;
542 return TRUE;
543 }
544 +
545 +static BOOL OnThemeControlWmNotify(
546 + __in const THEME_CONTROLWMNOTIFY_ARGS* pArgs,
547 + __in THEME_CONTROLWMNOTIFY_RESULTS* /*pResults*/
548 + )
549 +{
550 + BOOL fProcessed = FALSE;
551 +
552 + switch (pArgs->lParam->code)
553 + {
554 + case TVN_SELCHANGEDW:
555 + switch (pArgs->pThemeControl->wId)
556 + {
557 + case THMVWR_CONTROL_TREE:
558 + NMTREEVIEWW* ptv = reinterpret_cast<NMTREEVIEWW*>(pArgs->lParam);
559 + ::PostThreadMessageW(vdwDisplayThreadId, WM_THMVWR_SHOWPAGE, SW_HIDE, ptv->itemOld.lParam);
560 + ::PostThreadMessageW(vdwDisplayThreadId, WM_THMVWR_SHOWPAGE, SW_SHOW, ptv->itemNew.lParam);
561 +
562 + fProcessed = TRUE;
563 + break;
564 + }
565 + break;
566 + }
567 +
568 + return fProcessed;
569 +}
src/test/burn/TestData/Manual/BafThmutilTesting/BafThmUtilTesting.cpp
+28 -42
@@ -43,62 +43,48 @@ static void CALLBACK BafThmUtilTestingTraceError(
43 class CBafThmUtilTesting : public CBalBaseBAFunctions
44 {
45 public: // IBAFunctions
46 - /*virtual STDMETHODIMP OnThemeLoaded(
47 - THEME* pTheme,
48 - WIX_LOCALIZATION* pWixLoc
46 + virtual STDMETHODIMP OnThemeControlLoading(
47 + __in LPCWSTR wzName,
48 + __inout BOOL* pfProcessed,
49 + __inout WORD* pwId
50 )
51 {
51 - HRESULT hr = S_OK;
52 -
53 - hr = __super::OnThemeLoaded(pTheme, pWixLoc);
52 + if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, wzName, -1, L"InstallTestButton", -1))
53 + {
54 + *pfProcessed = TRUE;
55 + *pwId = BAF_CONTROL_INSTALL_TEST_BUTTON;
56 + }
57
55 - return hr;
56 - }*/
58 + return S_OK;
59 + }
60
58 - virtual STDMETHODIMP WndProc(
59 - __in THEME* pTheme,
60 - __in HWND hWnd,
61 - __in UINT uMsg,
61 + virtual STDMETHODIMP OnThemeControlWmCommand(
62 __in WPARAM wParam,
63 - __in LPARAM lParam,
64 - __inout LRESULT* plRes
63 + __in LPCWSTR /*wzName*/,
64 + __in WORD wId,
65 + __in HWND /*hWnd*/,
66 + __inout BOOL* pfProcessed,
67 + __inout LRESULT* plResult
68 )
69 {
67 - switch (uMsg)
70 + HRESULT hr = S_OK;
71 +
72 + switch (HIWORD(wParam))
73 {
69 - case WM_COMMAND:
70 - switch (HIWORD(wParam))
74 + case BN_CLICKED:
75 + switch (wId)
76 {
72 - case BN_CLICKED:
73 - switch (LOWORD(wParam))
74 - {
75 - case BAF_CONTROL_INSTALL_TEST_BUTTON:
76 - OnShowTheme();
77 - *plRes = 0;
78 - return S_OK;
79 - }
80 -
77 + case BAF_CONTROL_INSTALL_TEST_BUTTON:
78 + OnShowTheme();
79 + *pfProcessed = TRUE;
80 + *plResult = 0;
81 break;
82 }
83 - break;
84 - }
85 -
86 - return __super::WndProc(pTheme, hWnd, uMsg, wParam, lParam, plRes);
87 - }
83
89 - virtual STDMETHODIMP OnThemeControlLoading(
90 - __in LPCWSTR wzName,
91 - __inout BOOL* pfProcessed,
92 - __inout WORD* pwId
93 - )
94 - {
95 - if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, wzName, -1, L"InstallTestButton", -1))
96 - {
97 - *pfProcessed = TRUE;
98 - *pwId = BAF_CONTROL_INSTALL_TEST_BUTTON;
84 + break;
85 }
86
101 - return S_OK;
87 + return hr;
88 }
89
90 private: