Sheik
22nd May 2008 20:03 UTC
nsdialogs - Any way to override/get a callback on the <Cancel> button?
Hi all,
I was wondering if there was any "new" way of overriding or getting a callback on the button press of <Cancel> ?
The old method was to provide an override to the Abort function, specifically:
!define MUI_CUSTOMFUNCTION_ABORT "CustomAbort"
However, I was hoping that maybe now with nsdialog, we might be able to register a Abort callback on a per page basis, rather than a global Abort function that would get called from any page when the user presses <Cancel> ...
I have some code that I use to override the text <Cancel> to <Skip> on a specific page, and if they press <Skip> (Cancel), I skip forward a page, rather than Abort the whole Installer...
I was hoping things might have changed so that I don't have to install a global handler for <Cancel>...
Thanks!
Scott
Red Wine
22nd May 2008 22:15 UTC
I guess we need a function nsDialogs::OnCancel here. I wonder if it's possible...
In the meantime this workaround should do the trick:
EDIT: In order to work even if a control has triggered before the cancel button, it needs a pop in every function that is called by the controls, see bellow the edited scenario.
showinstdetails show
outfile test.exe
!include nsdialogs.nsh
page license
page custom myFirstCustomPage
page custom mySecondCustomPage
page directory
page instfiles
var myFirstCustomPage
var mySecondCustomPage
Function myFirstCustomPage
nsDialogs::Create /NOUNLOAD 1018
Pop $myFirstCustomPage
${IfThen} $myFirstCustomPage == error ${|} Abort ${|}
${NSD_CreateGroupBox} 0u 10u 100% 50% "This is my first custom page:"
Pop $0
${NSD_CreateRadioButton} 10 25u 40% 12u "button 1"
Pop $R0
${NSD_CreateRadioButton} 10 45u 40% 12u "button 2"
Pop $R1
${NSD_AddStyle} $R0 ${WS_GROUP}
${NSD_SetState} $R0 ${BST_CHECKED}
${NSD_OnClick} $R0 myfunc
${NSD_OnClick} $R1 myfunc
GetDlgItem $myFirstCustomPage $myFirstCustomPage 1200
nsDialogs::Show
FunctionEnd
Function mySecondCustomPage
nsDialogs::Create /NOUNLOAD 1018
Pop $mySecondCustomPage
${IfThen} $mySecondCustomPage == error ${|} Abort ${|}
${NSD_CreateGroupBox} 0u 10u 100% 50% "This is my second custom page:"
Pop $0
${NSD_CreateCheckBox} 10 25u 40% 12u "checkbox 1"
Pop $R0
${NSD_CreateCheckBox} 10 45u 40% 12u "checkbox 2"
Pop $R1
${NSD_SetState} $R0 ${BST_CHECKED}
${NSD_SetState} $R1 ${BST_CHECKED}
${NSD_OnClick} $R0 myfunc
${NSD_OnClick} $R1 myfunc
GetDlgItem $mySecondCustomPage $mySecondCustomPage 1200
nsDialogs::Show
FunctionEnd
Function myfunc
pop $1
FunctionEnd
Function .onUserAbort
Pop $0
${If} $0 = $myFirstCustomPage
MessageBox MB_OK "I'm gonna do crazy things now..."
${ElseIf} $0 = $mySecondCustomPage
MessageBox MB_OK "Now what?"
${EndIf}
FunctionEnd
section
sectionend
Red Wine
23rd May 2008 01:20 UTC
Can't edit the damn thing above :(
The function .onUserAbort:
Function .onUserAbort
Pop $0
${Unless} $0 == ""
${If} $0 = $myFirstCustomPage
MessageBox MB_OK "I'm gonna do crazy things now..."
${ElseIf} $0 = $mySecondCustomPage
MessageBox MB_OK "Now what?"
${EndIf}
${EndUnless}
FunctionEnd
Sheik
23rd May 2008 03:39 UTC
Thanks RedWine.
Yeah, I was hoping we could do away with the whole global function to trap Cancel events on any page.
It would really be nice to be able to register a "cancel_function" callback per page, like we can with the "leave_function" when we call the "Page" function.
ie, maybe we could change:
4.5.4 Page
custom [creator_function] [leave_function] [caption] [/ENABLECANCEL]
to:
4.5.4 Page
custom [creator_function] [leave_function] [cancel_function][caption] [/ENABLECANCEL]
Sheik
23rd May 2008 04:12 UTC
Hmmm, just looking at the nsdialog code, this should actually be pretty trival to do!
There is already code to trap the <Back> button with "onBack".
Surely we can add one to trap the <Cancel> button as well.
Assuming I can get NSIS to compile, I will try adding this code tonight/tomorrow.
Sheik
23rd May 2008 15:34 UTC
Well, I got it half done.
I can get the callback into OnCancel, but there is some stuff in exehead/Ui.c that causes NSIS to bail regardless if we Abort the Cancel or not.
But here is a small patch for the half I did get done so far:
===================================================================
RCS file: /cvsroot/nsis/NSIS/Contrib/nsDialogs/nsDialogs.c,v
retrieving revision 1.5
diff -r1.5 nsDialogs.c
36a37,43
> if (wParam == (WPARAM) 120)
> {
> if (g_pluginParms->ExecuteCodeSegment(g_dialog.callbacks.onCancel - 1, 0))
> {
> return 0;
> }
> }
390a398,402
> void __declspec(dllexport) OnCancel(HWND hwndParent, int string_size, char *variables, stack_t **stacktop, extra_parameters *extra)
> {
> SetDialogCallback(DLG_CALLBACK_IDX(onCancel));
> }
>
===================================================================
RCS file: /cvsroot/nsis/NSIS/Contrib/nsDialogs/defs.h,v
retrieving revision 1.2
diff -r1.2 defs.h
25a26
> nsFunction onCancel;