DetailUpdate

From NSIS Wiki
Jump to navigationJump to search
Author: Afrow UK (talk, contrib)


Description

A small function/macro combo to update the text of the last item printed in the install files page list view control. It also updates the status label above the progress bar with the same text.

The Function

Function DetailUpdate
  Exch $R0
  Push $R1
  Push $R2
  Push $R3
 
  FindWindow $R2 `#32770` `` $HWNDPARENT
  GetDlgItem $R1 $R2 1006
  SendMessage $R1 ${WM_SETTEXT} 0 `STR:$R0`
  GetDlgItem $R1 $R2 1016
 
  System::Call *(&t${NSIS_MAX_STRLEN}R0)i.R2
  System::Call *(i0,i0,i0,i0,i0,iR2,i${NSIS_MAX_STRLEN},i0,i0)i.R3
 
  !define LVM_GETITEMCOUNT 0x1004
  !define LVM_SETITEMTEXT 0x102E
  SendMessage $R1 ${LVM_GETITEMCOUNT} 0 0 $R0
  IntOp $R0 $R0 - 1
  System::Call user32::SendMessage(iR1,i${LVM_SETITEMTEXT},iR0,iR3)
 
  System::Free $R3
  System::Free $R2
 
  Pop $R3
  Pop $R2
  Pop $R1
  Pop $R0
FunctionEnd
!macro DetailUpdate Text
  Push `${Text}`
  Call DetailUpdate
!macroend
!define DetailUpdate `!insertmacro DetailUpdate`

I've decided to use the System plug-in to call SendMessage for setting the list view item text. This probably isn't necessary (the built in SendMessage did work as well) but as System has allocated the memory I'd rather be on the safe side and use that instead.

Usage

Function SomeProcess
  DetailPrint `Processing: 0% done...`
  ${For} $R0 1 5
    Sleep 2000
    IntOp $R1 $R0 * 20
    ${DetailUpdate} `Processing: $R1% done...`
  ${Next}
  ${DetailUpdate} `Processing complete!`
FunctionEnd
 
Section `Some process`
  Call SomeProcess
SectionEnd

Note that I've placed the loop inside a function and called that function from the section otherwise the progress bar will move back and forth.

Background

The install files page window is just a standard Windows SysListView32 control which means you can send any of the LVM_* messages to it. Some messages however such as LVM_SETITEMTEXT require a LVITEM struct as well as a buffer containing the text to set. The first System::Call allocates that buffer and initialises it with the new text and the second System::Call allocates the LVITEM struct containing a pointer to that buffer. At the end we have to free these two chunks of allocated memory using System::Free. Using this code it should be straight forward to work with other list view controls such as with nsDialogs.