2010-11-30 12 views
3

Delphiコントロールをフェールセーフで解放する方法はありますか?Delphi:実行時に動的コントロールを解放する

私はTStringGridの子孫を持っていますが、これはインプレースエディタのためのカスタムコントロールを埋め込んでいます。ユーザーがタブキーまたは矢印キーを使用してグリッドのセル内を移動するとき、セルが編集可能な場合は動的コントロールを作成する必要があります。私は必要なイベントをフックして、私のカスタムコントロールのOnKeyDownイベントを利用して、ナビゲーションキーを親のTStringGridに戻します。

以前は、TStringGridの子孫が埋め込みコントロールでFreeAndNilを呼び出すだけでしたが、状況によってはUpdateUIState/GetParentForm内でアクセス違反が発生することがありました。コールスタックを見ると、コントロールがフリーズされた後に、WM_KEYDOWN(TWinControl.WMKeyDown)メッセージがまだ発生していたようです。

私はすべての準備をして、How to free control inside its event handler?で説明した変更を実装しました。これは問題を解決したようですが、私はこのアプローチに他のキャビットがあるかどうか疑問に思っています。

実際には、この回避策では、CM_RELEASEメッセージがポストされた時点でキュー上に存在するすべてのメッセージの後まで、コントロールの破棄が遅延されました。

CM_RELEASEがポストされた後、別のWM_KEY *または類似のメッセージがすべてメッセージキューにポストされている可能性はありませんか?だから、

procedure TMyCustomControl.HandleRelease(var Msg: TMessage); 
begin 
    Free; 
end; 

が、これはすべてのインスタンスに安全になりますか、私はキューから他のメッセージをクリアするために何かをする必要があります。

私の現在のCM_RELEASEハンドラは次のようになりますか?

+2

同様の状況で私は必要なたびに埋め込みコンポーネントを作成して解放しません。代わりに、私はinit時にそれを作成し、必要に応じて可視/不可視にします。 –

+0

キューから他のメッセージをクリアするにはどうすればよいですか?_いいえ、メッセージは「親」から子供、AFAIKに発送されます。 – Trinidad

+0

CodeInChaosの答えは、Andreasの答えよりも近いです。なぜなら、私は複合コントロール自体に問題がないからです。コントロールの作成と解放の設計が最適ではないことは理解していますが、セルの編集方法が必要なためです。このカスタムコントロールは制約エンジンと結びついており、他のセル値に簡単に再配線されることはありません。私は本当にCM_RELEASEメッセージの後にキューに入れられた可能性のあるメッセージを削除する手段があるかどうかを知りたいと思う。可能であれば、私は確かにApplication.ProcessMessagesを避けたいですが、それは既存のメッセージをすべて消去するという効果があります。 – jchoover

答えて

0

一般に、そのコントロールのイベントハンドラでコントロールを破棄しないでください。

しかし、あなたの関数は、そのコントロールの内部コードから決して呼び出されないプレーンな非仮想メッセージハンドラなので、あなたは大丈夫です。私はスタイルの観点からあまりにも多くを好きではありませんが、あなたのユースケースでは大丈夫だと思います。

しかし、カスタムメッセージはよりクリーンかもしれません。

CM_RELEASEがポストされた後、別のWM_KEY *または同様のメッセージがすべてメッセージキューにポストされている可能性はありますか?

キュー内のメッセージが大きな問題を引き起こす場合は、メッセージを他のスレッドやアプリケーションから投稿できるため、コントロールを安全に破壊することはできません。アプリケーションの正しい機能がすべての場合に処理されるメッセージに依存しないことを確認してください。

+0

可能であればコンポーネントを永続化しますが、このユーザーコントロールは実際には現在のセルを定義するメタデータに基づいて1つ以上の子コントロールを含む複合コントロールです。私が懸念していた唯一の理由は、コントロールがフリーズした後にWM_KEYメッセージがトリガされ、UpdateUIStateコールがSelf(null)でGetParentFormに渡され、コントロールと盲目的にやり取りする渡された。 – jchoover

0

SendMessageはメッセージを送信し、メッセージが返るのを待つので、解放しているコントロールのイベントハンドラでは安全に使用できません。

PostMessageはメッセージを送信し、イベントが終了した後で処理されます(イベントにコードがない場合)。

関連する問題