Link to home
Start Free TrialLog in
Avatar of TCSCode
TCSCode

asked on

How do I make a install app act like installshield

How do I make a install program act like installshield, i would like to make a install program but i don't know how to make the forms go back and forth like installshield does. i want to have three buttons "Back,  Next, and Cancel". When the next butoon is pressed, I want the next form to show and the current form to hide. When i press the back button i want it to goto the previous form. How can i do this? examples code please. TCSCode.
Avatar of rwilson032697
rwilson032697

Here's a code snippet that will help you:

unit WizardUtils;

interface

uses
  ComCtrls,
  extctrls;

type
  TSetButtonEnablement = procedure of Object;

function WizardFindTheNextPage(PageControl : TPageControl;
                               GoForward: Boolean): TTabSheet;

procedure WizardChangePageControlTab(PageControl : TPageControl;
                                     Tab : TTabSheet;
                                     Image : TImage;
                                     SetButtonEnablement : TSetButtonEnablement);

implementation

function WizardFindTheNextPage(PageControl : TPageControl;
                               GoForward: Boolean): TTabSheet;
var
  increment : Integer;
begin
  Result := PageControl.ActivePage;
  if GoForward then
    Increment := 1
  else
    Increment := -1;

  if (Result.PageIndex + Increment >= 0) and
     (Result.PageIndex + Increment <= PageControl.Pagecount - 1) then
    repeat
      Result := PageControl.Pages[Result.PageIndex + Increment]
    until (Result.Enabled or
           (Result.PageIndex = 0) or
           (Result.PageIndex = PageControl.PageCount - 1))
  else
    Result := Nil;

  if assigned(Result) and not Result.Enabled then
    Result := Nil;
end;


procedure WizardChangePageControlTab(PageControl : TPageControl;
                                     Tab : TTabSheet;
                                     Image : TImage;
                                     SetButtonEnablement : TSetButtonEnablement);
var
  AllowChange : Boolean;
begin
  if not assigned(Tab) then
    exit;

  AllowChange := True;
  if Assigned(PageControl.OnChanging) then
    PageControl.OnChanging(Tab, AllowChange);

  if AllowChange then
    begin
      if assigned(Image) then
        Image.Parent := Tab;
      PageControl.ActivePage := Tab;
      SetButtonEnablement;
      if Assigned(PageControl.OnChange) then
        PageControl.OnChange(Tab);
    end;
end;

end.

Cheers,

Raymond.

Here's an example of how to use it - I have snipped out a bunch of code that really serves to confuse the issue - it pretty simple, the form has a page control with a number of pages on it as well as Next, Prev, Cancel and Finish buttons...

Give me a yell if you have any questions...

unit CrashPayment;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Grids, AdvGrid, ComCtrls, RippleComps, ExtCtrls,
  Mortgages,
  RippleForms;

type
  TCrashPaymentWizardForm = class(TRippleForm)

// Big snip for brevity

    btnHelp: TButton;
    btnPrevious: TButton;
    btnFinish: TButton;
    bntNext: TButton
// Another big snip

    procedure btnPreviousClick(Sender: TObject);
    procedure bntNextClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure btnHelpClick(Sender: TObject);
    procedure MemoEnter(Sender: TObject);
    procedure btnFinishClick(Sender: TObject);
    procedure PageControl1Change(Sender: TObject);
    procedure PageControl1Changing(Sender: TObject;
      var AllowChange: Boolean);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }

    procedure SetButtonEnablement;
  end;

var
  CrashPaymentWizardForm: TCrashPaymentWizardForm;

implementation

uses
  WizardUtils,
  ImageModule,
  MortCalcDecls;

{$R *.DFM}

procedure TCrashPaymentWizardForm.btnPreviousClick(Sender: TObject);
begin
  WizardChangePageControlTab(PageControl1,
                             WizardFindTheNextPage(PageControl1, false),
                             Image1, SetButtonEnablement);
end;

