4

SDL_CreateWindowFrom 関数を介して SDL レンダリング サーフェスをラップするカスタム VCL コントロールを作成したいと考えています。SDL_CreateWindowFrom は、既存の HWND ハンドルを取得し、高性能レンダリング コンテキスト (DirectX や OpenGL を含むいくつかのバックエンドが利用可能) をそれに配置します。

ヘルプファイルには、「コンポーネントの作成中またはストリーミング中にハンドル プロパティを参照しないでください」と記載されています。しかし、それは理由を述べていません。最初に Handle プロパティにアクセスしようとすると、有効なハンドルが存在することを確認するために HandleNeeded が呼び出されます。

そこで、質問が 2 つあります。1: コンポーネントの作成中に Handle プロパティを参照してはならない理由は何ですか? 2. コントロールのポイント全体が、HWND の初期化を必要とするレンダリング サーフェスをラップすることである場合、(理想的には) 作成/ストリーミング中に行われるべき初期化を安全に実行できるのはいつですか?

4

2 に答える 2

15

本質的には、それはパフォーマンスの問題です。ストリーミング プロセス中に発生する可能性のある他の「悪い」副作用が潜在的に存在します。物事は「建設の途中」にあり、通常そこにあると期待されるすべてのものは、おそらくそうではありません.

「Handle」プロパティを参照すると、ハンドル作成プロセスが開始されます。これは、Handle を読み取ると実際に GetHandle が呼び出されるためです。ストリーミング プロセスでこれを行うのが早すぎると、せいぜいストリーミング パフォーマンスが遅くなり、最悪の場合、部分的に構成された "ハンドル" になる可能性があります。

プロパティ セッター内から適切にハンドルを参照する必要がある場合は、HandleAllocated を確認してハンドルが作成されているかどうかを確認してから、それを参照する必要があります。SetWindowLong() などを呼び出すなど、ハンドルにフラグの変更を加える必要がある場合は、その状態をコンポーネント インスタンスに「キャッシュ」してから、CreateWnd をオーバーライドして、その時点でそれらの設定を適用する必要があります。もう 1 つのオプションは、Loaded 仮想メソッドが呼び出されるまで、ストリーミング中 (ComponentState で csLoading の場合) のすべてのハンドル アクセスを延期することです。

最後に、ハンドルを再作成する必要がある場合があることに注意する必要があります。これは、周囲のフォームまたは親コンポーネントのハンドルが再作成プロセスを経た場合に発生する可能性があります。Windows の最近のリリースまで、一部のウィンドウ フラグを変更する唯一の方法は、ハンドルを破棄し、CreateWindowEx() 呼び出しで新しいフラグを使用して再作成することでした。まだこれを行う多くのコンポーネントがあります。(ControlState の csRecreating) を確認することで、再作成状況にあるかどうかがわかります。

したがって、質問に直接答えるには、CreateWnd をオーバーライドしてそこで作業を行うのが最善の方法です。CreateWnd は、ハンドルが作成されたときにのみ呼び出されます。適切に設計されたコンポーネントは、表示される直前に CreateWnd への呼び出しを 1 回だけ取得する必要があります。

于 2009-02-24T17:59:33.080 に答える
3

2 番目の質問に答えるには: コントロールがTCustomControlであると仮定すると、おそらくCreateWindowHandle()をオーバーライドする必要があります。これには、コントロールの新しいウィンドウ ハンドルが作成されるたびに、すべての初期化が正しく繰り返されるという利点があります。これにより、ウィンドウを再作成しないと設定またはリセットできないいくつかのウィンドウ スタイル フラグを変更できます。また、必要のないときにハンドルを解放し、後で再作成することにより、リソースを節約することもできます。

于 2009-02-24T17:48:47.880 に答える