📄 uwizard.pas
字号:
end;
{Creates a text field on the page.
~param Text the text to show in the text field
~result the new text field }
function TWizardPage.AddEditField(Text: String): TEdit;
begin
Result := TEdit(CreateControl(TEdit)); //create the text field
Result.Width := Parent.Width - 20; //make it span the whole width
Result.Anchors := [akLeft,akTop,akRight]; //and keep it that way
Result.Text := Text; //set the text
inc(FNewComponentTop, Result.Height + 10); //create next component below it
end;
{Creates a text field to show some text on the page.
~param Text the text to show
~param ForceSingleLine if the text should be forced to be shown in a
single-line edit field
~result the new control showing the text, either TEdit or TMemo }
function TWizardPage.ShowText(Text: String;
ForceSingleLine: Boolean = False): TControl;
begin
//should be shown in a single-line edit field or the text is small and fits
if ForceSingleLine or ((Length(Text) < 100) and //on one line?
(Pos(#13, Text) = 0) and (Pos(#10, Text) = 0)) then
begin
Result := CreateControl(TEdit); //create the control
{$IFDEF LINUX}
// TEdit(Result).BorderStyle := bsSingle; //bsNone ???
{$ELSE}
TEdit(Result).Ctl3D := False; //don't decorate that much
{$ENDIF}
TEdit(Result).ParentColor := True; //mark as read-only
TEdit(Result).ReadOnly := True;
end
else
begin
Result := CreateControl(TMemo); //create multi-line edit field
{$IFDEF LINUX}
TMemo(Result).BorderStyle := bsSingle; //don't decorate that much
{$ELSE}
TMemo(Result).Ctl3D := False;
{$ENDIF}
TMemo(Result).ParentColor := True; //mark as read-only
TMemo(Result).ReadOnly := True;
end;
Result.Width := Parent.Width - 20; //let it span the whole width
Result.Anchors := [akLeft,akTop,akRight]; //and keep it that way
{$IFDEF LINUX}
if Result is TEdit then //show the text
TEdit(Result).Text := Text
else
{$ENDIF}
TMemo(Result).Text := Text;
if Result is TMemo then //is a memo
begin
//needs only one single line?
if TMemo(Result).Lines.Count <= 1 then //is this portable?
begin
try
FComponents.Remove(Result); //don't free it twice
finally
Result.Free; //free it again
end;
Result := ShowText(Text, True); //show as a single-line edit field
//don't increment twice due to the recursive call
dec(FNewComponentTop, Result.Height + 10);
end //if TMemo(Result).Lines.Count <= 1
else
begin
//show scroll bar to keep the whole text visible
TMemo(Result).ScrollBars := ssVertical;
//set height of the memo to show the text exactly
TMemo(Result).Height := GetMemoHeight(TMemo(Result),
TMemo(Result).Lines.Count);
end; //else TMemo(Result).Lines.Count <= 1
end; //if Result is TMemo
//create the next component below this one
inc(FNewComponentTop, Result.Height + 10);
end;
{Creates a check box on the page.
~param Caption the caption of the check box
~param Checked if the check box is initially checked
~param Event method to call, when the state of the check box changed
~result the created check box }
function TWizardPage.AddCheckBox(Caption: String; Checked: Boolean = False;
Event: TNotifyEvent = nil): TCheckBox;
begin
Result := TCheckBox(CreateControl(TCheckBox)); //create the check box
Result.Width := Parent.Width - 20; //span the whole with
Result.Anchors := [akLeft,akTop,akRight]; //and keep it that way
Result.Caption := Caption; //set its caption
Result.Checked := Checked; //set its state
Result.OnClick := Event; //set the handler
//create the next component below this one
inc(FNewComponentTop, Result.Height + 10);
end;
{Creates a button on the page.
~param Caption the caption of the button
~param Event method to call, when the button is clicked
~result the created button }
function TWizardPage.AddButton(Caption: String; Event: TNotifyEvent): TButton;
begin
Result := TButton(CreateControl(TButton)); //create the check box
Result.Width := 150;
Result.Caption := Caption; //set its caption
Result.OnClick := Event; //set the handler
//create the next component below this one
inc(FNewComponentTop, Result.Height + 10);
end;
{Frees all components of the page. }
procedure TWizardPage.FreeComponents;
var i :Integer; //counter through all components
begin
for i := 0 to FComponents.Count - 1 do //for each component
TObject(FComponents[i]).Free; //free it
FComponents.Clear; //clear the list
end;
{Returns the next page to be shown.
~result the next page to be shown }
function TWizardPage.GetNextPage: TWizardPage;
begin
Result := nil; //this base page has no other pages
end;
{Called when the current page is no longer shown.
~param GoingBack if the preceding page will be shown }
procedure TWizardPage.ChangingPage(GoingBack: Boolean);
begin
end;
{Updates the state of the three buttons. }
procedure TWizardPage.RequestButtonUpdate;
begin
TFormWizard(Form).UpdateButtons; //let the form update the buttons
end;
{Changed the current page. This does not work, because all components will be
freed, including the one whose event initiated the change. This will cause
memory access violatations (if you're lucky) when the event if futher
processed after the change of the page. So always use the "Next" button to
show the next page.
~param NewPage the new page that should be shown }
procedure TWizardPage.RequestPageChange(NewPage: TWizardPage);
begin
//let the form show the new page
TFormWizard(Form).ChangeCurrentWizardPage(NewPage);
end;
{Returns the preceding page to show it again.
~result the preceding page to show it or nil }
function TWizardPage.Back: TWizardPage;
begin
Result := FPreviousPage; //return the preceding page
if assigned(Result) then //has a preceding page?
ChangingPage(True); //trigger event
end;
{Returns the next page to show.
~result the next page to show or nil }
function TWizardPage.Next: TWizardPage;
begin
if not assigned(FNextPage) then //next page not already created?
FNextPage := GetNextPage; //create it
Result := FNextPage; //use the next page
if not assigned(Result) then //no next page?
Result := FSuperPage; //if it is a sub-thread, return its parent page
if assigned(Result) then //new page will be shown?
ChangingPage(False); //trigger event
end;
{Called when the page should be shown.
~param PreviousPage the previously shown page or nil }
procedure TWizardPage.ShowPage(PreviousPage: TWizardPage);
begin
FNewComponentTop := 20; //create components with a vertical margin
end;
{Called when the page should no longer be shown. Will not be called when the
wizard is ended (i.e. the form is closed), use ~[link EventCloseQuery]
instead.
~param NewPage the page that will be shown instead }
procedure TWizardPage.HidePage(NewPage: TWizardPage);
begin
FreeComponents; //remove all created components
end;
{Called when the form of the wizard is about to be closed.
~param Msg the message to show to inquire a confirmation if the wizard
should really be ended
~param ShowQuery if the query to confirm the ending of the wizard should be
shown }
procedure TWizardPage.EventCloseQuery(var Msg: String; var ShowQuery: Boolean);
begin
ShowQuery := False; //by default no query
end;
{ * * * *** * * * *** TFormWizard *** * * * *** * * * }
{Called to show a new page of the wizard.
~param NewPage the page to show and make the current }
procedure TFormWizard.InitWizardPage(NewPage: TWizardPage);
var OldPage :TWizardPage; //the previously shown page
begin
OldPage := FCurrentPage; //save the current page
FCurrentPage := NewPage; //set the new page
NewPage.ShowPage(OldPage); //show the new page
GroupBox.Caption := NewPage.Caption; //show its caption
UpdateButtons; //and update the states of the buttons
end;
{Called to hide a page of the wizard and show a new one.
~param NewPage the new page to show instead }
procedure TFormWizard.DeInitWizardPage(NewPage: TWizardPage);
begin
assert(assigned(FCurrentPage));
FCurrentPage.HidePage(NewPage); //hide the current page
end;
{Can be called to update the state of the three buttons according to the
current page of the wizard. }
procedure TFormWizard.UpdateButtons;
begin
//update the caption of all buttons and enable or disable them
BitBtnBack.Caption := FCurrentPage.ButtonCaptions[wbBack];
BitBtnBack.Enabled := wbBack in FCurrentPage.ButtonsEnabled;
BitBtnNext.Caption := FCurrentPage.ButtonCaptions[wbNext];
BitBtnNext.Enabled := wbNext in FCurrentPage.ButtonsEnabled;
BitBtnClose.Caption := FCurrentPage.ButtonCaptions[wbClose];
BitBtnClose.Enabled := wbClose in FCurrentPage.ButtonsEnabled;
end;
{Can be called to change the current page of the wizard.
~param NewPage the new page to show }
procedure TFormWizard.ChangeCurrentWizardPage(NewPage: TWizardPage);
begin
DeInitWizardPage(NewPage); //hide the old page
InitWizardPage(NewPage); //show the new page
end;
{Starts the wizard with the given page.
~param StartPageClass the class of the first page of the wizard to show
~param Data custom data for the wizard }
procedure TFormWizard.StartWizard(StartPageClass: TWizardPageClass;
Data: TObject);
begin
assert(not assigned(FFirstPage));
assert(not assigned(FCurrentPage));
//create the first page
FFirstPage := StartPageClass.Create(Self, GroupBox, Data, nil);
InitWizardPage(FFirstPage); //and show it
end;
{Called when the button to go to the preceding page is clicked.
~param Sender the sender of the event, ~[link BitBtnBack] }
procedure TFormWizard.BitBtnBackClick(Sender: TObject);
var Page :TWizardPage; //the preceding page to show
begin
Page := FCurrentPage.Back; //get the preceding page
if assigned(Page) then //preceding page available?
begin
DeInitWizardPage(Page); //hide the current page
InitWizardPage(Page); //show the preceding page
end;
end;
{Called when the button to end the current page and go to the next page is
clicked.
~param Sender the sender of the event, ~[link BitBtnNext] }
procedure TFormWizard.BitBtnNextClick(Sender: TObject);
var Page :TWizardPage; //the next page to show
begin
Page := FCurrentPage.Next; //get the next page
if assigned(Page) then //page available?
begin
DeInitWizardPage(Page); //hide the current page
InitWizardPage(Page); //show the next page
end;
end;
{Called when the button to end the wizard and close the form is clicked.
~param Sender the sender of the event, ~[link BitBtnClose] }
procedure TFormWizard.BitBtnCloseClick(Sender: TObject);
begin
Close; //close the form
end;
{Called when the form created.
~param Sender the sender of the event, ~[link Self] }
procedure TFormWizard.FormCreate(Sender: TObject);
begin
TFormSettings.SaveBasicFormValues(Self); //read the basic form values
end;
{Called when the window is about of being closed.
~param Sender the sender of the event, ~[link Self]
~param CanClose if the window should be closed }
procedure TFormWizard.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
var Msg :String; //the message to inquire confirmation
begin
CanClose := True; //assume it can be closed
if assigned(FCurrentPage) then //a wizard is shown?
begin
Msg := 'Are you sure you want to close this wizard?'; //initialize message
FCurrentPage.EventCloseQuery(Msg, CanClose); //query the page
//if the page requested it, inquire confirmation and close only if confirmed
CanClose := not CanClose or
(MessageDlg(Msg, mtConfirmation, [mbNo, mbYes], HelpContext) =
mrYes);
end;
end;
{Called when the form is closed.
~param Sender the sender of the event, the form
~param Action action to do on this event }
procedure TFormWizard.FormClose(Sender: TObject; var Action: TCloseAction);
var Settings :TFormSettings; //to save the settings of the form
begin
DeInitWizardPage(nil); //hide the current wizard page
Action := caFree; //free the form
//get object to save the settings in
Settings := TFormSettings(TFormSettings.GetSettings(ClassName));
if assigned(Settings) then
Settings.GetValuesFromForm(Self); //save current settings
end;
{Called when the form is being deleted.
~param Sender the sender of the event, the form }
procedure TFormWizard.FormDestroy(Sender: TObject);
begin
FFirstPage.Free; //free the wizard (with all pages)
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -