⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uwizard.pas

📁 DelphiDoc is a program for automatic generation of documentation on a Delphi-Project. At the momen
💻 PAS
📖 第 1 页 / 共 2 页
字号:
{  JADD - Just Another DelphiDoc: Documentation from Delphi Source Code

Copyright (C) 2005-2008   Gerold Veith

This file is part of JADD - Just Another DelphiDoc.

DelphiDoc is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 3 as
published by the Free Software Foundation.

DelphiDoc is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
}


unit UWizard;

{Contains the base class, ~[link TWizardPage], of all pages to be used in a
 wizard and a simple form to show the wizard, ~[link TFormWizard].~[br]
 I'm not really happy with this layout, because it means an inflation of
 classes, but I can't think of a much better way. Perhaps it could be made to
 include several pages inside one class, but still allow to use several classes
 for several threads of pages, to keep the dynamic connectivity. But up to now
 it's like it's here defined. }

interface

uses
  Windows, Classes,
{$IFNDEF LINUX}
  Messages, Graphics, Controls, Forms, Dialogs, StdCtrls, Buttons,
{$ELSE}
  QControls, QStdCtrls, QForms, QButtons, QDialogs,
{$ENDIF}
  SysUtils;

type



   { * * *  ***  * * *  ***   TFormWizard   ***  * * *  ***  * * *  }


  //a base class of classes describing pages of a wizard
  TWizardPage = class;
  //a class describing a page of a wizard
  TWizardPageClass = class of TWizardPage;


  //buttons to be used in the wizard
  TWizardButton = (
                   wbBack,    //the button to go back to the previous page
                   wbNext,    //the button to go the next page
                   wbClose);  //the button to close the wizard
  //a set of the buttons to be used in the wizard
  TWizardButtons = set of TWizardButton;


  {A simple window serving as the host for a set of pages of a wizard to serve
   the wizard to the user. Contains a group box, on which the pages of the
   wizard can create components etc., and three buttons to go to the next page,
   to the previous page or to close the wizard. }
  TFormWizard = class(TForm)
    GroupBox: TGroupBox;
    BitBtnBack: TBitBtn;
    BitBtnNext: TBitBtn;
    BitBtnClose: TBitBtn;
    procedure BitBtnBackClick(Sender: TObject);
    procedure BitBtnNextClick(Sender: TObject);
    procedure BitBtnCloseClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormDestroy(Sender: TObject);
  private
    //the first page of the wizard
    FFirstPage: TWizardPage;
    //the currently shown page of the wizard
    FCurrentPage: TWizardPage;

    //Called to show a new page of the wizard.
    procedure InitWizardPage(NewPage: TWizardPage);
    //Called to hide a page of the wizard and show a new one.
    procedure DeInitWizardPage(NewPage: TWizardPage);
  public
    //Can be called to update the state of the three buttons according to the
    //current page of the wizard.
    procedure UpdateButtons;
    //Can be called to change the current page of the wizard
    //(actually can't be called without an error).
    procedure ChangeCurrentWizardPage(NewPage: TWizardPage);


    //Starts the wizard with the given page.
    procedure StartWizard(StartPageClass: TWizardPageClass; Data: TObject);
  end;









