李小平/河北省固安市華北石油工科大学
----どのようなプログラムを開発するにしても、データ入力は欠かせません。美しい入力インターフェースを素早く生成できれば、プログラム開発の効率が大幅に向上することは間違いありません。システムの元の制御では満足できないことがよくあります。 Delphi では、特定のフィールドの場合、オプションのコントロールは DBLabel、DBEdit などです。テーブル全体の入力の場合、DBGrid があります。 Dbedit などのコントロールを使用する場合、ユーザーは各フィールドの位置を完全に調整する必要があります。これにより美しい効果が得られますが、フィールドの数が多い場合は非常に面倒になることは間違いありません。 DBGridを使用すると、フィールドがいくつあってもコントロールは1つだけで済むので簡単ですが、フィールドが1つずつ配置されるので少し使いにくいです。一般ユーザーにとって、表形式での入力は便利で美しいものです。これがこの記事が解決することを目的とした問題です。
----テクニカルキー
----このコントロールの主な機能は、データベース フィールドを編集することです。一般的な規則に従って、コントロールには TdataLink オブジェクトを含め、TdataLink に関連する一連のメソッドを実装する必要がありますが、これには大量のコードが必要になります。コードの量が増えると、システムが複雑になり、エラーが発生する可能性が高くなります。このコントロールの開発思想は、最小限のコードで最大限の機能を実現することです。したがって、TDBComboBox コントロールを使用してデータ フィールドを直接編集します。
---- 汎用性を実現するために、フィールド編集コントロール配列とフィールド タイトル配列がコントロール内に保持されます。次のように:
エディタ: TDBComboBox の配列。
-> 編集に使用される、動的に生成されるデータ コントロールの特定の配列
ラベル: TLabel の配列。
->各フィールドのタイトルは動的に生成されます
----TDBComboBox を使用する利点は、一般的な編集機能だけでなく、対応するプロンプト情報を各フィールドに追加できることです。コードは次のとおりです。
{フィールド I にプロンプト情報を追加する方法}
手順 TDBPanel.AddHits
(ItemIndex: 整数; ヒット数: 文字列の配列);
変数
m、n、i: 整数。
始める
n := 長さ(エディター);
m := 長さ(ヒット数);
ItemIndex< n の場合は開始します
for i:=0 から m-1 do Editors[ItemIndex].Items.Add(Hits[i]);
終わり;
終わり;
---- 特定のアプリケーションは多種多様であるため、プログラマーが特定のアプリケーション用の特別な機能を実装できるように、コントロールには十分なイベント処理インターフェイスを残す必要もあります。これには、ユーザーが実装するためにコントロール内に特定のイベント処理メソッドを定義する必要があります。ここで提供されるのは、すべてのフィールドが編集されたときに実行される処理である OnOkClick イベントです。コードは次のとおりです。
OKボタン: Tボタン;
-> 最後に追加された [OK] ボタンは、送信アクションを実装するために使用されます。
プロパティ OnOkClick: TNotifyEvent 読み取り FClick 書き込み FClick;
---- OnOKClick メソッドを実装することで、ユーザーは送信やデータ合理性テストなどのさまざまな処理タスクを完了できます。特別な処理が必要なもう 1 つのことは、さまざまなフィールド間の変換の制御です。デフォルトではマウスをクリックします。ただし、ユーザーの習慣として、キーボードの「上下左右」の 4 つの矢印キーを使用することがよくあります。この機能を実装するには、次の 2 つのメソッドを定義する必要があります。
プロシージャ AKeyPress(Sender: TObject; var Key: Char);
プロシージャ AKeyDown(送信者: TObject;
var キー: Word; Shift: TShiftState);
---- 上記 2 つのメソッドを動的に生成されたエディターに割り当てて、矢印キーへの応答を実装します。
---- テーブルごとにフィールドの数が異なるため、表示されない場合があるため、スクロール機能が必要です。したがって、TscrollBox コントロールがコントロールに挿入されます。最後に注意すべきことは、動的コントロールの取り消しとメモリの解放です。制御配列の取り消しとメモリの解放は、作成とはまったく逆の順序で行われます。そうしないと、何か問題が発生します。
----コントロールの使用
---- まず DBPanel コントロールをフォームに配置し、次にデータ ソース プロパティ、データ入力フォームの列数、およびその他のプロパティを設定します。プログラムでは、データ ソースを開いた後、データ編集コントロールを作成するメソッドを呼び出すだけです。今すぐ:
Query1.Open;->データソースを開く
DBPanel1.CreateEditors -> 各フィールドの編集コントロールを作成します。
DBPanel1.AddHits(0,['1111','11222','eeee']);
->特定のフィールドにプロンプト情報を設定します
DBPanel1.AddHits(1,['1111','11222','eeee']);
->特定のフィールドにプロンプト情報を設定します
コントロールおよびサンプル プログラムは Win98+Delphi 5.0 環境でデバッグされています。
---- 添付ファイル:TDBPanelのソースコード
ユニット DBPanel;
インタフェース
用途
ウィンドウ、メッセージ、SysUtils、クラス、
グラフィックス、コントロール、フォーム、ダイアログ、
ExtCtrls、dbctrls、stdctrls、db;
タイプ
TDBPanel = クラス(TPanel)
プライベート
{プライベート宣言}
FLeft: 整数。
FTop: 整数;
maxTextLen: 整数;
maxLabelLen: 整数;
FScrollBox: TScrollBox;{スクロール コントロール}
FLineHeight: 整数;
FClick: TNotifyEvent;
エディタ: TDBComboBox の配列。
-> 編集に使用される、動的に生成されるデータ コントロールの特定の配列
ラベル: TLabel の配列。
->各フィールドのタイトルは動的に生成されます
OKボタン: Tボタン;
-> 最後に追加された [OK] ボタンは、送信アクションを実装するために使用されます。
{データソース}
FDataSource: TDataSource;
FColumns: 整数。
->テーブルの列数を入力します。
保護された
{ 保護された宣言 }
プロシージャ FreeEditors;
→データ入力制御のメモリを解放
公共
プロシージャ CreateEditors;//
(DS: TDataSource; ColCount: 整数);
->各フィールドのデータ入力コントロールを作成する
コンストラクター Create(AOwner:
TComponent);
デストラクタ オーバーライド;
プロシージャ AKeyPress(送信者:
TObject; var キー: Char);
プロシージャ AKeyDown(送信者:
TObject; var キー: Word;
TShiftState);
プロシージャ ClearHits(ItemIndex: Integer);
プロシージャ AddHits(ItemIndex:
整数; ヒット数: 文字列の配列);
関数エディター(インデックス: 整数):
TDBコンボボックス;
{公的宣言}
出版された
propertyLeftLimit: 整数の読み取り
FLeft 書き込み FLeft デフォルト 10;
プロパティ TopLimit: 整数読み取り
FTop 書き込み FTop デフォルト 10;
プロパティ EditorLen: 整数読み取り
maxTextLen maxTextLen を書き込みます。
プロパティ LabelLen: 整数読み取り
maxLabelLen maxLabelLen のデフォルト 100 を書き込みます。
プロパティ LineHeight: 整数読み取り
FLineHeight 書き込み FLineHeight デフォルト 15;
プロパティ OnOkClick: TNotifyEvent
FClick を読み取り、FClick を書き込みます。
プロパティ データソース: TDataSource
FDataSource を読み取り FDataSource を書き込みます。
->データソース
プロパティ列: 整数読み取り
FColumns は FColumns を書き込みます;-> テーブル列の数
{ 公開された宣言 }
終わり;
手順 登録;
実装
手順 登録;
始める
RegisterComponents('追加', [TDBPanel]);
終わり;
{フィールド I にプロンプト情報を追加する方法}
プロシージャ TDBPanel.AddHits(ItemIndex:
整数; ヒット数: 文字列の配列);
変数
m、n、i: 整数。
始める
n := 長さ(エディター);
m := 長さ(ヒット数);
ItemIndex< n の場合は開始します
for i:=0 から m-1 do Editors[ItemIndex].Items.Add(Hits[i]);
終わり;
終わり;
プロシージャ TDBPanel.AKeyDown
(送信者: TObject; var Key: Word;
シフト: TShiftState);
始める
if (送信者が TDBComboBox である場合)、開始します
ケースのキー
VK_Next: (TDBComboBox として送信者)
.DataSource.DataSet.Next;
VK_PRIOR: (TDBComboBox として送信者)
.DataSource.DataSet.Prior;
終わり;
終わり;
終わり;
プロシージャ TDBPanel.AKeyPress(Sender: TObject; var Key: Char);
始める
if (送信者が TDBComboBox である場合)、開始します
if Key=#13 then (Owner as TForm).Perform(WM_NEXTDLGCTL, 0, 0);
終わり;
終わり;
プロシージャ TDBPanel.ClearHits(ItemIndex: Integer);
変数
n: 整数。
始める
n := 長さ(エディター);
itemIndex< n の場合、Editors[ItemIndex].Items.Clear;
終わり;
コンストラクター TDBPanel.Create(AOwner: TComponent);
始める
継承された Create(AOWner);
F左 :=10;
Fトップ := 10;
maxTextLen := 100;
maxLabelLen := 100;
FLineHeight := 15;
終わり;
{フィールドごとにデータ入力コントロールを作成する方法}
プロシージャ TDBPanel.CreateEditors;//
(DS: TDataSource; ColCount: 整数);
変数
i、n、RowCount: 整数。
TextHeight: 整数;
始める
DataSource.DataSet.Active の場合は開始します
n := DataSource.DataSet.FieldCount;
{タイトルの最大長と表示長を計算する}
DataSource.DataSet.First;
{高さを計算する}
TextHeight := Canvas.TextHeight(データソース
.DataSet.Fields[0].DisplayLabel) + FLineHeight;
{行数と列数を計算する}
RowCount := n div 列;
if n mod Columns < > 0 then inc(RowCount);
{メモリを割り当てる}
無料エディター;
SetLength(エディター, n);
SetLength(ラベル, n);
{スクロールボックスの作成}
FScrollBox := TScrollBox.Create(Owner);
FScrollBox.Parent := Self;
FScrollBox.Align := alClient;
{作成編集}
for i:=0 から n-1 までが始まります
{タイトルの作成}
ラベル[i] := TLabel.Create(Owner);
Labels[i].Parent := FScrollBox //Self;
Labels[i].Caption := DataSource.DataSet.Fields[i].DisplayLabel;
Labels[i].Left := FLeft + (maxLabelLen +
maxTextLen + 10) * (i div RowCount);
Labels[i].Width := maxLabelLen;
Labels[i].Top := FTop + (i mod RowCount) * TextHeight + 5;
{編集オブジェクトの作成}
エディタ[i] := TDBComboBox.Create(Owner);
Editors[i].Parent := FScrollBox //Self;
Editors[i].Left := Labels[i].Left + Labels[i].Width;
Editors[i].Width := maxTextLen;
Editors[i].Top := FTop + (i mod RowCount) * TextHeight;
Editors[i].DataSource := DataSource;
Editors[i].DataField := DataSource.DataSet.Fields[i].FieldName;
Editors[i].OnKeyPress := AKeyPress;
Editors[i].OnKeyDown := AKeyDown;
終わり;
{OK ボタンを作成}
OkButton := TButton.Create(Owner);
OkButton.Parent := FScrollBox;
OkButton.Left := Editors[n-1].Left;
OkButton.Top := Editors[n-1].Top + TextHeight;
OKButton.Caption := 'OK';
OKButton.OnClick := FClick;
終わり;
終わり;
デストラクター TDBPanel.Destroy;
始める
無料エディター;
継承された破壊。
終わり;
関数 TDBPanel.Editor(インデックス: 整数): TDBComboBox;
始める
if Index< Length(Editors) then Result := Editors[インデックス]
else 結果 := nil;
終わり;
プロシージャ TDBPanel.FreeEditors;
変数
i,n: 整数。
始める
{メモリは順番に解放されなければなりません!作成とは逆の順序で行う必要があります。
特にコンポーネント間に親子関係がある場合}
OkButton< >nil の場合、OkButton.Free;
Editors< >nil の場合、開始します
n := 長さ(エディター);
i:=0 から n-1 の場合、Editors[i].free を実行します。
編集者 := nil;
n := 長さ(ラベル);
i:=0 から n-1 の場合は、Labels[i].Free を実行します。
ラベル := nil;
終わり;
FScrollBox< >nil の場合、開始します
FScrollBox.Free;
FScrollBox := nil;
終わり;
終わり;
終わり。