Search code examples
nsisnsdialogs

Customizing an exsisting NSIS MUI2 page using nsDialogs


I want to include custom controls to Finish Page, depending on IfRebootFlag is set or not, but I don't know why some of those are created but not displayed.

The $hWnd is for each added control a number != 0, so it means all the controls were created. The position of controls seems to be ok... surely it is not behind the image on the left, because the Left coordinate is high enough to put the controls beyond the image

I tried for hours without understanding which can be the problem

;--------------------------------
;Header Files

!include nsDialogs.nsh
!include LogicLib.nsh
!include MUI2.nsh

Name App
OutFile ctmFinishPage.exe
XPStyle on


;--------------------------------
;General

!define MUI_FINISHPAGE_NOREBOOTSUPPORT

;--------------------------------
;Variables

Var hWndChkBoxRunApp
Var hWndChkBoxLinkApp
Var hWndHlineReboot
Var hWndLblReboot
Var hWndRadBtnRebootNow
Var hWndRadBtnRebootLater

Var ctlLeft
Var ctlTop
Var ctlWidht
Var ctlHeight
Var ctlText


;--------------------------------
;Pages

    ;install pages
        !insertmacro MUI_PAGE_INSTFILES

    !define MUI_PAGE_CUSTOMFUNCTION_SHOW MyFinishShow
    !define MUI_PAGE_CUSTOMFUNCTION_LEAVE MyFinishLeave
        !insertmacro MUI_PAGE_FINISH

;--------------------------------
;Languages

  !insertmacro MUI_LANGUAGE "English"


;--------------------------------
;Installer Sections

Section
    SetRebootFlag true
SectionEnd


;--------------------------------
;Functions

Function MyFinishShow
    ;add custom Reboot section to Finish page (MUI_FINISHPAGE_NOREBOOTSUPPORT flag is required)
    IfRebootFlag 0 noreboot
        StrCpy $ctlLeft 120u
        StrCpy $ctlWidht 61%

        StrCpy $0 50
        StrCpy $ctlTop $0u
        StrCpy $R0 10
        StrCpy $ctlHeight $R0u
        StrCpy $ctlText "Create Desktop shortcut"
            ${NSD_CreateCheckBox} $ctlLeft $ctlTop $ctlWidht $ctlHeight $ctlText
                Pop $hWndChkBoxLinkApp
                SetCtlColors $hWndChkBoxLinkApp "" "ffffff"
                ${NSD_SetState} $hWndChkBoxLinkApp ${BST_CHECKED}

        StrCpy $1 117
        StrCpy $ctlTop $1u
        StrCpy $R1 1
        StrCpy $ctlHeight $R1u
        StrCpy $ctlText ""
            ${NSD_CreateHLine} $ctlLeft $ctlTop $ctlWidht $ctlHeight $ctlText
                Pop $hWndHlineReboot

        IntOp $R1 $R1 + 4
        IntOp $2 $1 + $R1
        StrCpy $ctlTop $2u
        StrCpy $R2 25
        StrCpy $ctlHeight $R2u
        StrCpy $ctlText "Your computer must be restarted in order to complete the installation of App. Do you want to reboot now?"
            ${NSD_CreateLabel} $ctlLeft $ctlTop $ctlWidht $ctlHeight $ctlText
                Pop $hWndLblReboot
                SetCtlColors $hWndLblReboot "" "ffffff"

        IntOp $R2 $R2 + 8
        IntOp $3 $2 + $R2
        StrCpy $ctlTop $3u
        StrCpy $R3 10
        StrCpy $ctlHeight $R3u
        StrCpy $ctlText "Reboot now"
        ${NSD_CreateRadioButton} $ctlLeft $ctlTop $ctlWidht $ctlHeight $ctlText
            Pop $hWndRadBtnRebootNow
            SetCtlColors $hWndRadBtnRebootNow "" "ffffff"
            ${NSD_SetState} $hWndRadBtnRebootNow ${BST_CHECKED}

        IntOp $R3 $R3 + 9
        IntOp $4 $3 + $R3
        StrCpy $ctlTop $4u
        StrCpy $R4 10
        StrCpy $ctlHeight $R4u
        StrCpy $ctlText "I want to manually reboot later"
        ${NSD_CreateRadioButton} $ctlLeft $ctlTop $ctlWidht $ctlHeight $ctlText
            Pop $hWndRadBtnRebootLater
            SetCtlColors $hWndRadBtnRebootLater "" "ffffff"
            ${NSD_SetState} $hWndRadBtnRebootLater ${BST_UNCHECKED}

        ${NSD_OnChange} $hWndChkBoxLinkApp ToggleChkBoxState
        ${NSD_OnChange} $hWndRadBtnRebootNow ToggleRadBtnState
        ${NSD_OnChange} $hWndRadBtnRebootLater ToggleRadBtnState

        Goto end
    noreboot:
            StrCpy $ctlLeft 120u
        StrCpy $ctlWidht 61%

        StrCpy $0 110
        StrCpy $ctlTop $0u
        StrCpy $R0 10
        StrCpy $ctlHeight $R0u
        StrCpy $ctlText "Run App"
            ${NSD_CreateCheckBox} $ctlLeft $ctlTop $ctlWidht $ctlHeight $ctlText
                Pop $hWndChkBoxRunApp
                SetCtlColors $hWndChkBoxRunApp "" "ffffff"
                ${NSD_SetState} $hWndChkBoxRunApp ${BST_UNCHECKED}

        IntOp $R0 $R0 + 9
        IntOp $1 $0 + $R0
        StrCpy $ctlTop $1u
        StrCpy $R1 10
        StrCpy $ctlHeight $R1u
        StrCpy $ctlText "Create Desktop"
            ${NSD_CreateCheckBox} $ctlLeft $ctlTop $ctlWidht $ctlHeight $ctlText
                Pop $hWndChkBoxLinkApp
                SetCtlColors $hWndChkBoxLinkApp "" "ffffff"
                ${NSD_SetState} $hWndChkBoxLinkApp ${BST_CHECKED}

        ${NSD_OnChange} $hWndChkBoxRunApp ToggleChkBoxState
        ${NSD_OnChange} $hWndChkBoxLinkApp ToggleChkBoxState
    end:
FunctionEnd

Function MyFinishLeave
    ;reboot the PC if radio button for "Reboot Now" option is checked (MUI_FINISHPAGE_NOREBOOTSUPPORT flag needed)
    IfRebootFlag 0 noreboot
        ${NSD_GetState} $hWndChkBoxLinkApp $0
            ${If} $0 == ${BST_CHECKED}
                Call CreateDesktopShortcut
            ${EndIf}

        ${NSD_GetState} $hWndRadBtnRebootNow $0
            ${If} $0 == ${BST_CHECKED}
                ;Reboot
                MessageBox MB_OK "Reboot..."
            ${EndIf}
        Goto end
    noreboot:
        ${NSD_GetState} $hWndChkBoxRunApp $0
            ${If} $0 == ${BST_CHECKED}
                Call LaunchAppFile
            ${EndIf}

        ${NSD_GetState} $hWndChkBoxLinkApp $0
            ${If} $0 == ${BST_CHECKED}
                Call CreateDesktopShortcut
            ${EndIf}
    end:
FunctionEnd

Function ToggleChkBoxState
    ;manage Reboot radio buttons state. If one is checked, the other one is not checked and the other way around
    Pop $1      ;$1 = $hWndChkBoxRunApp/LinkApp

    ${NSD_GetState} $1 $0
        ${If} $0 == ${BST_CHECKED}
            ${NSD_SetState} $1 ${BST_UNCHECKED}
        ${Else}
            ${NSD_SetState} $1 ${BST_CHECKED}
        ${EndIf}
FunctionEnd

Function ToggleRadBtnState
    ;manage Reboot radio buttons state. If one is checked, the other one is not checked and the other way around
    Pop $1      ;$1 = $hWndRadBtnRebootNow/Later

    ${NSD_GetState} $1 $0
        ${If} $0 == ${BST_CHECKED}
            ${If} $1 == $hWndRadBtnRebootNow
                ${NSD_SetState} $hWndRadBtnRebootLater ${BST_UNCHECKED}
            ${Else}
                ${NSD_SetState} $hWndRadBtnRebootNow ${BST_UNCHECKED}
            ${EndIf}
        ${Else}
            ${If} $1 == $hWndRadBtnRebootNow
                ${NSD_SetState} $hWndRadBtnRebootLater ${BST_CHECKED}
            ${Else}
                ${NSD_SetState} $hWndRadBtnRebootNow ${BST_CHECKED}
            ${EndIf}
        ${EndIf}
FunctionEnd

Function LaunchAppFile
    ;create a file batch at runtime for launching an excel instance pointing to the App file name
    MessageBox MB_OK "App launched at runtime..."
FunctionEnd

Function CreateDesktopShortcut
    ;create App shortcut on DESKTOP folder with custom icon
    MessageBox MB_OK "Desktop Shortcut created..."
FunctionEnd

No error message is received during displaying Finish page

EDIT: Solved using User32::SetWindowPos API function in order to modify the Custom controls Z-order

!define HWND_TOP 0
!define SWP_NOSIZE 0x0001
!define SWP_NOMOVE 0x0002

System::Call "User32::SetWindowPos(i, i, i, i, i, i, i) b ($hWndCtmCtl, ${HWND_TOP}, 0, 0, 0, 0, ${SWP_NOSIZE}|${SWP_NOMOVE})"

Solution

  • $mui.FinishPage.Text MUI static control with ${MUI_FINISHPAGE_TEXT} text is displaying on top of some of your controls.

    Hide it with

    Function MyFinishShow
    ShowWindow $mui.FinishPage.Text 0
    ...
    

    Or make it transparent if you want to keep the text and see your controls under it. You would have to move the checkbox down a bit if you want to keep the text so that they don't overlap.

    Function MyFinishShow
    SetCtlColors $mui.FinishPage.Text "${MUI_TEXTCOLOR}" transparent
    ...