procedure TCrashPaymentWizardForm.bntNextClick(Sender: TObject);
begin
  WizardChangePageControlTab(PageControl1,
                             WizardFindTheNextPage(PageControl1, true),
                             Image1, SetButtonEnablement);
end;

procedure TCrashPaymentWizardForm.FormCreate(Sender: TObject);
begin
  PageControl1.ActivePage := PageControl1.Pages[0];
  SetButtonEnablement;
end;


procedure TCrashPaymentWizardForm.SetButtonEnablement;
begin
  btnPrevious.Enabled := PageControl1.Pages[0] <> PageControl1.ActivePage;
  bntNext.visible := WizardFindTheNextPage(PageControl1, true) <> Nil;
  btnFinish.visible := not bntNext.visible;
end;

procedure TCrashPaymentWizardForm.btnFinishClick(Sender: TObject);
var
  AllowChange : Boolean;
begin
  AllowChange := True;
  PageControl1Changing(PageControl1.ActivePage, AllowChange);
  if not AllowChange then
    exit;

  ModalResult := mrOK;
end;

procedure TCrashPaymentWizardForm.PageControl1Change(Sender: TObject);
var
//  I : integer;
  FreeIncome : Double;

begin
  If PageControl1.ActivePage = NameTab then
    begin
      ActiveControl := ScenarioNameEdit;
      ScenarioNameEdit.Text := TheScenario.Name;
      ScenarioDescriptionEdit.text := TheScenario.Description;
    end;

// Etc...

end;

procedure TCrashPaymentWizardForm.PageControl1Changing(Sender: TObject;
  var AllowChange: Boolean);
//var
//  I : Integer;
begin
  AllowChange := False;

  If PageControl1.ActivePage = NameTab then
    begin
      if not (ScenarioNameEdit.CheckValid) then
        exit;
      if ScenarioDescriptionEdit.text = '' then
        begin
          ShowMessage('Please supply a description');
          exit;
        end;

      TheScenario.Name := ScenarioNameEdit.Text;
      TheScenario.Description := ScenarioDescriptionEdit.text;
    end;

//Etc...
  AllowChange := True;
end;

procedure TCrashPaymentWizardForm.Button2Click(Sender: TObject);
begin
  if MessageDlg('Do you want to cancel setting up this crash repayment scenario?',
                mtConfirmation, [mbYes, mbNo], 0) = mrYes then
    begin
      TheScenario.Free;
      ModalResult := mrCancel;
    end;
end;

end.
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ComCtrls, StdCtrls, ExtCtrls;

const
  NUM_PANELS = 3;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Panel1: TPanel;
    Edit1: TEdit;
    Panel2: TPanel;
    Edit2: TEdit;
    Panel3: TPanel;
    Edit3: TEdit;
    procedure FormCreate(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
    pn: Integer;
    procedure SelectPanel;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
begin
  pn := 1;
  SelectPanel;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  if pn > 1 then
  begin
    dec(pn);
    SelectPanel;
  end;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  if pn < NUM_PANELS then
  begin
    Inc(pn);
    SelectPanel;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  close;
end;

procedure TForm1.SelectPanel;
var i: Integer;
begin
  for i := 1 to NUM_PANELS do
    TPanel(FindComponent('Panel' + IntToStr(i))).Visible := (i = pn);
end;

end.

TCS,
I'd have to say Eps has got it right mate. Use a single form with several panels of the same size and just hold a variable for each panel i.e.

procedure nextbuttonclick
begin
 Case (panelnumber) of
  1:begin
    end;
  2:begin
    end;
  and so on.... then have an identical event handler for the backbuttonclick

Gabe
Gabe: Why do you say that?

TCSCode: I should mention that you set the pages in the page control to hide their tab (ShowTab = False in object inspector).

Cheers,

Raymond.


Sorry Ray but the main massive application I have worked on with Delphi I started out using a pagecontrol and although it was easier to deal with in the IDE (slightly) in the long run the code is significantly more extensive for the pc (look at the difference between your example and eps) not to mention that PC's are flashy and dont switch smoothly through each other as a set of panels does which is why in my app I used panels and have found it alot easier to use.  This is of course just my opinion and I am not as advanced as you Ray, as is evidenced by our Expert points  lol :P  but from my own personal experience, panels is the way to go.

Gabe
Gabe: The code I posted perhaps does a little more than TSCCode requires as it supports removing pages from the 'wizard' without actually removing them from the page control itself.

I wrote the 'wizard' code as I have a number of wizards in my Mortgage Planner application - it made the amount of code required to manage each individual wizard quite small...

I have written several apps which use PCs extensively (even nested ones) with no flicker problems (though you have said in another thread you were using lots of images etc).

Well, TCSCode - its your call.

Cheers,

Raymond.

Raymond, Showtab := false means that the content of that tab will be invisible to I guess.....
Oops - There's no ShowTab property, I meant the TabVisible property.

(And no Epsylon, it doesn't mean the content of the tab is invisible :-)

Cheers,

Raymond.

Raymond, what about the SelectNext method:


procedure TForm1.NextButtonClick(Sender: TObject);
begin
  PageControl1.SelectNextPage(true);
end;

procedure TForm1.BackButtonClick(Sender: TObject);
begin
  PageControl1.SelectNextPage(false);
end;

Avatar of TCSCode

ASKER

Sorry rwilson, But I have to award Epsylon with the points. Epsylon's code is easier and smaller.
Avatar of TCSCode

ASKER

Epsylon answer this message for your points. Thank's for the help.
Thanks a lot TCSCode.


The answer is:

Use a few panels and stack them on top of each other. Make sure the panel's name are: Panel1, Panel2, ... Paneln.



Here is the code:


unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ComCtrls, StdCtrls, ExtCtrls;

const
  NUM_PANELS = 3;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Panel1: TPanel;
    Edit1: TEdit;
    Panel2: TPanel;
    Edit2: TEdit;
    Panel3: TPanel;
    Edit3: TEdit;
    procedure FormCreate(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
    pn: Integer;
    procedure SelectPanel;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
begin
  pn := 1;
  SelectPanel;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  if pn > 1 then
  begin
    dec(pn);
    SelectPanel;
  end;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  if pn < NUM_PANELS then
  begin
    Inc(pn);
    SelectPanel;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  close;
end;

procedure TForm1.SelectPanel;
var i: Integer;
begin
  for i := 1 to NUM_PANELS do
    TPanel(FindComponent('Panel' + IntToStr(i))).Visible := (i = pn);
end;

end.



Epsylon  :o)
epsylon: SelectNextPage is fine as long as you don't want the OnChange and OnChanging methods called. Of course this sucks badly when you're building a wizard as you need to validate the pages.

TCSCode: Well, as I say, it's your choice. Personally I think you are actually making work for yourself using panels, but that's just my opinion. Good luck.

Cheers,

Raymond.

ASKER CERTIFIED SOLUTION
Avatar of Epsylon
Epsylon

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Oh yeah, epsylon, your answer won't like reordering pages :-) (just another case where PC's are actually rather useful.

Cheers,

Raymond.

Raymond, to be honest, when I saw this question yesterday I wanted to answer this question with a PageControl solution as well the solution I just submitted as an answer. But when I saw that you answered it already I omitted the PageControl version. When I just came here I was supprised to see that I was asked to submit it.

Let TCSCode decide....

Epsylon.
Avatar of TCSCode

ASKER

Hi Epsylon,

Heres yours points, Thank's again.
Avatar of TCSCode

ASKER

Hi rwilson,

 Yes your code might save me work, if you can email me a copy of your code working to hyperon@eudoramail.com, then i will also reward you  with points aswel.

TCSCode.
TSCCode: I am emailing 'wizard.zip' to you, its a full project showing a simple three page PC - it also includes an image - note that the image is moved between pages 'cos I tend to use the same one for all pages in a particular wizard...

Cheers,

Raymond.

Avatar of TCSCode

ASKER

Great Thank's.