Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

How do I make a install app act like installshield

Posted on 1999-07-12
21
Medium Priority
?
290 Views
Last Modified: 2010-04-06
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.
0
Comment
Question by:TCSCode
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 8
  • 6
  • 5
  • +1
21 Comments
 
LVL 12

Expert Comment

by:rwilson032697
ID: 1387934
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.

0
 
LVL 12

Expert Comment

by:rwilson032697
ID: 1387935
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.
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 1387936
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.

0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 

Expert Comment

by:GabeinOZ
ID: 1387937
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
0
 
LVL 12

Expert Comment

by:rwilson032697
ID: 1387938
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.


0
 

Expert Comment

by:GabeinOZ
ID: 1387939
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
0
 
LVL 12

Expert Comment

by:rwilson032697
ID: 1387940
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.

0
 
LVL 13

Expert Comment

by:Epsylon
ID: 1387941
Raymond, Showtab := false means that the content of that tab will be invisible to I guess.....
0
 
LVL 12

Expert Comment

by:rwilson032697
ID: 1387942
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.

0
 
LVL 13

Expert Comment

by:Epsylon
ID: 1387943
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;

0
 

Author Comment

by:TCSCode
ID: 1387944
Sorry rwilson, But I have to award Epsylon with the points. Epsylon's code is easier and smaller.
0
 

Author Comment

by:TCSCode
ID: 1387945
Epsylon answer this message for your points. Thank's for the help.
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 1387946
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)
0
 
LVL 12

Expert Comment

by:rwilson032697
ID: 1387947
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.

0
 
LVL 13

Accepted Solution

by:
Epsylon earned 600 total points
ID: 1387948
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)
0
 
LVL 12

Expert Comment

by:rwilson032697
ID: 1387949
Oh yeah, epsylon, your answer won't like reordering pages :-) (just another case where PC's are actually rather useful.

Cheers,

Raymond.

0
 
LVL 13

Expert Comment

by:Epsylon
ID: 1387950
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.
0
 

Author Comment

by:TCSCode
ID: 1387951
Hi Epsylon,

Heres yours points, Thank's again.
0
 

Author Comment

by:TCSCode
ID: 1387952
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.
0
 
LVL 12

Expert Comment

by:rwilson032697
ID: 1387953
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.

0
 

Author Comment

by:TCSCode
ID: 1387954
Great Thank's.
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
In this brief tutorial Pawel from AdRem Software explains how you can quickly find out which services are running on your network, or what are the IP addresses of servers responsible for each service. Software used is freeware NetCrunch Tools (https…
We’ve all felt that sense of false security before—locking down external access to a database or component and feeling like we’ve done all we need to do to secure company data. But that feeling is fleeting. Attacks these days can happen in many w…
Suggested Courses

662 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question