Search code examples
windows-installernsis

create custom page with check boxes and test fields NSIS installer


I would like to add a page to my installer. The page should include a checkbox with a corresponding label, as well as two text boxes with their respective labels. Initially, the text boxes should be visible but not editable. If the checkbox is selected, then the two text boxes should become editable, and vice versa.

I have included my labels inside the .ini file.

; SelectionPage.ini

[Controls]
CheckboxID=1000
Textbox1ID=1001
Textbox2ID=1002

[Texts]
Header="Custom Page"
HeaderText="This is a custom page with editable text boxes."
EnableText="Enable Textboxes:"
Textbox1Label="Textbox 1:"
Textbox2Label="Textbox 2:"

and here is my code inside the .nsi file:

!macro ReadIniFile
    !define PAGE_INI "PlatformConfigPage.ini"
    !ifdef PAGE_INI
        !include LogicLib.nsh
        !include FileFunc.nsh
        ReadINIStr $0 "${PAGE_INI}" "Texts" "HeaderText"
        !define HEADER_TEXT $0
        ReadINIStr $0 "${PAGE_INI}" "Texts" "EnableText"
        !define ENABLE_TEXT $0
        ReadINIStr $0 "${PAGE_INI}" "Texts" "Textbox1Label"
        !define TEXTBOX1_LABEL $0
        ReadINIStr $0 "${PAGE_INI}" "Texts" "Textbox2Label"
        !define TEXTBOX2_LABEL $0
    !endif
!macroend

Function ShowPlatformConfigPage
    Call wel_pre
    !insertmacro MUI_HEADER_TEXT "$(ID_PLATFORM_CONFIGURATION_PAGE_TITLE)" ""

    ; Invoke ReadIniFile to read configuration from idPlatformConfigPage.ini
    !insertmacro ReadIniFile


    nsDialogs::Create 1018
    Pop $0

    ${If} $0 == error
        Abort
    ${EndIf}

    nsDialogs::CreateControl "Checkbox" ${WS_VISIBLE}|${WS_TABSTOP}|${WS_CHILD} ${DEFAULT_STYLES}|${BS_CHECKBOX} 0 0 100% 10% "${ENABLE_TEXT}"
    Pop $0
    ${NSD_CreateLabel} 0% 15% 100% 10% "${ENABLE_TEXT}"
    Pop $CB_Label
    ${NSD_CreateCheckbox} 30% 15% 70% 10% "Enable" ${DEFAULT_STYLES} ${WS_VISIBLE}|${WS_TABSTOP}|0x00000002 
    Pop $CB_EnableCheckbox
    ${NSD_AddStyle} $CB_EnableCheckbox ${BS_NOTIFY}

    ; Textbox 1
    ${NSD_CreateLabel} 10% 30% 20% 10% "${TEXTBOX1_LABEL}"
    Pop $0
    ${NSD_CreateText} 30% 30% 60% 10% "" ${DEFAULT_STYLES} ${WS_VISIBLE}|${WS_TABSTOP}
    Pop $TB1_Text
    EnableWindow $TB1_Text 0 ; Initially, disable the text box

    ; Textbox 2
    ${NSD_CreateLabel} 10% 45% 20% 10% "${TEXTBOX2_LABEL}"
    Pop $0
    ${NSD_CreateText} 30% 45% 60% 10% "" ${DEFAULT_STYLES} ${WS_VISIBLE}|${WS_TABSTOP}
    Pop $TB2_Text
    EnableWindow $TB2_Text 0 ; Initially, disable the text box


    nsDialogs::Show

    ${NSD_OnClick} $3 OnCheckboxClicked
FunctionEnd

Function OnCheckboxClicked
    ${NSD_GetState} $3 $0
    ${If} $0 = ${BST_CHECKED}
        EnableWindow $5 1 ; Enable Textbox 1
        EnableWindow $7 1 ; Enable Textbox 2

    ${Else}
        EnableWindow $5 0 ; Disable Textbox 1
        EnableWindow $7 0 ; Disable Textbox 2

    ${EndIf}
FunctionEnd

Hoeer I got confused and I get this error: Usage:

Pop $(user_var: output)

Solution

    • That error means you failed to provide a register/variable to pop into but I can't tell where in your incomplete code.
    • Using defines like you are doing there just makes everything confusing.
    • The Control IDs are not guaranteed when using nsDialogs

    Try this:

    RequestExecutionLevel user
    !include nsDialogs.nsh
    !include MUI2.nsh
        
    Var Checked
    Var Text1
    Var Text2
    
    Page Custom Showid8PlatformConfigPage
    !insertmacro MUI_PAGE_COMPONENTS
    !insertmacro MUI_PAGE_INSTFILES
    !insertmacro MUI_LANGUAGE English
    
    Function .onInit
    StrCpy $Text1 "Hello" ; Default value
    StrCpy $Text2 "World"
    
    InitPluginsDir
    ; Replace this with "File whatever.ini" if you are doing some kind of translation thing
    !tempfile ini
    !appendfile "${ini}" '[Texts]$\n'
    !appendfile "${ini}" 'id8Header="Custom Page"$\n'
    !appendfile "${ini}" 'id8HeaderText="This is a custom page with editable text boxes."$\n'
    !appendfile "${ini}" 'id8EnableText="Enable Textboxes:"$\n'
    !appendfile "${ini}" 'id8Textbox1Label="Textbox 1:"$\n'
    !appendfile "${ini}" 'id8Textbox2Label="Textbox 2:"$\n'
    File '/oname=$PluginsDir\UI.ini' "${ini}"
    !delfile "${ini}"
    FunctionEnd
    
    Function Showid8PlatformConfigPage
        ReadIniStr $1 "$PluginsDir\UI.ini" Texts id8Header
        ReadIniStr $2 "$PluginsDir\UI.ini" Texts id8HeaderText
        !insertmacro MUI_HEADER_TEXT "$1" "$2"
    
        nsDialogs::Create 1018
        Pop $0
        ${If} $0 == error
            Abort
        ${EndIf}
    
        ReadIniStr $0 "$PluginsDir\UI.ini" Texts id8EnableText
        ${NSD_CreateCheckbox} 30% 15% 70% 10% "$0"
        Pop $3
        ${NSD_OnClick} $3 OnCheckboxClicked
        SendMessage $3 ${BM_SETCHECK} $Checked 0
    
        ; Textbox 1
        ReadIniStr $0 "$PluginsDir\UI.ini" Texts id8Textbox1Label
        ${NSD_CreateLabel} 10% 30% 20% 10% "$0"
        Pop $0
        ${NSD_CreateText} 30% 30% 60% 10% "$Text1"
        Pop $1
    
        ; Textbox 2
        ReadIniStr $0 "$PluginsDir\UI.ini" Texts id8Textbox2Label
        ${NSD_CreateLabel} 10% 45% 20% 10% "$0"
        Pop $0
        ${NSD_CreateText} 30% 45% 60% 10% "$Text2"
        Pop $2
    
        Push 0
        Call OnCheckboxClicked ; Initialize textbox state
        nsDialogs::Show
    FunctionEnd
    
    Function OnCheckboxClicked
        Pop $0
        ${NSD_GetState} $3 $0
        IntOp $Checked "" || $0
        EnableWindow $1 $Checked
        EnableWindow $2 $Checked
    FunctionEnd
    
    Section
    MessageBox MB_OK "Checked=$Checked$\n1=$Text1$\n2=$Text2"
    SectionEnd