{$IFDEF LINUX}
  //seems not to be defined in Kylix strangely
  TControlClass = class of TControl;
{$ENDIF}




   { * * *  ***  * * *  ***   TWizardPage   ***  * * *  ***  * * *  }


  {The base class of all pages in a wizard. Each view, each page of a wizard is
   implemented by creating a class descending from this one that will create
   and handle all needed components. The pages are connected by references from
   each page to its predecessor and successor (and maybe sub-pages). It should
   always be possible to go back and then forward and also always to close the
   wizard. }
  TWizardPage = class
  private
    FData: TObject;             //some data to the wizard
    FForm: TForm;               //the form to show the page on
    FParent: TWinControl;       //parent to create all components on
    FComponents: TList;         //list of created components by the page
    //the preceding page, to which can be returned
    FPreviousPage: TWizardPage;
    //if it is a sub-thread of the wizard, the page that started the sub-thread
    //to return to, when it ends
    FSuperPage: TWizardPage;

    //Gets a caption of one of the three buttons.
    function GetButtonCaptions(Button: TWizardButton): String;
    //Calculated the needed height of a text field to fit all text visible in
    //it (Windows only).
    function GetMemoHeight(Memo: TMemo; Lines: Integer): Integer;
  protected
    FNextPage: TWizardPage;     //the succeeding page, if already created

    FCaption: String;           //caption of the page
    //captions of the three buttons
    FButtonCaptions: array[TWizardButton] of String;
    //what of the three buttons are enabled
    FButtonsEnabled: TWizardButtons;
    FHelpContext: THelpContext; //help context of the page

    //vertical position to create the next component of the page
    FNewComponentTop: Integer;



    //Creates a component of the page.
    function CreateControl(Control: TControlClass): TControl;
    //Creates a text field on the page.
    function AddEditField(Text: String): TEdit;
    //Creates a text field to show some text on the page.
    function ShowText(Text: String;
                      ForceSingleLine: Boolean = False): TControl;
    //Creates a check box on the page.
    function AddCheckBox(Caption: String; Checked: Boolean = False;
                         Event: TNotifyEvent = nil): TCheckBox;
    //Creates a button on the page.
    function AddButton(Caption: String; Event: TNotifyEvent): TButton;


    //Frees all components of the page.
    procedure FreeComponents;


    //Returns the next page to be shown.
    function GetNextPage: TWizardPage; virtual;
    //Called when the current page is no longer shown.
    procedure ChangingPage(GoingBack: Boolean); virtual;



    //Updates the state of the three buttons.
    procedure RequestButtonUpdate;
    //Changed the current page (does not work).
    procedure RequestPageChange(NewPage: TWizardPage);



    property Data: TObject read FData;
    property Form: TForm read FForm;
    property Parent: TWinControl read FParent;
    property Components: TList read FComponents;
    property PreviousPage: TWizardPage read FPreviousPage;
  public
    //Creates the page and initializes its attributes.
    constructor Create(Form: TForm; Parent: TWinControl;
                       Data: TObject; PreviousPage: TWizardPage); virtual;
    //Frees the page, all its components and following pages.
    destructor Destroy; override;



    //Returns the preceding page to show it again.
    function Back: TWizardPage;
    //Returns the next page to show.
    function Next: TWizardPage;


    //Called when the page should be shown.
    procedure ShowPage(PreviousPage: TWizardPage); virtual;
    //Called when the page should no longer be shown.
    procedure HidePage(NewPage: TWizardPage); virtual;



    //Called when the form of the wizard is about to be closed.
    procedure EventCloseQuery(var Msg: String; var ShowQuery: Boolean);
                                                                       virtual;


    property SuperPage: TWizardPage read FSuperPage write FSuperPage;

    property Caption: String read FCaption;
    property ButtonCaptions[Button: TWizardButton]: String
                                                        read GetButtonCaptions;
    property ButtonsEnabled: TWizardButtons read FButtonsEnabled;
  end;




//Shows the wizard indicated by the class of the first page.
procedure ShowWizard(Owner: TComponent; StartPageClass: TWizardPageClass;
                     Data: TObject);


implementation

{$R *.dfm}

uses USettingsKeeper;




{Shows the wizard indicated by the class of the first page.
~param Owner          the owner of the wizard
~param StartPageClass the class of the first page of the wizard to show
~param Data           custom data for the wizard }
procedure ShowWizard(Owner: TComponent; StartPageClass: TWizardPageClass;
                     Data: TObject);
var       i         :Integer;         //counter through all forms
begin
 i := Screen.FormCount - 1;           //check whether a wizard is already shown
 while (i >= 0) and not (Screen.Forms[i] is TFormWizard) do
  dec(i);
 if i >= 0 then                       //wizard is already shown?
  Screen.Forms[i].Show                  //just show it
 else
  with TFormWizard.Create(Owner) do   //create a new wizard
   begin
    Show;                               //show the form
    StartWizard(StartPageClass, Data);  //start the wizard
   end;
