1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
|
# SHMessageBoxCheck
# Works like MessageBox but includes a checkbox that gives the user the option not to show the message box again.
# In that case the return value (first value on the stack) is always set to the last user choice
#
# See
# http://nsis.sourceforge.net/SHMessageBoxCheck (documentation)
# https://msdn.microsoft.com/library/windows/desktop/bb773836.aspx (implementation details)
#
# types to indicate the buttons displayed in the message box
!define MB_OK 0x00000000
!define MB_OKCANCEL 0x00000001
!define MB_ABORTRETRYIGNORE 0x00000002 # not officially supported, use at your own risk!
!define MB_YESNOCANCEL 0x00000003 # not officially supported, use at your own risk!
!define MB_YESNO 0x00000004
!define MB_RETRYCANCEL 0x00000005 # not officially supported, use at your own risk!
!define MB_CANCELTRYCONTINUE 0x00000006 # not officially supported, use at your own risk!
!define MB_HELP 0x00004000 # not officially supported, use at your own risk!
# types to display an icon in the message box
!define MB_ICONHAND 0x00000010
!define MB_ICONQUESTION 0x00000020 # MS bug: Same as MB_ICONEXCLAMATION
!define MB_ICONEXCLAMATION 0x00000030
!define MB_ICONINFORMATION 0x00000040
# return values
!define IDOK 1
!define IDCANCEL 2
!define IDABORT 3
!define IDRETRY 4
!define IDIGNORE 5
!define IDYES 6
!define IDNO 7
!define IDCONTINUE 11
!define IDTRYAGAIN 10
# the user's previous choice (i.e. the button clicked in the message box)
Var _lastReturnValue
# The value that the call to SHMessageBoxCheck should return when the user chose not to display the message box again
!define _DEFAULT 9999
# Windows XP does not expose the function name, so we have to specify the function by ordinal value
!ifdef NSIS_UNICODE
!define _SHMessageBoxCheck_Ordinal 191
!else
!define _SHMessageBoxCheck_Ordinal 185
!endif
!macro SHMessageBoxCheckInit _UNIQUE_STRING
# SHMessageBoxCheck stores the user's choice not to display the message box again in the registry, see
# HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\DontShowMeThisDialogAgain
!ifdef _PSZ_REG_VAL
!error "Only call SHMessageBoxCheckInit once and make sure to call SHMessageBoxCheckCleanup before using it again"
!else
# the unique string used to identify this message (and name of the registry value used to store the checkbox status)
!define _PSZ_REG_VAL ${_UNIQUE_STRING}
!endif
# make sure the registry value is not yet set (for whatever reason)
${SHMessageBoxCheckCleanup}
!macroend
!define SHMessageBoxCheckInit "!insertmacro SHMessageBoxCheckInit"
!macro SHMessageBoxCheckCleanup
# delete the registry key that is used to store the checkbox status so we can start fresh next time
DeleteRegValue HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\DontShowMeThisDialogAgain" "${_PSZ_REG_VAL}"
!macroend
!define SHMessageBoxCheckCleanup "!insertmacro SHMessageBoxCheckCleanup"
!macro SHMessageBoxCheck _CAPTION _TEXT _TYPE
# this would be the simple way (by name)
# System::Call "shlwapi::SHMessageBoxCheck(p $HWNDPARENT, t '${_TEXT}', t '${_CAPTION}', i ${_TYPE}, i ${_DEFAULT}, t '${_PSZ_REG_VAL}') i .r0"
# for backwards-compatibility we get the process address by specifying the function's ordinal value
System::Call "kernel32::GetModuleHandle(t 'shlwapi.dll') p .s"
System::Call "kernel32::GetProcAddress(p s, i ${_SHMessageBoxCheck_Ordinal}) p .r0"
System::Call "::$0(p $HWNDPARENT, t '${_TEXT}', t '${_CAPTION}', i ${_TYPE}, i ${_DEFAULT}, t '${_PSZ_REG_VAL}') i .r0"
# save the user's choice (unless the default value was returned - then don't update and return the saved choice)
StrCmp $0 ${_DEFAULT} +2 0
StrCpy $_lastReturnValue $0
# push the return value to the stack
Push $_lastReturnValue
!macroend
!define SHMessageBoxCheck "!insertmacro SHMessageBoxCheck"
|