Delphi コンポーネントにはCreateWnd
and CreateWindowHandle
(およびDestroyWnd
and DestroyWindowHandle
) があります。どちらも子孫によってオーバーライドされることを意図していますよね? 基になる VCL 実装以外で呼び出されることを意図していませんか?
それらの違いは何ですか。それらのいずれかをいつオーバーライドする必要がありますか?
Delphi コンポーネントにはCreateWnd
and CreateWindowHandle
(およびDestroyWnd
and DestroyWindowHandle
) があります。どちらも子孫によってオーバーライドされることを意図していますよね? 基になる VCL 実装以外で呼び出されることを意図していませんか?
それらの違いは何ですか。それらのいずれかをいつオーバーライドする必要がありますか?
これまでのところ、ここでの回答のほとんどはほぼ的を射ており、彼らのアドバイスに耳を傾けるのがよいでしょう。ただし、この話にはもう少し続きがあります。いずれかをオーバーライドする時期についての特定の質問に対して、少し簡単に説明します。
CreateParams();
一般に、ほとんどの場合、実際に行う必要があるのは CreateParams() をオーバーライドすることだけです。既存のコントロール クラスをサブクラス化し (Windows スタイルの「サブクラス化」を覚えていますか?Petzold の Windows プログラミングに関する重要な研究を参照してください)、それを VCL コントロールにラップするだけの場合は、CreateParams からこれを行います。また、設定するスタイル ビットやその他のさまざまなパラメーターを制御することもできます。「サブクラス」を作成するプロセスを非常に簡単にしました。CreateParams() メソッドから CreateSubClass() を呼び出すだけです。TCheckBox や TButton などの例については、コア VCL コントロールを参照してください。
CreateWnd();
ウィンドウ ハンドルが作成されたら、それをもう少し処理する必要がある場合は、これをオーバーライドします。たとえば、ある種のリスト、ツリー、または作成後の構成が必要なコントロールがある場合は、ここで行います。継承された CreateWnd を呼び出し、それが戻ってきたら (CreateWnd から戻った場合、何かがうまくいかなかった場合に例外が発生するため、有効なハンドルがあることがわかっています)、追加の魔法を適用するだけです。一般的なシナリオは、インスタンス TStrings リストにキャッシュされたデータを取得し、実際にそれを下層のウィンドウ コントロールに移動することです。TListBox は、この典型的な例です。
CreateWindowHandle();
私はこれで私の記憶をリフレッシュしなければなりませんでしたが、これはめったに上書きされないようです. VCL 自体のいくつかのケースでは、TEdit や TMemo などの一部のコントロールを使用して、特定の Windows バージョンとロケールの異常を回避するために使用されているようです。もう 1 つのより明確なケースは、TCustomForm 自体にあります。この場合、古い MDI (マルチドキュメント インターフェイス) モデルをサポートするために存在します。この場合、通常の CreateWindowEx() API を使用して MDI 子を作成することはできません。実際にハンドルを作成するには、MDI 親フレームにメッセージを送信する必要があります。したがって、このメソッドをオーバーライドする唯一の理由は、ハンドルを作成する実際のプロセスが、昔ながらの実証済みの CreateWindowEx() とはまったく異なる方法で行われる場合です。
あなたの質問は単に作成プロセスについて尋ねているだけであることに気付きましたが、ハンドルの破壊と、ハンドルの再作成を取り巻く「ブードゥー」の両方に対して、場合によってはオーバーライドされる対応するメソッドがあります。しかし、これらは個別にカバーする必要がある他のトピックです:-)。
CreateWndは最初にCreateParamsを呼び出し、次に作成されたParamsを使用してCreateWindowHandleを呼び出します。通常、CreateWindowHandleではなくCreateWndとCreateParamsをオーバーライドします。
これがお役に立てば幸いです。
誰が何をするか:
CreateWndは、WinControl の完全に形成されたウィンドウを作成するゼネラル コントラクターです。まず、CreateParams を呼び出してWindowClass
に必要な属性を設定し、正しく登録されていることを確認する必要があります。次に、OS から結果のハンドルを返すCreateWindowHandleを
呼び出して、実際に作成されたウィンドウを取得します。
その後、メッセージを処理できる有効なウィンドウが作成され、CreateWndが最終的なグルーミングを行い、サイズ、フォントなどのさまざまな視覚的側面を調整します。
CreateWnd が終了した後、VCL がそのウィンドウ (識別、親子関係など) を管理するのを支援するために、 CreateHandle によって実行される後のステップもあります。
最終的な答えは、VCL の作成に関与した人々 (アレン?) からしか得られないと確信していますが、私見では、責任が最も少ない仮想メソッド/呼び出しチェーンで最も低いものをオーバーライドする必要があります。そのため、常にCreateParams()とCreateWindowHandle( ) をオーバーライドしてきました。どちらもCreateWnd()によって呼び出され、どちらも特別なことを 1 つだけ行うため、これは適切に見えます。
結局は好みの問題なのではないでしょうか。