Search code examples
nsisnsdialogs

nsDialogs::Show accepts ENTER key even if all buttons from UI are destroyed


I have a small bootstrapper with custom UI, which contains two pages, one to configure the install, and the other showing a progressbar for the download and install of the payload. My problem: If the user presses Enter key when in the second page, the installer exits, even if it didn't finish installing.

I removed all the controls I could from the UI with:

GetDlgItem $1 $HWNDPARENT 1 //(2, and 3)
System::Call `User32::DestroyWindow(i $1)`

in the onGuiInit function, and the first page ignores enter and space keys now, but the second page still exits on Enter key. I have no other components on that page except some labels, a progressbar, and a slideshow (nsisSlideshow plugin). In the background I have a thread which downloads and installs the payload.

The pages are declared like this:

Page Custom Options_Show Options_Leave
Page Custom Progress_Show Progress_Leave

So, long story short, when I press enter, the nsDialogs::Show function returns, killing the installer.

Any way I can stop it from doing this?


Solution

  • You really should try to stop forward page changes by calling Abort in the page leave callback function.

    NSIS only blocks clicks from buttons that exist and are disabled.

    !include nsDialogs.nsh
    Page Custom Options_Show #Options_Leave
    Page Custom Progress_Show #Progress_Leave
    
    Function DisableBottomButtons
    GetDlgItem $0 $hwndparent 1
    ShowWindow $0 0
    EnableWindow $0 0
    GetDlgItem $0 $hwndparent 2
    ShowWindow $0 0
    EnableWindow $0 0
    GetDlgItem $0 $hwndparent 3 
    ShowWindow $0 0
    EnableWindow $0 0
    FunctionEnd
    
    
    Function Options_Show
    nsDialogs::Create 1018
    Pop $0
    ${NSD_CreateButton} 0 20 100% 12u "Go to next page"
    Pop $0
    ${NSD_OnClick} $0 GoToNextPage
    Call DisableBottomButtons
    nsDialogs::Show
    FunctionEnd
    
    Function GoToNextPage
    GetDlgItem $0 $hwndparent 1
    EnableWindow $0 1
    SendMessage $hwndparent ${WM_COMMAND} 1 0
    FunctionEnd
    
    
    Function Progress_Show
    nsDialogs::Create 1018
    Pop $0
    ${NSD_CreateButton} 0 20 100% 12u "Exit"
    Pop $0
    ${NSD_OnClick} $0 ExitApp
    Call DisableBottomButtons
    nsDialogs::Show
    FunctionEnd
    
    Function ExitApp
    MessageBox mb_ok "Bye"
    ; Faking a click on Next/Close will not work when the button is disabled, 
    ; this uses a slightly ugly trick to bypass that. GoToNextPage does it properly.
    !define /math WM_NOTIFY_OUTER_NEXT ${WM_USER} + 0x8
    SendMessage $hwndparent ${WM_NOTIFY_OUTER_NEXT} 1 0
    FunctionEnd