Is it possible to list the progress like it does in other installers?
You can monitor changes in WizardForm.StatusLabel and WizardForm.FilenameLabel and add them to your custom list box progress view.
const
GWL_WNDPROC = -4;
SB_VERT = 1;
SB_BOTTOM = 7;
WM_VSCROLL = $0115;
WM_ERASEBKGND = $0014;
type
WPARAM = UINT_PTR;
LPARAM = LongInt;
LRESULT = LongInt;
var
OldStatusLabelWndProc: LongInt;
OldFilenameLabelWndProc: LongInt;
OldProgressListBoxWndProc: LongInt;
ProgressListBox: TNewListBox;
PrevStatus: string;
PrevFileName: string;
function CallWindowProc(
lpPrevWndFunc: LongInt; hWnd: HWND; Msg: UINT; wParam: WPARAM;
lParam: LPARAM): LRESULT; external 'CallWindowProcW@user32.dll stdcall';
function SetWindowLong(hWnd: HWND; nIndex: Integer; dwNewLong: LongInt): LongInt;
external 'SetWindowLongW@user32.dll stdcall';
procedure AddProgress(S: string);
begin
if S <> '' then
begin
ProgressListBox.Items.Add(S);
ProgressListBox.ItemIndex := ProgressListBox.Items.Count;
SendMessage(ProgressListBox.Handle, WM_VSCROLL, SB_BOTTOM, 0);
end;
end;
function StatusLabelWndProc(
hwnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT;
begin
Result := CallWindowProc(OldStatusLabelWndProc, hwnd, uMsg, wParam, lParam);
if PrevStatus <> WizardForm.StatusLabel.Caption then
begin
AddProgress(WizardForm.StatusLabel.Caption);
PrevStatus := WizardForm.StatusLabel.Caption;
end;
end;
function FilenameLabelWndProc(
hwnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT;
begin
Result := CallWindowProc(OldFilenameLabelWndProc, hwnd, uMsg, wParam, lParam);
if PrevFileName <> WizardForm.FilenameLabel.Caption then
begin
AddProgress(WizardForm.FilenameLabel.Caption);
PrevFileName := WizardForm.FilenameLabel.Caption;
end;
end;
function ProgressListBoxWndProc(
hwnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT;
begin
// reduce flicker
if uMsg = WM_ERASEBKGND then
begin
Result := 1;
end
else
begin
Result := CallWindowProc(OldProgressListBoxWndProc, hwnd, uMsg, wParam, lParam);
end;
end;
procedure InitializeWizard();
begin
OldStatusLabelWndProc :=
SetWindowLong(WizardForm.StatusLabel.Handle, GWL_WNDPROC,
CreateCallback(@StatusLabelWndProc));
OldFilenameLabelWndProc :=
SetWindowLong(WizardForm.FilenameLabel.Handle, GWL_WNDPROC,
CreateCallback(@FilenameLabelWndProc));
WizardForm.ProgressGauge.Top := WizardForm.FilenameLabel.Top;
ProgressListBox := TNewListBox.Create(WizardForm);
ProgressListBox.Parent := WizardForm.ProgressGauge.Parent;
ProgressListBox.Top :=
WizardForm.ProgressGauge.Top + WizardForm.ProgressGauge.Height + ScaleY(8);
ProgressListBox.Width := WizardForm.FilenameLabel.Width;
ProgressListBox.Height :=
ProgressListBox.Parent.ClientHeight - ProgressListBox.Top - ScaleY(16);
ProgressListBox.Anchors := [akLeft, akTop, akRight, akBottom];
OldProgressListBoxWndProc :=
SetWindowLong(ProgressListBox.Handle, GWL_WNDPROC,
CreateCallback(@ProgressListBoxWndProc));
// Lame way to shrink width of labels to client width of the list box,
// so that particularly when the file paths in FilenameLabel are shortened
// to fit to the label, they actually fit even to the list box.
WizardForm.StatusLabel.Width := WizardForm.StatusLabel.Width - ScaleY(24);
WizardForm.FilenameLabel.Width := WizardForm.FilenameLabel.Width - ScaleY(24);
end;
procedure DeinitializeSetup();
begin
// In case you are using VCL styles or similar, this needs to be done before
// you unload the style.
SetWindowLong(WizardForm.StatusLabel.Handle, GWL_WNDPROC, OldStatusLabelWndProc);
SetWindowLong(WizardForm.FilenameLabel.Handle, GWL_WNDPROC, OldFilenameLabelWndProc);
SetWindowLong(ProgressListBox.Handle, GWL_WNDPROC, OldProgressListBoxWndProc);
end;