Delphi -- スキルの探索:
{No.1}
モーダルフォームを作成するための文:
class PROcedure TMyForm.RunForm(AObj1, AObj2: TObject);
変数
vフォーム: TMyForm;
始める
vForm := TMyForm.Create(アプリケーション);
vForm を使用して行う
試す
InitForm(AObj1, AObj2);
モーダルを表示;
ついに
無料;
終わり;
終わり;
//*例:
クラスを通じて宣言された関数は、VC の静的関数と似ており、次のステートメントを使用します。
その他の具体的な情報については、Delphi ヘルプのクラスの説明を参照してください。
この慣用句を強調する目的は次のとおりです。
1. このフォームが複数の場所で使用されている場合、このコードが確実に均一に呼び出されるようにすることができます。
2. 関数が変更される場合 (例: ShowModal の戻り値に基づく処理)、この関数のみを変更します。
3. プログラムは適切にカプセル化されており、保守と引き継ぎが容易です。 *//
{No. 2}//タグの使用法
フォームツールバーボタンイベントへの応答
プロシージャ TMyForm.RunOperate(ATag: 整数);
始める
ケースAタグの
1: MyButton.Color := clRed;
2: MyButton.Color := clGreen;
3: MyButton.Color := clBlack;
終わり;
終わり;
プロシージャ TMyForm.ToolBtnClick(送信者: TObject);
始める
RunOperate(TControl(Sender).Tag);
終わり;
ドロップダウン メニューを使用していて、同様の機能を実行する必要がある場合は、
プロシージャ TMyForm.MenuItemClick(送信者: TObject);
始める
RunOperate(TMenuItem(Sender).Tag);
終わり;
//*例:
1. 明確な構造
2. 関連情報が集約され、確認、修正、保守が容易になります。
3. プログラムの適応性と拡張性を向上させます。たとえば、要件がツールバー ボタンに実装されずに別のボタンに実装された場合、変更が容易になります。
提案: 各カテゴリの後には 1 行または数行のコードが続きます。コードが多い場合は、代わりに process 関数を使用してください。
さらに興味深いのは、私がよく次のように書いていることです。
btnMyButton.Visible のケース
{表示} 本当: ...
{表示しない} False: ...
終わり; *//
{ No. 3 }//パラメータとしてイベントポインタ
// リストの読み取りなどにイベント ポインタを使用します。
タイプ
TDataSetEvent = オブジェクトのプロシージャ (DataSet: TDataSet; AIndex, ACount: Integer);
//TADOQuery から派生したクラス
プロシージャ TMyADOQuery.EnumRecord(AHereStr: String; APro: TDataSetEvent);
始める
近い;
SQL.クリア;
SQL.Add('Select * From Table1');
if AWhereStr <> '' then
SQL.Add('Where ' + AWhereStr);
開ける;
実行しない間は
始める
if Assigned(APro) then APro(Self, RecNo, RecordCount);
次;
終わり;
近い;
終わり;
//*例:
このメソッドは、現在のすべての子ウィンドウを列挙するための Window の API 関数 EnumChildWindow から来ています。
1. 原則: データの読み取りとデータの表示、データ処理などを分離するようにしてください。MVC などはすべてこの目的に使用されます。
2. プログラムの拡張性が向上しました。当初はリスト内の特定の列の情報を表示または処理したい場合に、プログラムを変更するときにデータ読み込み部分を読み込む必要がなくなりました。 , 情報表示などを修正するだけです。別の例として、レコードを読み取るときに、進行状況バーを使用して読み取りの進行状況を表示する必要があります。
*//
{ No. 4 } //定数配列
{No.2では以下の内容を実装します
プロシージャ TMyForm.RunOperate(ATag: 整数);
始める
ケースAタグの
1: MyButton.Color := clRed;
2: MyButton.Color := clGreen;
3: MyButton.Color := clBlack;
終わり;
終わり;
}
//その場合は配列を使用して実装するのが理想的です。
プロシージャ TMyForm.RunOperate(ATag: 整数);
定数
MyButtonColorMax := 3;
MyButtonColor: TColor の配列 [1..MyButtonColorMax] = (clRed, clGreen, clBlack);
始める
ケースAタグの
1..MyButtonColorMax: MyButton.Color := MyButtonColor[ATag];
101:....
終わり;
終わり;
//*例:
配列モードで使用する場合は、配列の上限または下限が定数を使用して実装されていることに注意し、今後の使用で配列ループの読み取りにこの定数を使用してみてください。
*//
{No. 5}メッセージメカニズムによりクラスのパブリック関数が削減される
//フォーム内のパブリック関数の定義を最小限に抑える方法。
{例: 現在のフォーム コントロールのプロパティ リスト フォームを実装する場合、特定のプロパティの値を変更する必要がある場合など、多くの情報が必要になります。それは対話する必要があります。クラスのパブリック関数を使用する場合、多くのパブリック関数を定義する必要があります。同時に帳票タイプの変換が必要な場合は、対象の帳票タイプに変換した後でのみパブリック関数を使用できます。したがって、2 つのユニットを互いに含める必要がある状況が発生します。}
//解決:
TfrmMyForm = クラス(TForm)
Ffrmプロパティ: TForm;
終わり;
...
FfrmProperty := TfrmProperty.MyCreate(Application, Self);
...
//プロパティウィンドウを更新する必要がある場合
FfrmProperty.Perform(WD_REFRESHPROPERTYLIST, 0, 0);
TfrmProperty = クラス(TForm)
プライベート
FMyForm: TForm;
プロシージャ WDREFRESHPROPERTYLIST(var メッセージ: TMessage) メッセージ WD_REFRESHPROPERTYLIST;
公共
コンストラクター MyCreate(Owner: TComponent; AForm: TForm);
終わり;
コンストラクター TfrmProperty.MyCreate(Owner: TComponent; AForm: TForm);
始める
継承された Create(Owner);
FMyForm := AForm;
終わり;
//* メッセージの使い方としては、フォームのパブリック関数の定義を減らすことができます。同時に、プログラムのスケーラビリティも向上します。代わりに彼のフォームを使用する場合、それはせいぜいあなたのフォームであり、現在のメッセージを処理しないため、簡単に変換できます*)//
{No. 6}登録リストを使用して拡張モジュールを管理する
//プロジェクト: データセットに対して複数の出力表示方法をサポートする必要があります
...例は後で示します
//* 以下を説明します。
1. 「複数の出力方法」とは、出力方法が将来のアプリケーションで頻繁に拡張される可能性があることを意味するため、プログラム設計時に出力方法の容易な拡張性を考慮する必要があります。
2. VCL のコントロール登録 (RegisterComponents) メカニズムを参照すると、VCL では多数の登録メカニズムが使用されていることがわかります。より古典的なものはコントロール プロパティ エディターの登録です。
*//
{No.7}あらかじめ定義された制御プログラムのバージョンを使用する
//二次開発プラットフォーム プログラムを実行している場合は、製品のバージョン管理とプロジェクトのバージョン管理の問題を含める必要があります
//通常は事前定義されたメソッドを使用して制御されます
// ステートメントは比較的単純です。
{$定義ジョイユアン97}
{$IFDEF JOYYUAN97} {ELSE} {ENDIF}
{$UNDEFジョイユアン97}
*イラスト:
1. 事前定義を複数の個別のファイルに分割します。
2. 各ユニットの先頭、ユニットの後に、{$I ...} を使用してファイルを現在のユニットに含めます。
3. 事前定義された条件に基づいて、現在のユニットに含めることができるユニット ファイルを制御します
4. プロジェクトの事前定義ファイルを分離してみます。すべての事前定義ファイルを含めた後、このファイルに、プロジェクトの必要に応じていくつかの事前定義ファイルを含めます。
*//
{No. 8}関数ポインタを使用してユニット プロジェクトの包含を減らす
//ユニットの包含を減らすことがパブリックユニットを作る第一歩だとよく思うので、ユニットの包含をできるだけ減らすにはどうすればよいか
//つまり、プログラム単位の結合を減らす方法についてさらに努力する必要がある。
{シナリオの説明:
TMyFormManager: フォーム管理クラス
TMyForm: データフォーム基本クラス
TMyFormaccess: フォーム情報の保存・読み込みクラス。フォーム情報をデータベースまたはその他のタイプの構造に保存します。
分析します:
1. フォーム基本クラス (TMyForm) とフォーム管理クラス (TMyFormManager) は、ユニット uManagers に実装する必要があります。
2. フォーム固有の実装クラス (TMyImageForm) ユニット fMyImange には、フォーム継承とフォーム管理のためのユニット uManagers が含まれる必要があります。
3. フォームデータ読み取りクラス (TMyFormAccess) ユニット uMyAccess には、ユニット uManagers とユニット fMyImange が含まれている必要があります。
質問:
フォームを保存したい場合は、フォームのボタンイベントで行う必要があります。フォーム ユニットに関しては、フォーム データ アクセス クラス ユニットが含まれている必要があり、フォーム基本クラスに配置されている場合は、ユニット uManager にユニット uMyAccess が含まれている必要があります。
データ アクセス、つまりデータ ストレージ形式が要件に基づいて変更され、スケーラビリティが必要な場合、セルの包含は危険です。
解決策: 関数ポインター変数を使用します。
1. uManagersユニットに関数ポインタ変数を定義し、データ情報を保存します。
2. アプリケーションの初期化時に、この関数ポインタ変数に値を割り当てます。
3. フォーム情報を保存する必要がある場合は、ポインタが空でないことを確認してから、フォーム情報を保存する関数を実行します。
{No. 9}定数、定数を理解し、定数を使用する
定数定義の重要性を紹介する本はたくさんあり、私もよく思うのですが、VCLのソースコードを見ると、他人が定数を使っていることを無視してきたことに気づきます。
1. 私たちがよく使用するメッセージの定義は次のとおりです。定数を宣言し、適切なときにそれを使用します。
一般的に定義および使用されるのは次のとおりです。
定数
WD_MyMessage = WM_User + 101;
タイプ
TMyForm = クラス(TForm)
...
プロシージャ WDMyMessage(var message: TMessage); メッセージ WD_MyMessage {応答メッセージの位置};
終わり;
ただし、{応答メッセージの位置} ステートメントを次のように書き換えると、次のようになります。
プロシージャ WDMyMessage(var message: TMessage); メッセージ WM_User + 101;
同様に、コンパイルは成功し、使用は正常に行われます。したがって、定数定義は Windows システムの処理とインターフェイスで非常に一般的に使用されます。
2. Delphi では、clRed、clGreen などの色変数を定義しました。これらは、将来の使用を容易にするために定義された定数でもあります。この観察を通じて、定数の定義はプロジェクト内で部分的に再利用できる必要があることがわかりました。そこで、標準の定数ユニットを定義して、定義した定数を各プロジェクトで再利用できるようにすることができます。
{No. 10}Delphi でよく使われる配列
Delphi には、TIdentMapEntryd 型の配列の定義と使用のための比較的完全な実装があります。
TIdentMapEntry = レコード
値: 整数。
名前: 文字列。
終わり;
1. 配列定義: TIdentMapEntry の array[0..ArrMax]
参照してください: 制御ユニット:
カーソル: TIdentMapEntry の array[0..21] = (
...
);
2. 相互に評価する 2 つの関数: IntToIdent (値から名前を検索) と IdentToInt (名前から値を検索)。
特定のアプリケーションについては、IdentToCursor および CursorToIdent を参照してください。
3. 応用: a. このツリー グループ定義メソッドと配列操作関数を直接適用します。 b. 関数内の配列にアクセスして操作する方法を学びます。 c. 標準的な情報アクセス関数の定義を学習します: function IntToIdent(Int: Longint; var Ident: string; const Map: array of TIdentMapEntry): Boolean; アクセスが有効かどうかについては、パラメータによって返されます。関数に渡されたブール値の戻り値を判定します。
{No. 11}特殊なケースから一般的な発見まで
カーソルの定義と操作関数を追跡することで次のことを発見しました。
1. {No.10}で紹介したように、カーソルの定義と一般的な操作を一般化します。
2. Int と Ident 間の変換関数を提供します。
3. 配列のリスト情報を周期的に読み込む関数: GetCursorValues; このうち、リスト情報の読み込みには、{その3}で紹介した「イベントポインタをパラメータとして使用する」方法を使用します。
{No.6}の補足:
例:
プロシージャ RegisterComponents(const Page: string;
ComponentClasses: TComponentClass の配列);
始める
割り当て済み(RegisterComponentsProc)の場合
RegisterComponentsProc(ページ, コンポーネントクラス)
それ以外
raise EComponentError.CreateRes(@SRegisterError);
終わり;
解釈:
1. 登録メソッドを使用して、使用できるコントロールの種類などを記録します。
3. RegisterComponentsProc では、将来のプログラム拡張やバージョンアップ等を容易にするため、{No.8}の「関数ポインタを利用して単位プロジェクトの組み込みを減らす」方法を採用しています。
{いいえ。11}パブリック関数は 1 つだけ定義してください
//プロジェクトの説明: 次に、CAD 図面または Visio システムを実装する必要があります。これには、優れた拡張性と容易なメンテナンスが必要です。
//また、システムの一部または拡張されたシステムをパッケージ化して将来のプロジェクトで直接使用できるように、低結合性が必要です。
デザイン:
1. グラフィカル オブジェクト抽象クラスを設計します。このクラスでは、抽象関数 CadPerform を定義します。関数のパラメータは、関数 TControl.Perform(Msg: Cardinal; WParam, LParam: Longint) を参照します。
2. グラフィックス管理クラスでは、グラフィックスオブジェクトリストの管理を実装します。リストに格納されるのは抽象オブジェクトのポインタです。
3. 特定のクラス オブジェクトを制御する場合は、CanPerform 関数を使用し、現在の操作のカテゴリに応じて Msg を渡し、対応するパラメーター情報を渡すだけです。
実装: TCad は、抽象クラスから継承された第 1 レベルのコントロール クラスです。
関数 TCad.CadPerform(Msg: Cardinal; WParam、LParam: Longint): Longint;
始める
のケースメッセージ
My_Message1: 結果 := MyMessage1(WParam, LParam);
My_Message2: 結果 := MyMessage2(WParam, LParam);
終わり;
終わり;
TPoint は TCad から継承しているため、CadPerform 関数は次のように実装されます。
関数 TPoint.CadPerform(Msg: Cardinal; WParam、LParam: Longint): Longint;
始める
のケースメッセージ
My_Message1: Result := MyMessage1(WParam, LParam); //TCad でのこの操作タイプの処理はブロックされます。
My_Message3: 結果 := MyMessage3(WParam, LParam);
else Result := 継承された CadPerform(Msg, WParam, LParam);
終わり;
終わり;
*イラスト:
グラフィックス オブジェクトを頻繁に操作するため、クラスの高度なカプセル化とプログラムの保守と拡張を容易にするために、パブリックでオープンなインターフェイス関数を定義します。
*//
{No.12}
私のプログラミング要件は次のとおりです: (一部の情報には言語制限がありません)
//以下のほぼすべての解決策は上記のメソッドで見つけることができます。
1. プログラムの複雑さを軽減します。 a. 関数の数を減らし、Case メソッドと Tag メソッドを使用し、Perform の定義方法を学習します。 b. ユニットの入れ子関係を減らし、メッセージ パッシング メソッドを使用し、フォーム ユニットの相互包含を減らします。
2.減らす
{No. 13} ブロードキャストを使用して管理クラスから管理リスト オブジェクトへの通知を実装する
//{No. 12} プロジェクトの説明では、描画フォーム コントロールのプロパティまたはステータスが変更されると、多くの場合、すべてのグラフィック オブジェクトに通知し、対応する変更を行う必要があります。
//ブロードキャスト関数を1つ定義するだけで親子通知が実現でき、プログラムの再利用性、拡張性、保守性などが向上し、クラス構造が明確になります。
//例: 1. Visio および MapInfo では、現在のフォームの縮尺 (ズーム率) が変更された場合、現在表示されているすべてのグラフィックス オブジェクトを新しい縮尺で再描画する必要があります。 2. 現在のフォームのデフォルトのフォームフォントを変更すると、テキスト情報を表示するためにデフォルトでフォームフォントを使用するグラフィックオブジェクトのテキストフォントもそれに応じて変更する必要があります。
//解決策は、属性またはステータスが変更されたときにすべてのサブコントロールに通知する TWinControl の処理メカニズムを参照してください。
プロシージャ TWinControl.NotifyControls(メッセージ: Word);
変数
メッセージ: Tメッセージ;
始める
Message.Msg := メッセージ;
Message.WParam := 0;
Message.LParam := 0;
メッセージ.結果 := 0;
Broadcast(Message);//現在の変更メッセージをブロードキャストする
終わり;
で:
プロシージャ TWinControl.Broadcast(var Message);
変数
I: 整数。
始める
for I := 0 から ControlCount - 1 まで
始める
Controls[I].WindowProc(TMessage(メッセージ));
//次のように変更します。 with TMessage(Message) do Cads[I].CadPerform(msg, WParam, LParam);
TMessage(Message).Result <> 0 の場合、終了します。
終わり;
終わり;
ただし、グラフィックス オブジェクトを扱う場合は、Cads の CanPerform パブリック関数を直接呼び出すことがあります。
{No. 14}必要に応じてオブジェクトを動的に作成する
例: http://www.delphibbs.com/keylife/iblog_show.asp?xid=824
//************オプション 2: 必要に応じてプロパティ フォームを作成する
用途
...
fプロパティ;
タイプ
TfrmMyMap = クラス
...
プロシージャ OnfrmMyMapDestroy(送信者: TObject);
プロシージャ OnMapGeoSelected(AGeo: TGeometry);
プライベート
Ffrmプロパティ: Tfrmプロパティ;
プロシージャ ShowPropertyForm(aVisible: Boolean);
公共
終わり;
プロシージャ TfrmMyMap.ShowPropertyForm(aVisible: Boolean);
始める
if Not Assigned(FfrmProperty) then FfrmProperty := TfrmProperty.Create(Application);
FfrmProperty.Visible := aVisible;
終わり;
プロシージャ TfrmMyMap.OnfrmMyMapDestroy(送信者: TObject);
始める
Assigned(FfrmProperty) の場合、FfrmProperty.Free;
終わり;
プロシージャ TfrmMyMap.OnMapGeoSelected(AGeo: TGeometry);
始める
if Assigned(FfrmProperty) then FfrmProperty.MyRefresh(AGeo);
終わり;
ここでは次のように説明されています。
1. 必要に応じてオブジェクト FfrmProperty を動的に作成します
2. 現在のオブジェクトが解放されたら、オブジェクトの正当性を判断し、動的に作成されたオブジェクトを解放します。
{No. 15}インターフェースを作成するか構造を作成する
//プロジェクト説明: テーブルコントロールを開発する際、セルをComに設定すると、テーブル内の情報が多すぎると読み込み速度が保証できず、クラッシュする可能性もあります。 Comを使用する理由は、将来的に各セルの処理と情報を制御外に拡張できるようにするためです。
私の解決策は、Cellから派生した各コントロールのインスタンスを作成し、各セルの情報を記録するいくつかの構造体オブジェクトRecordを動的に作成することです。セルを操作する必要がある場合は、Cellコンポーネントに構造体オブジェクトのポインタを割り当てます。テスト結果は次のとおりです。非常に満足です。
したがって、Com の多数のインスタンスを使用する必要がある場合は、1 つのインスタンスを管理および保守するようにしてください。そうすれば、そのインスタンス内のデータが動的に作成および管理され、速度の点で良い効果が得られます。
さらに、パラメーターを渡したり使用したりするときに、 pMyInterface = ^IMyInterface インターフェイス ポインターを宣言してください。これにより、カウント関数 _AddInft などの呼び出しの回数が減り、速度も向上します。動作は普通です。