Custom Uninstall page (not MsgBox)

后端 未结 4 1565
南方客
南方客 2020-11-29 08:58

I need to ask the user for a password during install, which is then used as part of a command which runs after installation. I\'m using a custom page to do this and it works

相关标签:
4条回答
  • 2020-11-29 09:19

    Inno does not currently support wizard pages during uninstall. You will need to use Forms instead.

    0 讨论(0)
  • 2020-11-29 09:36

    I'm using InnoSetup 5.4.2 and in the docs are several Uninstall Event Functions including: procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);

    You should be able to create an input page within the [code] section.

    0 讨论(0)
  • You can modify the uninstall form to behave like the install form (with pages and the Next/Back buttons).

    In the InitializeUninstallProgressForm:

    • Create the new pages and insert them to the UninstallProgressForm.InnerNotebook (or the .OuterNotebook).
    • Implement the "Next" and the "Back" buttons.
    • You can also make the "Cancel" button working.
    • Run modal loop of the form using UninstallProgressForm.ShowModal.
    • Only after the modal loop exits, restore original layout of the form and let the uninstallation continue.
    [Code]
    
    var
      UninstallFirstPage: TNewNotebookPage;
      UninstallSecondPage: TNewNotebookPage;
      UninstallBackButton: TNewButton;
      UninstallNextButton: TNewButton;
    
    procedure UpdateUninstallWizard;
    begin
      if UninstallProgressForm.InnerNotebook.ActivePage = UninstallFirstPage then
      begin
        UninstallProgressForm.PageNameLabel.Caption := 'First uninstall wizard page';
        UninstallProgressForm.PageDescriptionLabel.Caption :=
          'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';
      end
        else
      if UninstallProgressForm.InnerNotebook.ActivePage = UninstallSecondPage then
      begin
        UninstallProgressForm.PageNameLabel.Caption := 'Second uninstall wizard page';
        UninstallProgressForm.PageDescriptionLabel.Caption :=
          'Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.';
      end;
    
      UninstallBackButton.Visible :=
        (UninstallProgressForm.InnerNotebook.ActivePage <> UninstallFirstPage);
    
      if UninstallProgressForm.InnerNotebook.ActivePage <> UninstallSecondPage then
      begin
        UninstallNextButton.Caption := SetupMessage(msgButtonNext);
        UninstallNextButton.ModalResult := mrNone;
      end
        else
      begin
        UninstallNextButton.Caption := 'Uninstall';
        { Make the "Uninstall" button break the ShowModal loop }
        UninstallNextButton.ModalResult := mrOK;
      end;
    end;  
    
    procedure UninstallNextButtonClick(Sender: TObject);
    begin
      if UninstallProgressForm.InnerNotebook.ActivePage = UninstallSecondPage then
      begin
        UninstallNextButton.Visible := False;
        UninstallBackButton.Visible := False;
      end
        else
      begin
        if UninstallProgressForm.InnerNotebook.ActivePage = UninstallFirstPage then
        begin
          UninstallProgressForm.InnerNotebook.ActivePage := UninstallSecondPage;
        end;
        UpdateUninstallWizard;
      end;
    end;
    
    procedure UninstallBackButtonClick(Sender: TObject);
    begin
      if UninstallProgressForm.InnerNotebook.ActivePage = UninstallSecondPage then
      begin
        UninstallProgressForm.InnerNotebook.ActivePage := UninstallFirstPage;
      end;
      UpdateUninstallWizard;
    end;
    
    procedure InitializeUninstallProgressForm();
    var
      PageText: TNewStaticText;
      PageNameLabel: string;
      PageDescriptionLabel: string;
      CancelButtonEnabled: Boolean;
      CancelButtonModalResult: Integer;
    begin
      if not UninstallSilent then
      begin
        { Create the first page and make it active }
        UninstallFirstPage := TNewNotebookPage.Create(UninstallProgressForm);
        UninstallFirstPage.Notebook := UninstallProgressForm.InnerNotebook;
        UninstallFirstPage.Parent := UninstallProgressForm.InnerNotebook;
        UninstallFirstPage.Align := alClient;
    
        PageText := TNewStaticText.Create(UninstallProgressForm);
        PageText.Parent := UninstallFirstPage;
        PageText.Top := UninstallProgressForm.StatusLabel.Top;
        PageText.Left := UninstallProgressForm.StatusLabel.Left;
        PageText.Width := UninstallProgressForm.StatusLabel.Width;
        PageText.Height := UninstallProgressForm.StatusLabel.Height;
        PageText.AutoSize := False;
        PageText.ShowAccelChar := False;
        PageText.Caption := 'Press Next to proceeed with uninstallation.';
    
        UninstallProgressForm.InnerNotebook.ActivePage := UninstallFirstPage;
    
        PageNameLabel := UninstallProgressForm.PageNameLabel.Caption;
        PageDescriptionLabel := UninstallProgressForm.PageDescriptionLabel.Caption;
    
        { Create the second page }
    
        UninstallSecondPage := TNewNotebookPage.Create(UninstallProgressForm);
        UninstallSecondPage.Notebook := UninstallProgressForm.InnerNotebook;
        UninstallSecondPage.Parent := UninstallProgressForm.InnerNotebook;
        UninstallSecondPage.Align := alClient;
    
        PageText := TNewStaticText.Create(UninstallProgressForm);
        PageText.Parent := UninstallSecondPage;
        PageText.Top := UninstallProgressForm.StatusLabel.Top;
        PageText.Left := UninstallProgressForm.StatusLabel.Left;
        PageText.Width := UninstallProgressForm.StatusLabel.Width;
        PageText.Height := UninstallProgressForm.StatusLabel.Height;
        PageText.AutoSize := False;
        PageText.ShowAccelChar := False;
        PageText.Caption := 'Press Uninstall to proceeed with uninstallation.';
    
        UninstallNextButton := TNewButton.Create(UninstallProgressForm);
        UninstallNextButton.Parent := UninstallProgressForm;
        UninstallNextButton.Left :=
          UninstallProgressForm.CancelButton.Left -
          UninstallProgressForm.CancelButton.Width -
          ScaleX(10);
        UninstallNextButton.Top := UninstallProgressForm.CancelButton.Top;
        UninstallNextButton.Width := UninstallProgressForm.CancelButton.Width;
        UninstallNextButton.Height := UninstallProgressForm.CancelButton.Height;
        UninstallNextButton.OnClick := @UninstallNextButtonClick;
    
        UninstallBackButton := TNewButton.Create(UninstallProgressForm);
        UninstallBackButton.Parent := UninstallProgressForm;
        UninstallBackButton.Left :=
          UninstallNextButton.Left - UninstallNextButton.Width -
          ScaleX(10);
        UninstallBackButton.Top := UninstallProgressForm.CancelButton.Top;
        UninstallBackButton.Width := UninstallProgressForm.CancelButton.Width;
        UninstallBackButton.Height := UninstallProgressForm.CancelButton.Height;
        UninstallBackButton.Caption := SetupMessage(msgButtonBack);
        UninstallBackButton.OnClick := @UninstallBackButtonClick;
        UninstallBackButton.TabOrder := UninstallProgressForm.CancelButton.TabOrder;
    
        UninstallNextButton.TabOrder := UninstallBackButton.TabOrder + 1;
    
        UninstallProgressForm.CancelButton.TabOrder := UninstallNextButton.TabOrder + 1;
    
        { Run our wizard pages } 
        UpdateUninstallWizard;
        CancelButtonEnabled := UninstallProgressForm.CancelButton.Enabled
        UninstallProgressForm.CancelButton.Enabled := True;
        CancelButtonModalResult := UninstallProgressForm.CancelButton.ModalResult;
        UninstallProgressForm.CancelButton.ModalResult := mrCancel;
    
        if UninstallProgressForm.ShowModal = mrCancel then Abort;
    
        { Restore the standard page payout }
        UninstallProgressForm.CancelButton.Enabled := CancelButtonEnabled;
        UninstallProgressForm.CancelButton.ModalResult := CancelButtonModalResult;
    
        UninstallProgressForm.PageNameLabel.Caption := PageNameLabel;
        UninstallProgressForm.PageDescriptionLabel.Caption := PageDescriptionLabel;
    
        UninstallProgressForm.InnerNotebook.ActivePage :=
          UninstallProgressForm.InstallingPage;
      end;
    end;
    


    See also Inno Setup - How to create a OuterNotebook/welcome page in the uninstaller?

    0 讨论(0)
  • 2020-11-29 09:41

    Luckily Inno Setup gives enough abilities to build own forms so you can imitate any page of uninstall form on another modal form. Here's what I managed to create. The form takes dimensions from UninstallForm, contains a TNewNotebook control and buttons to jump between pages and to cancel the dialog.

    demo

    const
      ControlGap = 5; // determined empirically
    
    // Set Back/Next buttons state according to current selected notebook page
    procedure UpdateButtonsState(Form: TSetupForm);
    var
      Notebook: TNewNotebook;
      BtnBack, BtnNext: TButton;
    begin
      Notebook := TNewNotebook(Form.FindComponent('Notebook'));
      BtnBack := TButton(Form.FindComponent('BtnBack'));
      BtnNext := TButton(Form.FindComponent('BtnNext'));
    
      // Update buttons state
      BtnBack.Enabled := (Notebook.ActivePage <> Notebook.Pages[0]);
      if Notebook.ActivePage <> Notebook.Pages[Notebook.PageCount - 1] then
      begin
        BtnNext.Caption := SetupMessage(msgButtonNext)
        BtnNext.ModalResult := mrNone;
      end
      else
      begin
        BtnNext.Caption := SetupMessage(msgButtonFinish);
        BtnNext.ModalResult := mrYes;
      end;
    end;
    
    // Change notebook page
    procedure BtnPageChangeClick(Sender: TObject);
    var
      NextPage: TNewNotebookPage;
      Notebook: TNewNotebook;
      Form: TWinControl;
      Button, BtnBack, BtnNext: TButton;
    begin
      Button := TButton(Sender);
      Form := Button;
      while not (Form is TSetupForm) do
        Form := Form.Parent;
      Notebook := TNewNotebook(Form.FindComponent('Notebook'));
      BtnBack := TButton(Form.FindComponent('BtnBack'));
      BtnNext := TButton(Form.FindComponent('BtnNext'));
    
      // Avoid cycled style of Notebook's page looping
      if (Button = BtnBack) and (Notebook.ActivePage = Notebook.Pages[0]) then
        NextPage := nil
      else
      if (Button = BtnNext) and (Notebook.ActivePage = Notebook.Pages[Notebook.PageCount - 1]) then
        NextPage := nil
      else
        NextPage := Notebook.FindNextPage(Notebook.ActivePage, Button = BtnNext);
      Notebook.ActivePage := NextPage;
    
      UpdateButtonsState(TSetupForm(Form));
    end;
    
    // Add a new page to notebook and return it
    function AddPage(NotebookForm: TSetupForm): TNewNotebookPage;
    var
      Notebook: TNewNotebook;
    begin
      Notebook := TNewNotebook(NotebookForm.FindComponent('Notebook'));
      Result := TNewNotebookPage.Create(Notebook);
      Result.Notebook:=Notebook;
      Result.Parent:=Notebook;
      Result.Align := alClient;
      if Notebook.ActivePage = nil then 
        Notebook.ActivePage := Result;
      UpdateButtonsState(NotebookForm);
    end;
    
    // Create a form with notebook and 3 buttons: Back, Next, Cancel
    function CreateNotebookForm: TSetupForm;
    var
      Notebook: TNewNotebook;
      NotebookPage: TNewNotebookPage;
      Pan: TPanel;
      TmpLabel: TLabel;
      MaxWidth, i: Integer;
      BtnBack, BtnNext, BtnCancel: TButton;
      BtnLabelMsgIDs: array of TSetupMessageID;
    begin
      Result := CreateCustomForm;
      Result.SetBounds(0, 0, UninstallProgressForm.Width, UninstallProgressForm.Height);
      Result.Position := poOwnerFormCenter;
    
      Notebook := TNewNotebook.Create(Result);
      Notebook.Parent := Result;
      Notebook.Name := 'Notebook';  // will be used for searching
      Notebook.Align := alClient;
    
      Pan := TPanel.Create(Result);
      Pan.Parent := Notebook;
      Pan.Caption := '';
      Pan.Align := alBottom;
    
      // Create buttons
    
      BtnNext := TNewButton.Create(Result);
      with BtnNext do
      begin
        Parent := Pan;
        Name := 'BtnNext';  // will be used for searching
        Caption := SetupMessage(msgButtonNext);
        OnClick := @BtnPageChangeClick;
        ParentFont := True;
      end;
    
      BtnBack := TNewButton.Create(Result);
      with BtnBack do
      begin
        Parent := Pan;
        Caption := SetupMessage(msgButtonBack);
        Name := 'BtnBack';  // will be used for searching
        OnClick := @BtnPageChangeClick;
        ParentFont := True;
      end;
    
      BtnCancel := TNewButton.Create(Result);
      with BtnCancel do
      begin
        Parent := Pan;
        Name := 'BtnCancel';  // will be used for searching
        Caption := SetupMessage(msgButtonCancel);
        ModalResult := mrCancel;
        Cancel := True;
        ParentFont := True;
      end;
    
      // Determine dimensions of buttons. Should use TCanvas.TextWidth here
      // but it doesn't allow Font property assignment :(
    
      TmpLabel := TLabel.Create(Result);
      with TmpLabel do
      begin
        Left := 0;
        Top := 0;
        Parent := Pan;
        ParentFont := True;
        Visible := False;
        WordWrap := False;
        Autosize := True;
      end;
    
      // Determine max label width among these labels: Back, Next, Cancel, Finish
      SetArrayLength(BtnLabelMsgIDs, 4);
      BtnLabelMsgIDs[0] := msgButtonBack;
      BtnLabelMsgIDs[1] := msgButtonNext;
      BtnLabelMsgIDs[2] := msgButtonCancel;
      BtnLabelMsgIDs[3] := msgButtonFinish;
      MaxWidth := 0;
      for i := Low(BtnLabelMsgIDs) to High(BtnLabelMsgIDs) do
      begin
        TmpLabel.Caption := SetupMessage(BtnLabelMsgIDs[i]) + 'WWW';  // Add letters for surrounding spaces 
        if MaxWidth < TmpLabel.Width then
          MaxWidth := TmpLabel.Width;
      end;
    
      TmpLabel.Caption := 'Yy';  // Determine height
    
      // Assign sizes and positions
      Pan.ClientHeight := TmpLabel.Height*4;
    
      with BtnBack do
      begin
        Width := MaxWidth;
        Height := TmpLabel.Height*2;
        Left := Parent.ClientWidth - 3*(MaxWidth + ScaleX(ControlGap));
        Top := (Parent.ClientHeight - Height) div 2;
      end;
      with BtnNext do
      begin
        Width := MaxWidth;
        Height := TmpLabel.Height*2;
        Left := Parent.ClientWidth - 2*(MaxWidth + ScaleX(ControlGap));
        Top := (Parent.ClientHeight - Height) div 2;
      end;
      with BtnCancel do
      begin
        Width := MaxWidth;
        Height := TmpLabel.Height*2;
        Left := Parent.ClientWidth - 1*(MaxWidth + ScaleX(ControlGap));
        Top := (Parent.ClientHeight - Height) div 2;
      end;
    end;
    

    Usage is like

    // UninstallProgressForm is about to be shown
    // Show modal dialog which allows to select additional components to uninstall
    procedure InitializeUninstallProgressForm;
    var
      Form: TSetupForm;
      i: Integer;
      NotebookPage: TNewNotebookPage;
      ModResult: Integer;
    begin
      Form := CreateNotebookForm;
      for i := 1 to 4 do
      begin
        NotebookPage := AddPage(Form);
        with NotebookPage do
        begin
          Color := clWindow;
          with TLabel.Create(Form) do
          begin
            Parent := NotebookPage;
            SetBounds(0, 0, 50, 30);
            Autosize := true;
            Font.Size := 14;
            Caption := 'Label ' + IntToStr(i);
          end;
        end;
      end;
    
      ModResult := Form.ShowModal;
      if ModResult = mrYes then
        MsgBox('Continuing uninstall', mbInformation, MB_OK)
      else
      begin
        MsgBox('Cancelled', mbInformation, MB_OK);
        Abort;
      end;
    
      ...
    end;
    
    0 讨论(0)
提交回复
热议问题