mirror of
				https://gitlab.com/freepascal.org/lazarus/lazarus.git
				synced 2025-11-04 03:39:48 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			559 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			559 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
{
 | 
						|
 /***************************************************************************
 | 
						|
                          synchronize - example
 | 
						|
                          ---------------------
 | 
						|
 | 
						|
                   Just a simple example to show & verify functionality
 | 
						|
                   of the lazarus TThread.Synchronize / TProgressBar classes.
 | 
						|
 | 
						|
                   Initial Revision  : Sun Aug 15 1999
 | 
						|
 | 
						|
                   by Stefan Hille <stoppok@osibisa.ms.sub.org>
 | 
						|
                   and Micha Nelissen
 | 
						|
 | 
						|
 ***************************************************************************/
 | 
						|
 | 
						|
 ***************************************************************************
 | 
						|
 *                                                                         *
 | 
						|
 *   This source is free software; you can redistribute it and/or modify   *
 | 
						|
 *   it under the terms of the GNU General Public License as published by  *
 | 
						|
 *   the Free Software Foundation; either version 2 of the License, or     *
 | 
						|
 *   (at your option) any later version.                                   *
 | 
						|
 *                                                                         *
 | 
						|
 *   This code 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.                              *
 | 
						|
 *                                                                         *
 | 
						|
 *   A copy of the GNU General Public License is available on the World    *
 | 
						|
 *   Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also      *
 | 
						|
 *   obtain it by writing to the Free Software Foundation,                 *
 | 
						|
 *   Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1335, USA.   *
 | 
						|
 *                                                                         *
 | 
						|
 ***************************************************************************
 | 
						|
}
 | 
						|
program Synchronize;
 | 
						|
 | 
						|
{$mode objfpc}{$H+}
 | 
						|
 | 
						|
{ threading directive not needed anymore for 1.9.8+ }
 | 
						|
{ $threading on}
 | 
						|
 | 
						|
uses
 | 
						|
{$ifdef UNIX}
 | 
						|
  CThreads,
 | 
						|
{$endif}
 | 
						|
  Interfaces, Classes, StdCtrls, Forms, Buttons, Menus, ComCtrls,
 | 
						|
  SysUtils, Extctrls;
 | 
						|
 | 
						|
 | 
						|
type
 | 
						|
 | 
						|
  TAThread = class(TThread)
 | 
						|
  protected
 | 
						|
    FTargetListBox: TListBox;
 | 
						|
    FTargetProgress: TProgressBar;
 | 
						|
    FTestStrings: TStrings;
 | 
						|
    procedure ExecDone;
 | 
						|
    procedure ShowStrings;
 | 
						|
  public
 | 
						|
    constructor Create(CreateSuspended: boolean);
 | 
						|
    destructor Destroy; override;
 | 
						|
  end;
 | 
						|
 | 
						|
  TThread1 = class(TAThread)
 | 
						|
  public
 | 
						|
    constructor Create;
 | 
						|
    procedure Execute; override;
 | 
						|
  end;
 | 
						|
 | 
						|
  TThread2 = class(TAThread)
 | 
						|
  public
 | 
						|
    constructor Create;
 | 
						|
    procedure Execute; override;
 | 
						|
  end;
 | 
						|
 | 
						|
  TForm1 = class(TForm)
 | 
						|
  public
 | 
						|
    Progre1: TProgressBar;
 | 
						|
    Progre2: TProgressBar;
 | 
						|
    Progre3: TProgressBar;
 | 
						|
    Listbox1: TListBox;
 | 
						|
    Listbox2: TListBox;
 | 
						|
    Thread1: TThread1;
 | 
						|
    Thread2: TThread2;
 | 
						|
    ThreadList: TList;
 | 
						|
    Button1: TButton;
 | 
						|
    Button2: TButton;
 | 
						|
    Button3: TButton;
 | 
						|
    Button4: TButton;
 | 
						|
    Button5: TButton;
 | 
						|
    Button6: TButton;
 | 
						|
    Button7: TButton;
 | 
						|
    Button8: TButton;
 | 
						|
    Button9: TButton;
 | 
						|
    Button10: TButton;
 | 
						|
    mnuFile: TMainMenu;
 | 
						|
    itmFileQuit: TMenuItem;
 | 
						|
    constructor Create(AOwner: TComponent); override;
 | 
						|
    destructor Destroy; override;
 | 
						|
    procedure LoadMainMenu;
 | 
						|
    procedure mnuQuitClicked(Sender : TObject);
 | 
						|
  protected
 | 
						|
    procedure Button1CLick(Sender : TObject);
 | 
						|
    procedure Button2CLick(Sender : TObject);
 | 
						|
    procedure Button3CLick(Sender : TObject);
 | 
						|
    procedure Button4CLick(Sender : TObject);
 | 
						|
    procedure Button5CLick(Sender : TObject);
 | 
						|
    procedure Button6CLick(Sender : TObject);
 | 
						|
    procedure Button7CLick(Sender : TObject);
 | 
						|
    procedure Button8CLick(Sender : TObject);
 | 
						|
    procedure Button9CLick(Sender : TObject);
 | 
						|
    procedure Button10CLick(Sender : TObject);
 | 
						|
    function CloseQuery: boolean; override;
 | 
						|
  end;
 | 
						|
 | 
						|
threadvar
 | 
						|
  threadvartest: integer;
 | 
						|
 | 
						|
var
 | 
						|
  Form1 : TForm1;
 | 
						|
  TotalCount: integer;
 | 
						|
  { GlobalData is an example of what you should NOT do :)
 | 
						|
    Access from multiple threads to same variable unprotected }
 | 
						|
  GlobalData: integer;
 | 
						|
 | 
						|
constructor TAThread.Create(CreateSuspended: boolean);
 | 
						|
begin
 | 
						|
  inherited;
 | 
						|
 | 
						|
  FTestStrings := TStringList.Create;
 | 
						|
end;
 | 
						|
 | 
						|
destructor TAThread.Destroy;
 | 
						|
begin
 | 
						|
  inherited;
 | 
						|
 | 
						|
  FTestStrings.Free;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TAThread.ExecDone;
 | 
						|
var
 | 
						|
  lPos: integer;
 | 
						|
begin
 | 
						|
  Form1.ThreadList.Remove(Self);
 | 
						|
  FTargetListBox.Items.Insert(0, 'Thread terminated');
 | 
						|
  if Form1.ThreadList.Count = 0 then
 | 
						|
  begin
 | 
						|
    lPos := Pos('[', Form1.Caption);
 | 
						|
    if lPos > 0 then
 | 
						|
      Form1.Caption := Copy(Form1.Caption, 1, lPos - 1) + '[done, ready to exit]';
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TAThread.ShowStrings;
 | 
						|
var
 | 
						|
  i: integer;
 | 
						|
begin
 | 
						|
  FTargetListBox.Items.BeginUpdate;
 | 
						|
  for i := 0 to FTestStrings.Count - 1 do
 | 
						|
  begin
 | 
						|
    FTargetListBox.Items.Insert(0, FTestStrings.Strings[i]);
 | 
						|
    while FTargetListBox.Items.Count > 30 do
 | 
						|
      FTargetListBox.Items.Delete(FTargetListBox.Items.Count-1);
 | 
						|
  end;
 | 
						|
  FTargetListBox.Items.EndUpdate;
 | 
						|
  FTestStrings.Clear;
 | 
						|
  if FTargetProgress.Position = FTargetProgress.Max then
 | 
						|
    FTargetProgress.Position := FTargetProgress.Min;
 | 
						|
  FTargetProgress.StepIt;
 | 
						|
end;
 | 
						|
 | 
						|
constructor TThread1.Create;
 | 
						|
begin
 | 
						|
  FTargetListBox := Form1.Listbox1;
 | 
						|
  FTargetProgress := Form1.Progre1;
 | 
						|
  FreeOnTerminate := true;
 | 
						|
  inherited Create(false);
 | 
						|
end;
 | 
						|
 | 
						|
function DoCalculation: integer;
 | 
						|
var
 | 
						|
  i, k: integer;
 | 
						|
  j: array[0..511] of integer;
 | 
						|
begin
 | 
						|
  for i := 0 to 100000 do
 | 
						|
  begin
 | 
						|
    j[i mod $1ff] := i * i;
 | 
						|
    k := j[(i + 3) and $1ff] div (i+1);
 | 
						|
    j[(i + 5) and $1ff] := k - 3;
 | 
						|
  end;
 | 
						|
  result := j[5];
 | 
						|
end;
 | 
						|
 | 
						|
procedure TThread1.Execute;
 | 
						|
var
 | 
						|
  i: integer;
 | 
						|
begin
 | 
						|
  threadvartest := 10;
 | 
						|
  FTestStrings.Add('Threadvar is @'+IntToStr(ptrint(@threadvartest)));
 | 
						|
  for i := 0 to TotalCount - 1 do
 | 
						|
  begin
 | 
						|
    GlobalData += 3;
 | 
						|
    DoCalculation;
 | 
						|
    FTestStrings.Add('Information: '+IntToStr(GlobalData-3)+' '+IntToStr(threadvartest));
 | 
						|
    GlobalData -= 3;
 | 
						|
    DoCalculation;
 | 
						|
    Synchronize(@ShowStrings);
 | 
						|
    threadvartest := 10;
 | 
						|
    if Terminated then break;
 | 
						|
  end;
 | 
						|
  Synchronize(@ExecDone);
 | 
						|
end;
 | 
						|
 | 
						|
constructor TThread2.Create;
 | 
						|
begin
 | 
						|
  FTargetListBox := Form1.Listbox2;
 | 
						|
  FTargetProgress := Form1.Progre2;
 | 
						|
  FreeOnTerminate := true;
 | 
						|
  inherited Create(false);
 | 
						|
end;
 | 
						|
 | 
						|
procedure TThread2.Execute;
 | 
						|
var
 | 
						|
  i: integer;
 | 
						|
begin
 | 
						|
  threadvartest := 15;
 | 
						|
  FTestStrings.Add('Threadvar is @'+IntToStr(ptrint(@threadvartest)));
 | 
						|
  for i := 0 to TotalCount - 1 do
 | 
						|
  begin
 | 
						|
    GlobalData -= 3;
 | 
						|
    DoCalculation;
 | 
						|
    FTestStrings.Add('Information: '+IntToStr(GlobalData+3)+' '+IntToStr(threadvartest));
 | 
						|
    threadvartest := 15;
 | 
						|
    GlobalData += 3;
 | 
						|
    DoCalculation;
 | 
						|
    if (i and $3) = $3 then
 | 
						|
      Synchronize(@ShowStrings);
 | 
						|
    if Terminated then break;
 | 
						|
  end;
 | 
						|
  Synchronize(@ExecDone);
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
constructor TForm1.Create(AOwner: TComponent);
 | 
						|
begin
 | 
						|
   inherited CreateNew(AOwner, 1);
 | 
						|
   Caption := 'Thread Synchronize Demo v0.1';
 | 
						|
   ThreadList := TList.Create;
 | 
						|
   LoadMainMenu;
 | 
						|
end;
 | 
						|
 | 
						|
destructor TForm1.Destroy;
 | 
						|
begin
 | 
						|
  inherited;
 | 
						|
 | 
						|
  FreeAndNil(ThreadList);
 | 
						|
end;
 | 
						|
 | 
						|
function TForm1.CloseQuery: boolean;
 | 
						|
var
 | 
						|
  I: integer;
 | 
						|
begin
 | 
						|
  if ThreadList.Count > 0 then
 | 
						|
  begin
 | 
						|
    Caption := Caption + ' [wait for threads termination]';
 | 
						|
    for I := 0 to ThreadList.Count - 1 do
 | 
						|
      TThread(ThreadList.Items[I]).Terminate;
 | 
						|
    Result := false;
 | 
						|
  end else
 | 
						|
    inherited;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TForm1.Button1Click(Sender : TObject);
 | 
						|
Begin
 | 
						|
   if assigned (progre3) then begin
 | 
						|
        progre3.Position := 0;
 | 
						|
        progre3.Min := progre3.Min - 1
 | 
						|
   end;
 | 
						|
End;
 | 
						|
 | 
						|
procedure TForm1.Button2Click(Sender : TObject);
 | 
						|
Begin
 | 
						|
   if assigned (progre3) then begin
 | 
						|
        progre3.Position := 0;
 | 
						|
        progre3.Min := progre3.Min + 1;
 | 
						|
   end;
 | 
						|
End;
 | 
						|
 | 
						|
procedure TForm1.Button3Click(Sender : TObject);
 | 
						|
Begin
 | 
						|
   if assigned (progre3) then begin
 | 
						|
        progre3.Position := 0;
 | 
						|
        progre3.Max := progre3.Max +1;
 | 
						|
   end;
 | 
						|
End;
 | 
						|
 | 
						|
procedure TForm1.Button4Click(Sender : TObject);
 | 
						|
Begin
 | 
						|
   if assigned (progre3) then begin
 | 
						|
        progre3.Position := 0;
 | 
						|
        progre3.Max := progre3.Max -1;
 | 
						|
   end;
 | 
						|
End;
 | 
						|
 | 
						|
procedure TForm1.Button10Click(Sender : TObject);
 | 
						|
Begin
 | 
						|
  if assigned (progre3) then begin
 | 
						|
    if progre3.position >= progre3.max then
 | 
						|
      progre3.position := progre3.min;
 | 
						|
    progre3.stepit;
 | 
						|
  end;
 | 
						|
End;
 | 
						|
 | 
						|
procedure TForm1.Button5Click(Sender : TObject);
 | 
						|
Begin
 | 
						|
   if assigned (progre1) then begin
 | 
						|
        Progre1.Smooth := not Progre1.Smooth;
 | 
						|
        if assigned (Button6)
 | 
						|
          then Button6.Visible := Progre1.Smooth;
 | 
						|
   end;
 | 
						|
End;
 | 
						|
 | 
						|
procedure TForm1.Button6Click(Sender : TObject);
 | 
						|
Begin
 | 
						|
   if assigned (progre1) then begin
 | 
						|
        Progre1.BarShowtext := not Progre1.BarShowtext;
 | 
						|
   end;
 | 
						|
End;
 | 
						|
 | 
						|
procedure TForm1.Button7Click(Sender : TObject);
 | 
						|
Begin
 | 
						|
   if assigned (progre1) then
 | 
						|
   begin
 | 
						|
     case Progre1.Orientation of
 | 
						|
        pbVertical      : Progre1.Orientation := pbRightToLeft;
 | 
						|
        pbRightToLeft   : Progre1.Orientation := pbTopDown;
 | 
						|
        pbTopDown       : Progre1.Orientation := pbHorizontal;
 | 
						|
        pbHorizontal    : Progre1.Orientation := pbVertical;
 | 
						|
     end;
 | 
						|
   end;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TForm1.Button8Click(Sender : TObject);
 | 
						|
begin
 | 
						|
        { Create the threads }
 | 
						|
        TotalCount := 1000;
 | 
						|
        GlobalData := 100;
 | 
						|
        threadvartest := 20;
 | 
						|
        Thread1 := TThread1.Create;
 | 
						|
        Thread2 := TThread2.Create;
 | 
						|
        ThreadList.Add(Thread1);
 | 
						|
        ThreadList.Add(Thread2);
 | 
						|
 | 
						|
End;
 | 
						|
 | 
						|
procedure TForm1.Button9Click(Sender : TObject);
 | 
						|
begin
 | 
						|
  Listbox1.Items.Clear;
 | 
						|
  Listbox2.Items.Clear;
 | 
						|
end;
 | 
						|
 | 
						|
{------------------------------------------------------------------------------}
 | 
						|
procedure TForm1.LoadMainMenu;
 | 
						|
 | 
						|
begin
 | 
						|
        { set the height and width }
 | 
						|
        Height := 350;
 | 
						|
        Width := 700;
 | 
						|
 | 
						|
        { Create a progressbar }
 | 
						|
        Progre1 := TProgressBar.Create (Self);
 | 
						|
        with Progre1 do
 | 
						|
        begin
 | 
						|
          Parent := Self;
 | 
						|
          SetBounds(300, 10, 250, 20);
 | 
						|
          Min := 0;
 | 
						|
          Max := 10;
 | 
						|
          Step := 1;
 | 
						|
          BarShowText := true;
 | 
						|
          Smooth := True;
 | 
						|
          Show;
 | 
						|
        end;
 | 
						|
 | 
						|
        Progre2 := TProgressBar.Create (Self);
 | 
						|
        with Progre2 do
 | 
						|
        begin
 | 
						|
          Parent := Self;
 | 
						|
          SetBounds(300, 35, 250, 20);
 | 
						|
          Min := 0;
 | 
						|
          Max := 10;
 | 
						|
          Step := 1;
 | 
						|
          BarShowText := true;
 | 
						|
          Smooth := True;
 | 
						|
          Show;
 | 
						|
        end;
 | 
						|
 | 
						|
        Progre3 := TProgressBar.Create (Self);
 | 
						|
        with Progre3 do
 | 
						|
        begin
 | 
						|
          Parent := Self;
 | 
						|
          SetBounds(300, 60, 250, 20);
 | 
						|
          Min := 0;
 | 
						|
          Max := 10;
 | 
						|
          Step := 1;
 | 
						|
          BarShowText := true;
 | 
						|
          Smooth := True;
 | 
						|
          Show;
 | 
						|
        end;
 | 
						|
 | 
						|
        { create listboxes to show thread results }
 | 
						|
        Listbox1 := TListBox.Create(self);
 | 
						|
        with Listbox1 do
 | 
						|
        begin
 | 
						|
          Parent := self;
 | 
						|
          SetBounds(10, 120, 200, 180);
 | 
						|
        end;
 | 
						|
 | 
						|
        Listbox2 := TListBox.Create(self);
 | 
						|
        with Listbox2 do
 | 
						|
        begin
 | 
						|
          Parent := self;
 | 
						|
          SetBounds(250, 120, 200, 180);
 | 
						|
        end;
 | 
						|
 | 
						|
 | 
						|
        { Create a few buttons }
 | 
						|
        Button2 := TButton.Create(Self);
 | 
						|
        Button2.Parent := Self;
 | 
						|
        Button2.Left := 200;
 | 
						|
        Button2.Top := 70;
 | 
						|
        Button2.Width := 80;
 | 
						|
        Button2.Height := 30;
 | 
						|
        Button2.Show;
 | 
						|
        Button2.Caption := 'PMin ++';
 | 
						|
//      Button2.ToolTip := 'Tool Tip';
 | 
						|
//      Button2.ShowToolTip := True;
 | 
						|
        Button2.OnClick := @Button2Click;
 | 
						|
 | 
						|
 | 
						|
        Button1 := TButton.Create(Self);
 | 
						|
        Button1.Parent := Self;
 | 
						|
        Button1.Left := 50;
 | 
						|
        Button1.Top := 70;
 | 
						|
        Button1.Width := 80;
 | 
						|
        Button1.Height := 30;
 | 
						|
        Button1.Show;
 | 
						|
        Button1.Caption := 'PMin--';
 | 
						|
        Button1.OnClick := @Button1Click;
 | 
						|
 | 
						|
        { Create 2 more buttons outside the groupbox }
 | 
						|
        Button3 := TButton.Create(Self);
 | 
						|
        Button3.Parent := Self;
 | 
						|
        Button3.Left := 50;
 | 
						|
        Button3.Top := 30;
 | 
						|
        Button3.Width := 80;
 | 
						|
        Button3.Height := 30;
 | 
						|
        Button3.Show;
 | 
						|
        Button3.Caption := 'PMax++';
 | 
						|
//      Button3.ToolTip := 'Tool Tip';
 | 
						|
//      Button3.ShowToolTip := True;
 | 
						|
        Button3.OnClick := @Button3Click;
 | 
						|
 | 
						|
        Button4 := TButton.Create(Self);
 | 
						|
        Button4.Parent := Self;
 | 
						|
        Button4.Left := 200;
 | 
						|
        Button4.Top := 30;
 | 
						|
        Button4.Width := 80;
 | 
						|
        Button4.Height := 30;
 | 
						|
        Button4.Show;
 | 
						|
        Button4.Caption := 'PMax--';
 | 
						|
        Button4.OnClick := @Button4Click;
 | 
						|
 | 
						|
        Button10 := TButton.Create(Self);
 | 
						|
        with Button10 do
 | 
						|
        begin
 | 
						|
          Parent := Self;
 | 
						|
          SetBounds(140, 30, 50, 30);
 | 
						|
          Show;
 | 
						|
          Caption := 'Step It';
 | 
						|
          OnClick := @Button10Click;
 | 
						|
        end;
 | 
						|
 | 
						|
        Button5 := TButton.Create(Self);
 | 
						|
        Button5.Parent := Self;
 | 
						|
        Button5.Left := 500;
 | 
						|
        Button5.Top := 110;
 | 
						|
        Button5.Width := 130;
 | 
						|
        Button5.Height := 30;
 | 
						|
        Button5.Show;
 | 
						|
        Button5.Caption := 'Toggle Smooth';
 | 
						|
        Button5.OnClick := @Button5Click;
 | 
						|
 | 
						|
        Button6 := TButton.Create(Self);
 | 
						|
        Button6.Parent := Self;
 | 
						|
        Button6.Left := 500;
 | 
						|
        Button6.Top := 150;
 | 
						|
        Button6.Width := 130;
 | 
						|
        Button6.Height := 30;
 | 
						|
        Button6.Show;
 | 
						|
        Button6.Caption := 'Toggle Text';
 | 
						|
        Button6.OnClick := @Button6Click;
 | 
						|
        Button6.Visible := Progre1.Smooth;
 | 
						|
 | 
						|
        Button7 := TButton.Create(Self);
 | 
						|
        Button7.Parent := Self;
 | 
						|
        Button7.Left := 500;
 | 
						|
        Button7.Top := 190;
 | 
						|
        Button7.Width := 130;
 | 
						|
        Button7.Height := 30;
 | 
						|
        Button7.Show;
 | 
						|
        Button7.Caption := 'Orientation';
 | 
						|
        Button7.OnClick := @Button7Click;
 | 
						|
 | 
						|
        Button8 := TButton.Create(Self);
 | 
						|
        with Button8 do
 | 
						|
        begin
 | 
						|
          Parent := Self;
 | 
						|
          SetBounds(500, 230, 130, 30);
 | 
						|
          Show;
 | 
						|
          Caption := 'Thread test';
 | 
						|
          OnClick := @Button8Click;
 | 
						|
        end;
 | 
						|
 | 
						|
        Button9 := TButton.Create(Self);
 | 
						|
        with Button9 do
 | 
						|
        begin
 | 
						|
          Parent := Self;
 | 
						|
          SetBounds(500, 270, 130, 30);
 | 
						|
          Show;
 | 
						|
          Caption := 'Clear listboxes';
 | 
						|
          OnClick := @Button9Click;
 | 
						|
        end;
 | 
						|
 | 
						|
        { create a menubar }
 | 
						|
        mnuFile := TMainMenu.Create(Self);
 | 
						|
        mnuFile.Name:='mnuFile';
 | 
						|
        Menu := mnuFile;
 | 
						|
 | 
						|
        itmFileQuit := TMenuItem.Create(Self);
 | 
						|
        itmFileQuit.Caption := 'Quit';
 | 
						|
        itmFileQuit.OnClick := @mnuQuitClicked;
 | 
						|
        mnuFile.Items.Add(itmFileQuit);
 | 
						|
 | 
						|
end;
 | 
						|
 | 
						|
{------------------------------------------------------------------------------}
 | 
						|
procedure TForm1.mnuQuitClicked(Sender : TObject);
 | 
						|
begin
 | 
						|
  Close;
 | 
						|
end;
 | 
						|
{------------------------------------------------------------------------------}
 | 
						|
 | 
						|
begin
 | 
						|
   Application.Initialize; { calls InitProcedure which starts up GTK }
 | 
						|
   Application.CreateForm(TForm1, Form1);
 | 
						|
   Application.Run;
 | 
						|
end.
 | 
						|
 |