The Delphi Bug List

Entry No.
103
VCL - 一般 - コントロール - TWinControl
RecreateWnd は、ウィンドウハンドルを信頼する API ルーチンにとって危険である
1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 4.03 5.0 5.01 6.0 6.01 6.02 Kylix 1.0
Gotcha Gotcha Gotcha Gotcha Gotcha Gotcha Gotcha Gotcha Gotcha Gotcha Gotcha Gotcha Gotcha Gotcha N/A
解説
TWinControl から派生する全てのコンポーネントは、カレントウィンドウを破棄して再生成するメソッド RecreateWnd を持っています。これは特定の状況、例えば生成された後にウィンドウのスタイルが変更されたような場合に必要とされます。しかしながら、ある種の Windows の関数はウィンドウハンドルに依存しており、ウィンドウの再生成はそのような関数が正しく動作することを妨げます。例えば、関数 DragAcceptFiles はウィンドウハンドルを受け取り、ファイルマネージャからのファイルのドロップを受け取れるように、そのウィンドウを登録します。もしそのウィンドウが再生成されてしまうと、DragAcceptFiles に渡したハンドルは無効になってしまいます。
解決策 / 回避方法
これは、非常に大きな gotcha、というほどのバグではありません。私の考える最良の解決方法は、RecreateWnd メソッドをオーバーライドする新しい派生コンポーネントを作成し、inherited が呼ばれた後にウィンドウハンドルを再登録することです。この回避策の明らかな欠点は、問題が発生するかもしれない全てのコンポーネントに対してこれを行わなければならないことです。

もう1つの候補は、単純に、コンポーネントウィンドウの再生成が必要になるようなことは何もしないことです。ウィンドウを再生成しなければならない状況:

  • ボーダースタイル(BorderStyle)の変更
  • エディットコントロールのプロパティ CharCase または HideSelection または OEMConvert の変更
  • メモコントロールのプロパティ Alignment または ScrollBars の変更
  • リストボックスコントロールのプロパティ Sorted または Style の変更
  • リストボックスコントロールのプロパティ Alignment の変更
  • チェックボックスコントロールのプロパティ Ctl3D の変更

  • これを完全なリストだとは思わないでください。これは私が STDCTRLS.PAS から見つけたもののおよそ半分にすぎません。このことは、これらの状況を避けるよりも、RecreateWnd をオーバーライドする新しい派生コンポーネントを作るべきだということを、良く表していると思います。
    Latest update of this entry: before April 1998
    本家 The Delphi Bug List のエントリーはこちら
    The Delphi Bug List 日本語訳 へ