なぜあなたは、コンポーネントの作成やストリーミング中にハンドルを使用してはなりませんか?
-
06-09-2019 - |
質問
私はSDL_CreateWindowFrom機能を介して、SDLの描画表面をラップするカスタムVCLコントロールを作りたいです。 SDL_CreateWindowFromは、その上に(それはDirectXとOpenGLのを含む利用可能ないくつかのバックエンドを、持っている)既存のHWNDハンドルを取り、高性能なレンダリングコンテキストを置きます。
ヘルプファイルは、「コンポーネントの作成やストリーミング中にHandleプロパティを参照しないでください。」と言いますしかし、それは、なぜ言うことはありません。それはあなたがHandleプロパティにアクセスしようとする最初の時間は、それが有効なハンドルが存在することを確認するためにHandleNeededを呼ぶだろうと述べています。
だから私は2つの質問があります。 1:あなたはコンポーネントの作成中にHandleプロパティを参照してはならない理由は何ですか? 2.コントロールの全体のポイントは、(理想的に)作成/ストリーミング中に行われるべきである初期化を実行することが安全であるとき、初期化するHWNDを要求する描画表面をラップすることですか?
解決
それの中核となるのは、それがパフォーマンスのことです。ストリーミング処理中のため、同様に発生する可能性が潜在的に他の「悪い」の副作用があります。物事は、「半ば建設」であり、通常であることが予想されているすべてのは、おそらくありません。
あなたは「ハンドル」プロパティを参照すると、これはハンドルの作成プロセスを開始します。読み取りハンドルが実際にGetHandleを呼び出すためです。ストリーミング処理でもすぐにこれを行うと、あなたが終わる可能性があり、最高の状態で、低速のストリーミング性能、部分的に構成され、さらに悪化で「ハンドル。」
あなたがプロパティのセッターの中から適切に処理するために参照する必要がある場合は、、ハンドルがHandleAllocatedをチェックすることで作成されているか調べなければなりません、とだけにして、あなたはそれを参照します。あなたは、のSetWindowLong()か何かを呼び出すようにハンドルにはいくつかのフラグの変更を行うために必要な場合、あなたは、「キャッシュ」、そのコンポーネントインスタンスでの状態とはCreateWndをオーバーライドし、その時点でそれらの設定を適用する必要があります。別のオプションは、ストリーミング中(ComponentStateでcsLoadingならば、)ロードされた仮想メソッドが呼び出されるまで、すべてのハンドルへのアクセスを延期することです。
最後に、あなたはあなたのハンドルを再作成を取得する必要があるかもしれない例を認識する必要があります。周囲のフォームまたは親コンポーネントのハンドルが再作成プロセスを通過した場合に発生することがあります。 Windowsのより多くの最近のリリースまでは、いくつかのウィンドウのフラグを変更する唯一の方法は、ハンドルを破棄してのCreateWindowEx()の呼び出しで新しいフラグを再作成することでした。まだこれを行う多くのコンポーネントがあります。あなたは(ControlStateを中csRecreating)をチェックすることにより、再作成状況にいる場合は、知っています。
だから、直接あなたの質問に答えるために、最高の場所は、CreateWndをオーバーライドして、そこに自分の仕事をすることです。ハンドルが作成されるときCreateWndにのみ呼び出されます。適切に設計されたコンポーネントは、示されようとしている直前CreateWndに一つだけのコールを取得する必要があります。
他のヒント
あなたの2つ目の質問に答えるために:のは、TCustomControl は、あなたのコントロールをされたと仮定し、あなたはおそらく、のCreateWindowHandle()のをオーバーライドする必要があります。これは、すべての初期化が正しく新しいウィンドウコントロールに対してハンドルが作成されるたびに繰り返されるという利点があります。これは、ウィンドウを再作成することなく、セットまたはリセットすることはできませんいくつかのウィンドウスタイルフラグを変更することができます。また、それが必要とされていない時にハンドルを解放し、後でそれを再作成することにより、リソースを節約することができない。
また、この質問を参照してください。いただきまし-差-間-createwnd-と-createwindowhandle と何をすべきかについて、より詳細な回答とするとき...