end;


















   { * * *  ***  * * *  ***   TWizardPage   ***  * * *  ***  * * *  }



{Creates the page and initializes its attributes.
~param Form         the form to show the page of the wizard on
~param Parent       the parent to show the components of the page on
~param Data         custom data for the wizard
~param PreviousPage the previous page of this page (to go back to) }
constructor TWizardPage.Create(Form: TForm; Parent: TWinControl;
                               Data: TObject; PreviousPage: TWizardPage);
begin
 inherited Create;                      //create the object

 FForm := Form;                         //save the parameters
 FParent := Parent;
 FData := Data;
 FPreviousPage := PreviousPage;

 FComponents := TList.Create;           //create list for components

// FCaption := '';
 FButtonCaptions[wbBack] := '&Back';    //initialize state of buttons
 FButtonCaptions[wbNext] := '&Next';
 FButtonCaptions[wbClose] := '&Close';
 FButtonsEnabled := [wbNext, wbClose];
 if assigned(PreviousPage) then
  Include(FButtonsEnabled, wbBack);
end;


{Frees the page, all its components and following pages. }
destructor TWizardPage.Destroy;
begin
 if assigned(FComponents) then
  begin
   FreeComponents;                  //free all created components
   FComponents.Free;                //free the list
  end;

 FNextPage.Free;                   //free all following pages

 inherited Destroy;                //free this page
end;





{Gets a caption of one of the three buttons.
~param Button the button, whose caption should be returned
~result the caption of the button }
function TWizardPage.GetButtonCaptions(Button: TWizardButton): String;
begin
 Result := FButtonCaptions[Button];  //just return the caption
end;






{Calculated the needed height of a text field to fit all text visible in it.
 Works under Windows only.
~param Memo  the memo to calculate the needed height of
~param Lines number of lines needed to be visible
~result needed height of the memo }
function TWizardPage.GetMemoHeight(Memo: TMemo; Lines: Integer): Integer;
{$IFNDEF LINUX}
var      OldFont    :HFont;        //current font
         DC         :THandle;      //handle on device context of the memo
         TM         :TTextMetric;  //information about the current font
         TheRect    :TRect;        //text rect of the memo
{$ENDIF}
begin
{$IFNDEF LINUX}

 DC := GetDC(Memo.Handle);         //get the device context of the memo
 try
   OldFont := SelectObject(DC, Memo.Font.Handle); //set current font
   try
     GetTextMetrics(DC, TM);       //get height of one line
     //get rectanlge of the text inside the memo
     Memo.Perform(EM_GETRECT, 0, LPARAM(@TheRect));
     //calculate needed height for the lines + height of decorations
     //(assuming decoration is equal at top and bottom)
     Result := 2 * TheRect.Top + (TM.tmHeight + TM.tmExternalLeading) * Lines;

//     Result := Memo.Height - (TheRect.Bottom - TheRect.Top) +
//               (TM.tmHeight + TM.tmExternalLeading) * Lines;
   finally
     SelectObject(DC, Oldfont);                   //restore the old font
   end;
 finally
   ReleaseDC(Memo.Handle, DC);     //release the device context
 end;

{$ELSE}

 //can't calculate needed height, so return the current height
 Result := Memo.Height;

{$ENDIF}
end;



{Creates a component of the page.
~param Control the class of the control to create
~result the created control }
function TWizardPage.CreateControl(Control: TControlClass): TControl;
begin
 Result := Control.Create(Form);     //create the control on the form
 try
   Result.Parent := Parent;          //put it on its parent (the groupbox)
   Result.Top := FNewComponentTop;   //put it on the current location
   Result.Left := 10;                //with a small margin to the left

{$IFNDEF LINUX}
   if Result is TWinControl then
{$ENDIF}
    //set help context of the page
    TWinControl(Result).HelpContext := FHelpContext;

   FComponents.Add(Result);          //add it to the list, so it gets freed
 except
   Result.Free;
   raise;
 end;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -