Delphi Programming / Object Pascal
[掲載 2014年11月20日] [更新 2014年12月09日] Delphi サンプルプログラム集 |
054_TStringGrid のインプレイスボタンとその機能 |
動作確認等 |
Windows 7 U64(SP1) + Delphi XE(UP1) Pro |
|
054_TStringGrid_Button.zip [1,854 KB] 2014年12月09日版 (EXE 同梱) |
- 2014年12月09日
- 必要なファイルをプロジェクトに追加するのはトラブル発生の要因のようなので,全てライブラリパスに置いて使用しする方法に変更
- コメント類の間違い等の修正
- コンポーネントは別のページを作成して移動
|
セル編集時のボタン表示とドロップダウンリストとダイアログの表示 |
TStringGird や TDBGrid でセルの編集を開始すると,インプレイスエディタが起動します.
このインプレイスエディタのクラス名は TInplaceEdit です.その継承クラスに TInplaceEditList があります.この TInplaceEditList には,セルの編集時にボタンを表示し,そのボタンをクリックした時の動作を実装できる機能があります.
本ページは,この機能を使用したサンプルです.
指定可能なボタンは TEditStyle 型で 3 種類あります.1 つは,ボタンを表示しない指定です.これは,通常のセルの編集と同じです.1 つは,下向きの矢印画像のボタンで,ドロップダウンのリストを表示するために使用します.もう 1 つは,参照用のボタンで,省略記号 [...] のボタンです.
本ページのサンプルでは,TStringGrid の派生クラスを作成して,それを利用します.テストの度にコンポーネントとしてインストール (登録) していては面倒です.そこで,[派生元のコンポーネントと交換する方法] の記事のユニットを使用して,実行時に,フォームに配置した TStringGrid と入れ換えてテストしています.
このユニットは,サンプルプログラムのルートフォルダにあります.添付のプロジェクトを利用するには,このユニットを,ライブラリパスの通ったフォルダに置いてください.
|
下図は,本ページのテストで使用したプロジェクトのフォームの設計時画面です.
TStringGrid をフォームに配置しています.プロパティ等はデフォルトのままにして,実行時に設定しています.
|
|
図1
テストプログラムの設計時画面 |
[備考 1]
ドロップダウンのリストですが,ネット上の記事では,コンボボックスと書いてあることがありすが,動作仕様は TListBox です.
|
[備考 2]
ドロップダウンで表示されるウィンドウのクラス名は
TPopupListbox です.内部では PickList という名前が使われています.したがって,ドロップダウンリストというより,ピックアップリストと呼んだ方がいいのかも知れません.
|
セルが編集状態になったら,インプレイスなボタンを表示して,そのボタンをクリックした時の動作を設定するサンプルです.
この機能を実現するには,TStringGrid の CreateEditor, GetEditStyle をオーバライド (override) して使用します.クラス内のメソッドをオーバライドする時は,[メッセージ処理メソッドの作成] の記事にある操作で作成すると便利で確実です. |
|
図2
セルの編集開始
- [F2] で編集状態になる
- 編集状態になるとボタンが現れる
|
|
図3
ドロップダウンリストを表示
- [Alt] + [↓] で表示できる
- コントロールの実体は TListBox
|
|
図4
省略記号のボタン
- セルが編集開始になると現れる
- マウスボタンのクリックでダイアログを表示
- セルの左下から表示するようにしている
|
リスト1
セルの編集開始でボタンを表示して,ドロップダウンのリストを表示したりダイアログを表示 |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, Grids, StdCtrls;
type
//---------------------------------------------------------------------------
// TStringGridのセル編集時に[↓][...]ボタンを表示するには,
// 以下のメソッドをoverride実装したTStringGirdを作成する
// CreateEditor
// GetEditStyle
//
// EditListGetItemsEvent
// EditButtonClickEvent
// は,CreateEditorメソッド内で定義するボタンクリック関係のイベント用
// 関数名は任意,引数の順番と型は決まっている
//---------------------------------------------------------------------------
TplStringGrid = class(TStringGrid)
private
procedure EditListGetItemsEvent(ACol, ARow: Integer; Items: TStrings);
procedure EditButtonClickEvent(Sender: TObject);
protected
function CreateEditor: TInplaceEdit; override;
function GetEditStyle(ACol: Integer; ARow: Integer): TEditStyle; override;
end;
TForm1 = class(TForm)
Panel1: TPanel;
StringGrid1: TStringGrid;
procedure FormCreate(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
uses plChgCompo;
{$R *.dfm}
//=============================================================================
// テスト用に列数と列幅等を設定し,テスト用のデータを各セルにセット
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
//フォーム作成時にコンポーネントの置換え
StringGrid1 := TStringGrid(ChangeComponent(StringGrid1, TplStringGrid));
StringGrid1.DefaultDrawing := True;
//編集可能にしないとインプレイスエディタは起動しない
StringGrid1.Options := StringGrid1.Options + [goEditing];
StringGrid1.FixedCols := 1;
StringGrid1.FixedRows := 1;
StringGrid1.ColCount := 4;
StringGrid1.RowCount := 4;
StringGrid1.DefaultColWidth := 80;
//左端の列幅設定
StringGrid1.ColWidths[0] := 10;
//テスト用の値をセット(固定行)
StringGrid1.Cells[1,0] := '都道府県';
StringGrid1.Cells[2,0] := '調査番号';
StringGrid1.Cells[3,0] := '結果値';
//テスト用の値をセット
StringGrid1.Cells[2,1] := 'A-100';
StringGrid1.Cells[2,2] := 'A-200';
StringGrid1.Cells[2,3] := 'A-300';
StringGrid1.Cells[3,1] := '500';
StringGrid1.Cells[3,2] := '800';
StringGrid1.Cells[3,3] := '300';
end;
{ TplStringGrid }
//-----------------------------------------------------------------------------
// TStringGirdのCreateEditorメソッド処理
// セルが編集状態になると自動的に実行されるメソッド
// ここで,TInplaceEditListのインスタンスを生成し
// ボタンをクリックした時に実行するイベント用のプロシージャを指定する
//
// PickListの行数とボタンの幅も設定可能
//-----------------------------------------------------------------------------
function TplStringGrid.CreateEditor: TInplaceEdit;
begin
inherited;
Result := TInplaceEditList.Create(Self);
TInplaceEditList(Result).OnGetPickListitems := EditListGetItemsEvent;
TInplaceEditList(Result).OnEditButtonClick := EditButtonClickEvent;
TInplaceEditList(Result).DropDownRows := 8;
TInplaceEditList(Result).ButtonWidth := 17;
end;
//-----------------------------------------------------------------------------
// TStringGirdのGetEditStyleメソッド処理
// ボタンのスタイルを決定する際に,自動的に実行されるメソッド
// ここでボタンのスタイルを設定する
// esSimpleがあるが,esSimpleは通常のセル
// GetはTStringGirdが取得するという意味
//-----------------------------------------------------------------------------
function TplStringGrid.GetEditStyle(ACol, ARow: Integer): TEditStyle;
begin
case ACol of
1: Result := esPickList;
2: Result := esEllipsis;
else
Result := inherited GetEditStyle(ACol, ARow);
end;
end;
//-----------------------------------------------------------------------------
// 利用者が定義したイベント処理用のプロシージャ
// ボタンのスタイルがesPickList[↓]の時の処理用
// ここでピックアップリストの値をセットする
//-----------------------------------------------------------------------------
procedure TplStringGrid.EditListGetItemsEvent(ACol, ARow: Integer; Items: TStrings);
begin
if ACol = 1 then begin
Items.Add('東京都');
Items.Add('埼玉県');
Items.Add('神奈川県');
Items.Add('群馬県');
Items.Add('栃木県');
Items.Add('茨城県');
Items.Add('千葉県');
Items.Add('長野県');
Items.Add('山梨県');
Items.Add('岐阜県');
Items.Add('新潟県');
Items.Add('福島県');
Items.Add('山形県');
end;
end;
//-----------------------------------------------------------------------------
// 利用者が定義したイベント処理用のプロシージャ
// ボタンのスタイルがesEllipsis[...]の時の処理用
//
// ここでは,セルの情報を表示するダイアログを表示
//-----------------------------------------------------------------------------
procedure TplStringGrid.EditButtonClickEvent(Sender: TObject);
var
LDialog : TForm;
LRect : TRect;
TheText : String;
LPos : TPoint;
begin
if Col = 2 then begin
LRect := CellRect(Col, Row);
//ダイアログに表示する情報
TheText := 'セル値 : ' + Cells[Col, Row] + sLineBreak;
TheText := TheText + '列番号 : ' + IntToStr(Col) + sLineBreak;
TheText := TheText + '行番号 : ' + IntToStr(Row) + sLineBreak;
TheText := TheText + '左端値 : ' + IntToStr(LRect.Left) + sLineBreak;
TheText := TheText + '上端値 : ' + IntToStr(LRect.Top);
LDialog := CreateMessageDialog(TheText, mtInformation, [mbOK], mbOK);
try
//ダイアログの表示位置を計算
//ダイアログの表示位置は,該当セルの左下とする
LPos := Self.ClientToScreen(Point(LRect.Left, LRect.Top));
LDialog.Left := LPos.X;
LDialog.Top := LPos.Y + (LRect.Bottom - LRect.Top) + 5;
LDialog.Width := 180;
//ダイアログを表示
LDialog.ShowModal;
finally
FreeAndNil(LDialog);
end;
end;
end;
end.
上のサンプルの実行結果を見ると,ドロップダウンのウィンドウは,
- システムの設定が,ウィンドウの下に影を表示しないになっていると,ドロップダウンのウィンドウの境界が明確でない
- 日本語の場合,表示に使用するフォントによっては行間が狭くなる
という仕様になっています.そこで,少しは体裁を整えるために,このリストをカスタマイズしたサンプルです.TInplaceEditList の CreateWnd と DropDown メソッドをオーバライドして,そのメソッド内に設定コードを記述しています.
下のコードは,最初のサンプルに追加した分です.ただし,最初のサンプルの TInplaceEditList の部分を TMyInplaceEditList に書き換えています. |
|
図5
カスタマイズしたドロップダウンリスト |
リスト2
ドロップダウンのリストをカスタマイズする例
最初のサンプルに追加した分.TInplaceEditList は TMyInplaceEditList に変更する |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, Grids, StdCtrls;
type
//---------------------------------------------------------------------------
// TInplaceEditListをカスタマイズするための継承クラス
//---------------------------------------------------------------------------
TMyInplaceEditList = class(TInplaceEditList)
protected
procedure CreateWnd; override;
procedure DropDown; override;
end;
//---------------------------------------------------------------------------
// TStringGridのセル編集時に[↓][...]ボタンを表示するには,
// 以下のメソッドをoverride実装したTStringGirdを作成する
// CreateEditor
// GetEditStyle
//
// EditListGetItemsEvent
// EditButtonClickEvent
// は,CreateEditorメソッド内で定義するボタンクリック関係のイベント用
// 関数名は任意,引数の順番と型は決まっている
//---------------------------------------------------------------------------
TplStringGrid = class(TStringGrid)
private
procedure EditListGetItemsEvent(ACol, ARow: Integer; Items: TStrings);
procedure EditButtonClickEvent(Sender: TObject);
protected
function CreateEditor: TInplaceEdit; override;
function GetEditStyle(ACol: Integer; ARow: Integer): TEditStyle; override;
end;
TForm1 = class(TForm)
Panel1: TPanel;
StringGrid1: TStringGrid;
Memo1: TMemo;
procedure FormCreate(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
uses plChgCompo;
{$R *.dfm}
//=============================================================================
// テスト用に列数と列幅等を設定し,テスト用のデータを各セルにセット
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
//フォーム作成時にコンポーネントの置換え
StringGrid1 := TStringGrid(ChangeComponent(StringGrid1, TplStringGrid));
StringGrid1.DefaultDrawing := True;
//編集可能にしないとインプレイスエディタは起動しない
StringGrid1.Options := StringGrid1.Options + [goEditing];
StringGrid1.FixedCols := 1;
StringGrid1.FixedRows := 1;
StringGrid1.ColCount := 4;
StringGrid1.RowCount := 4;
StringGrid1.DefaultColWidth := 80;
//左端の列幅設定
StringGrid1.ColWidths[0] := 10;
//テスト用の値をセット(固定行)
StringGrid1.Cells[1,0] := '都道府県';
StringGrid1.Cells[2,0] := '調査番号';
StringGrid1.Cells[3,0] := '結果値';
//テスト用の値をセット
StringGrid1.Cells[2,1] := 'A-100';
StringGrid1.Cells[2,2] := 'A-200';
StringGrid1.Cells[2,3] := 'A-300';
StringGrid1.Cells[3,1] := '500';
StringGrid1.Cells[3,2] := '800';
StringGrid1.Cells[3,3] := '300';
end;
{ TplStringGrid }
//-----------------------------------------------------------------------------
// TStringGirdのCreateEditorメソッド処理
// セルが編集状態になると自動的に実行されるメソッド
// ここで,TInplaceEditListのインスタンスを生成し
// ボタンをクリックした時に実行するイベント用のプロシージャを指定する
//
// PickListの行数とボタンの幅も設定可能
//-----------------------------------------------------------------------------
function TplStringGrid.CreateEditor: TInplaceEdit;
begin
inherited;
Result := TMyInplaceEditList.Create(Self);
TMyInplaceEditList(Result).OnGetPickListitems := EditListGetItemsEvent;
TMyInplaceEditList(Result).OnEditButtonClick := EditButtonClickEvent;
TMyInplaceEditList(Result).DropDownRows := 8;
TMyInplaceEditList(Result).ButtonWidth := 17;
end;
//-----------------------------------------------------------------------------
// TStringGirdのGetEditStyleメソッド処理
// ボタンのスタイルを決定する際に,自動的に実行されるメソッド
// ここでボタンのスタイルほ設定する
// esSimpleがあるが,esSimpleは通常のセル
// GetはTStringGirdが取得するという意味
//-----------------------------------------------------------------------------
function TplStringGrid.GetEditStyle(ACol, ARow: Integer): TEditStyle;
begin
case ACol of
1: Result := esPickList;
2: Result := esEllipsis;
else
Result := inherited GetEditStyle(ACol, ARow);
end;
end;
//-----------------------------------------------------------------------------
// 利用者が定義したイベント処理用のプロシージャ
// ボタンのスタイルがesPickList[↓]の時の処理用
// ここでピックアップリストの値をセットする
//-----------------------------------------------------------------------------
procedure TplStringGrid.EditListGetItemsEvent(ACol, ARow: Integer; Items: TStrings);
begin
if ACol = 1 then begin
Items.Add('東京都');
Items.Add('埼玉県');
Items.Add('神奈川県');
Items.Add('群馬県');
Items.Add('栃木県');
Items.Add('茨城県');
Items.Add('千葉県');
Items.Add('長野県');
Items.Add('山梨県');
Items.Add('岐阜県');
Items.Add('新潟県');
Items.Add('福島県');
Items.Add('山形県');
end;
end;
//-----------------------------------------------------------------------------
// 利用者が定義したイベント処理用のプロシージャ
// ボタンのスタイルがesEllipsis[...]の時の処理用
//
// ここでは,セルの情報を表示するダイアログを表示
//-----------------------------------------------------------------------------
procedure TplStringGrid.EditButtonClickEvent(Sender: TObject);
var
LDialog : TForm;
LRect : TRect;
TheText : String;
LPos : TPoint;
begin
if Col = 2 then begin
LRect := CellRect(Col, Row);
//ダイアログに表示する情報
TheText := 'セル値 : ' + Cells[Col, Row] + sLineBreak;
TheText := TheText + '列番号 : ' + IntToStr(Col) + sLineBreak;
TheText := TheText + '行番号 : ' + IntToStr(Row) + sLineBreak;
TheText := TheText + '左端値 : ' + IntToStr(LRect.Left) + sLineBreak;
TheText := TheText + '上端値 : ' + IntToStr(LRect.Top);
LDialog := CreateMessageDialog(TheText, mtInformation, [mbOK], mbOK);
try
//ダイアログの表示位置を計算
//ダイアログの表示位置は,該当セルの左下の座標値とする
LPos := Self.ClientToScreen(Point(LRect.Left, LRect.Top));
LDialog.Left := LPos.X;
LDialog.Top := LPos.Y + (LRect.Bottom - LRect.Top) + 5;
LDialog.Width := 180;
//ダイアログを表示
LDialog.ShowModal;
finally
FreeAndNil(LDialog);
end;
end;
end;
{ TMyInplaceEditList }
//-----------------------------------------------------------------------------
// TInplaceEditListクラスのCreateWndメソッド処理
// PickList(TCustomListBox)のスタイルを変更してみる
//
// ItemHeightの値を変更するには
// (1) このCreateWndメソッドでStyleをlbOwnerDrawVariableにする
// (3) DropDownのinheritedの前でItemHeightの値を設定する
// といいようである
//-----------------------------------------------------------------------------
procedure TMyInplaceEditList.CreateWnd;
begin
inherited;
//TPopupListboxの継承元はTCustomListBox
with TListBox(PickList) do begin
BevelKind := bkFlat;
BevelWidth := 1;
BevelInner := bvNone;
BevelOuter := bvRaised;
Style := lbOwnerDrawVariable;
end;
end;
//-----------------------------------------------------------------------------
// TInplaceEditListクラスのCreateメソッド処理
// PickList(TCustomListBox)の背景色と幅等を変更してみる
//-----------------------------------------------------------------------------
procedure TMyInplaceEditList.DropDown;
begin
//本当はTPopupListboxなのであるが,TPopupListboxの継承元はTCustomListBox
//iheritedの後で設定すると[↓]クリックしても,初回はリスト表示しない
//色はinheritedの後でないと反映されない
TListBox(PickList).ItemHeight := 18;
inherited;
TListBox(PickList).Color := $00FEF8E7;
TListBox(PickList).Width := 150;
TListBox(PickList).ItemIndex := 2;
end;
end.
ボタンのスタイルを esPickList にすると,矢印ボタンが表示され,ドロップダウンのウィンドウが表示されるようになっていますが,これを変更する例です.
このウィンドウは,TInplaceEditList の DropDown メソッドが表示しています.そこで,DropDown の元のコードを実行しないようにしたのが下のコードです.
下のコードは,最初のサンプルに追加した分です.ただし,最初のサンプルの TInplaceEditList の部分を TMyInplaceEditList に書き換えています.
下のコードでは単純なダイアログを表示するだけですが,項目の選択等のフォームをポップアップ表示すれば,元のドロップダウンのような用途としても利用可能でしょう.
|
|
図6
ドロップダウンの代りにダイアログを表示
|
リスト3
ドロップダウンのボタンでダイアログを表示するサンプル
最初のサンプルに追加した分.TInplaceEditList は TMyInplaceEditList に変更する |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, Grids, StdCtrls;
type
//---------------------------------------------------------------------------
// TInplaceEditListをカスタマイズする
// CreateEditorメソッドで,このTMyInplaceEditListを生成するようにする
//---------------------------------------------------------------------------
TMyInplaceEditList = class(TInplaceEditList)
protected
procedure DropDown; override;
end;
//---------------------------------------------------------------------------
// TStringGridのセル編集時に[↓][...]ボタンを表示するには,
// 以下のメソッドをoverride実装したTStringGirdを作成する
// CreateEditor
// GetEditStyle
//---------------------------------------------------------------------------
TplStringGrid = class(TStringGrid)
protected
function CreateEditor: TInplaceEdit; override;
function GetEditStyle(ACol: Integer; ARow: Integer): TEditStyle; override;
end;
TForm1 = class(TForm)
Panel1: TPanel;
StringGrid1: TStringGrid;
procedure FormCreate(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
uses plChgCompo;
{$R *.dfm}
//=============================================================================
// テスト用に列数と列幅等を設定し,テスト用のデータを各セルにセット
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
//フォーム作成時にコンポーネントの置換え
StringGrid1 := TStringGrid(ChangeComponent(StringGrid1, TplStringGrid));
StringGrid1.DefaultDrawing := True;
//編集可能にしないとインプレイスエディタは起動しない
StringGrid1.Options := StringGrid1.Options + [goEditing];
StringGrid1.FixedCols := 1;
StringGrid1.FixedRows := 1;
StringGrid1.ColCount := 4;
StringGrid1.RowCount := 4;
StringGrid1.DefaultColWidth := 80;
//左端の列幅設定
StringGrid1.ColWidths[0] := 10;
//テスト用の値をセット(固定行)
StringGrid1.Cells[1,0] := '都道府県';
StringGrid1.Cells[2,0] := '調査番号';
StringGrid1.Cells[3,0] := '結果値';
//テスト用の値をセット
StringGrid1.Cells[2,1] := 'A-100';
StringGrid1.Cells[2,2] := 'A-200';
StringGrid1.Cells[2,3] := 'A-300';
StringGrid1.Cells[3,1] := '500';
StringGrid1.Cells[3,2] := '800';
StringGrid1.Cells[3,3] := '300';
end;
{ TplStringGrid }
//-----------------------------------------------------------------------------
// TStringGirdのCreateEditorメソッド処理
// セルが編集状態になると自動的に実行されるメソッド
// ここで,TInplaceEditListのインスタンスを生成し
// ボタンをクリックした時に実行するイベント用のプロシージャを指定する
//
// PickListの行数とボタンの幅も設定可能
//-----------------------------------------------------------------------------
function TplStringGrid.CreateEditor: TInplaceEdit;
begin
inherited;
Result := TMyInplaceEditList.Create(Self);
TMyInplaceEditList(Result).DropDownRows := 8;
TMyInplaceEditList(Result).ButtonWidth := 17;
end;
//-----------------------------------------------------------------------------
// TStringGirdのGetEditStyleメソッド処理
// ボタンのスタイルを決定する際に,自動的に実行されるメソッド
// ここでボタンのスタイルほ設定する
// esSimpleがあるが,esSimpleは通常のセル
// GetはTStringGirdが取得するという意味
//-----------------------------------------------------------------------------
function TplStringGrid.GetEditStyle(ACol, ARow: Integer): TEditStyle;
begin
case ACol of
1: Result := esPickList;
else
Result := inherited GetEditStyle(ACol, ARow);
end;
end;
{ TMyInplaceEditList }
//-----------------------------------------------------------------------------
// TInplaceEditListクラスのDropDownメソッド処理
// PickListボタン[↓]でダイアログを表示してみる
// そのために,継承元のコードを実行しないようにする(inheritedを削除する)
//-----------------------------------------------------------------------------
procedure TMyInplaceEditList.DropDown;
var
LDialog : TForm;
LCol : Integer;
LRow : Integer;
LRect : TRect;
TheText : String;
LPos : TPoint;
begin
LCol := TStringGrid(Grid).Col;
if LCol = 1 then begin
LRow := TStringGrid(Grid).Row;
LRect := TStringGrid(Grid).CellRect(LCol, LRow);
//ダイアログに表示する情報
TheText := 'セル値 : ' + TStringGrid(Grid).Cells[LCol, LRow] + sLineBreak;
TheText := TheText + '列番号 : ' + IntToStr(LCol) + sLineBreak;
TheText := TheText + '行番号 : ' + IntToStr(LRow) + sLineBreak;
TheText := TheText + '左端値 : ' + IntToStr(LRect.Left) + sLineBreak;
TheText := TheText + '上端値 : ' + IntToStr(LRect.Top);
LDialog := CreateMessageDialog(TheText, mtInformation, [mbOK], mbOK);
try
//ダイアログの表示位置を計算
//セルの左下から表示する
LPos := TStringGrid(Grid).ClientToScreen(Point(LRect.Left, LRect.Top));
LDialog.Left := LPos.X;
LDialog.Top := LPos.Y + (LRect.Bottom - LRect.Top) + 5;
LDialog.Width := 180;
//ダイアログを表示
LDialog.ShowModal;
finally
FreeAndNil(LDialog);
end;
end;
end;
end.
|