Search code examples
installationnsis

How to show some text on mouse move in NSIS installer


is there any possibility to show some descriptive text on NSIS installer custom page, but only on mouse hover?

I have the prerequisites check at the beginning of the installer and when one (or more) of the tests fail, appropriate warning message is displayed. It is custom page displayed before whole installation. The problem is, that there are too many messages (in the worst case) and installer page small -- it isn't possible to show all of them without overlaying... So I would like to display only some title (briefly describing the problem) and more detailed information somewhere below in the dedicated area, but only when mouse moved over the brief text. Or, other solution is to create some scrollable area...

But I don't know how to do it in NSIS. I know .onMouseOverSection callback, but AFAIK it can be used only in section selection page.

Is it possible to do it in NSIS page?

Thanks in advance.


Solution

  • I don't think doing this on the instfiles page is a good idea. I would go for a custom page. If you decide to go with the custom page idea, you probably have 3 options:

    • Create a custom nsis plugin that shows a page in any way you want.
    • Create a custom page with nsDialogs and handle the mouse messages with the WndSubclass plugin.
    • Use two component pages and tweak one of them.

    The following example uses the 3rd option since it uses only official nsis plugins.

    OutFile "$%temp%\test.exe"
    Name "Prereq desc"
    RequestExecutionLevel user
    !include MUI2.nsh
    
    !define MUI_PAGE_HEADER_TEXT "Header blablah"
    !define MUI_PAGE_HEADER_SUBTEXT "subheader blablah"
    !define MUI_COMPONENTSPAGE_TEXT_TOP "blablah 1"
    !define MUI_COMPONENTSPAGE_TEXT_INSTTYPE " "
    !define MUI_COMPONENTSPAGE_TEXT_COMPLIST " "
    !define MUI_COMPONENTSPAGE_TEXT_DESCRIPTION_TITLE "blablah 4"
    !define MUI_COMPONENTSPAGE_TEXT_DESCRIPTION_INFO "blablah 5"
    !define MUI_PAGE_CUSTOMFUNCTION_PRE prereqcreate
    !define MUI_PAGE_CUSTOMFUNCTION_SHOW prereqshow
    !insertmacro MUI_PAGE_COMPONENTS
    
    !define MUI_PAGE_CUSTOMFUNCTION_PRE componentscreate
    !insertmacro MUI_PAGE_COMPONENTS
    
    !insertmacro MUI_PAGE_INSTFILES
    !insertmacro MUI_LANGUAGE "English"
    
    Function .onInit
    InitPluginsDir
    StrCpy $0 0
    loop:
        ClearErrors
        SectionGetText $0 $1
        IfErrors done
        WriteIniStr "$Pluginsdir\sec.ini" S $0 $1 ;Save section names...
        IntOp $0 $0 + 1
        Goto loop
    done:   
    FunctionEnd
    
    !macro ShowSections initial flip
    StrCpy $0 0
    StrCpy $2 ${initial}
    loop:
        ClearErrors
        SectionGetText $0 $1
        IfErrors done
        ReadIniStr $1 "$Pluginsdir\sec.ini" S $0
        IntCmpU 0 $2 "" +2 +2
        StrCpy $1 ""
        SectionSetText $0 $1
        IntOp $0 $0 + 1
        IntCmpU $0 ${flip} "" +2 +2
        IntOp $2 $2 ! 
        Goto loop
    done:
    !macroend
    
    !macro CreatePreReq text name
    Section /o "${text}" ${name}
    SectionIn RO
    SectionEnd
    !macroend
    
    !insertmacro CreatePreReq "Windows Installer v4.5" SEC_PRMSI
    !insertmacro CreatePreReq ".NET v666" SEC_PRDOTNET
    
    Section "Program files" SEC_PROG
    ;...
    SectionEnd
    
    Section "Desktop shortcut" SEC_DESKLNK
    ;...
    SectionEnd
    
    !define FIRSTREALSECTION ${SEC_PROG}
    
    Function prereqcreate
    !insertmacro ShowSections 1 ${FIRSTREALSECTION}
    FunctionEnd
    
    Function prereqshow
    FindWindow $0 "#32770" "" $HWNDPARENT
    GetDlgItem $1 $0 0x3FD
    ShowWindow $1 0 
    GetDlgItem $1 $0 0x3FE
    ShowWindow $1 0 
    GetDlgItem $1 $0 0x3FF
    ShowWindow $1 0 ;hide space texts
    GetDlgItem $1 $0 0x408
    !define TVM_SETIMAGELIST 0x1109
    SendMessage $1 ${TVM_SETIMAGELIST} 2 0 ;Remove images (leaking the imagelist in the process, oh well)
    System::Call '*(&i24)i.r2'
    System::Call 'user32::GetWindowRect(ir1,ir2)'
    System::Call 'user32::MapWindowPoints(i0,ir0,ir2,i2)'
    System::Call '*$2(i,i.r0,i.r3,i.r4)'
    System::Free $2
    IntOp $4 $4 - $0
    System::Call 'user32::SetWindowPos(ir1,i0,i0,ir0,ir3,ir4,i0)'
    FunctionEnd
    
    Function componentscreate
    !insertmacro ShowSections 0 ${FIRSTREALSECTION}
    FunctionEnd
    
    !insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
      !insertmacro MUI_DESCRIPTION_TEXT ${SEC_PRMSI} "You need MSI in a NSIS installer? ;)"
      !insertmacro MUI_DESCRIPTION_TEXT ${SEC_PRDOTNET} "You need moar bloat!"
      !insertmacro MUI_DESCRIPTION_TEXT ${SEC_PROG} "Required program files..."
      !insertmacro MUI_DESCRIPTION_TEXT ${SEC_DESKLNK} "Stupid desktop shortcut"
    !insertmacro MUI_FUNCTION_DESCRIPTION_END