2

私が書いたものではないプログラムがあります。私はそのソースを持っておらず、そのプログラムの開発者は独自に開発しています。彼は私にそのプログラムのHWNDHINSTANCEハンドルをくれました。

win32APIを使用して、彼のウィンドウに子ウィンドウを作成しました。

最初に必要なのは、この子ウィンドウの一部の領域を透明にし、他の領域を不透明にすることです (ゲームのヘッドアップ ディスプレイ (HUD) など)。これにより、ユーザーは両方のウィンドウで物事を見ることができます。

2 番目に必要なことは、すべての入力を親ウィンドウに送信することです。私の子ウィンドウは入力を必要としません。

WS_EX_TRANSPARENTペインターアルゴリズムのように、最後に子を描画させるだけであることを私は知っています。

WS_EX_LAYERED子ウィンドウなので使えません。

ps

私はいたるところを見てきましたが、インターネット上で同様の質問がありましたが、解決策は見つかりませんでした.

実際、これはそのゲームの HUD のようなものです。マルチスレッドの複雑さのため、他の多くの理由で親ウィンドウに直接描画することはできません。

- 編集 - - - - - - - - - - - - - -

私はまだそれに取り組んでいます。皆様からのアドバイスを参考に色々と試しています。結合して機能する方法、または機能directXと組み合わせる方法はありますか? それがうまくいくと思います。現在、すべてのものを子ウィンドウとレイヤード ウィンドウとしてテストしています。SetWindowRgn()directxBitBlt()

4

3 に答える 3

3

友人たち、ついに私はそれを実現するためにいくつかのクレイジーなことをしました。ただし、描画に DirectX を直接使用するなど、あまり効率的ではありません。

私が反対するもの:

  • 使用済み(WS_EX_TRANSPARENT | WS_EX_LAYERED | WS_EX_ TOOLWINDOW)_()CreateWindowEx
  • ウィンドウの作成後、ウィンドウ スタイルから削除され、拡張ウィンドウ スタイルから(WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE)も削除されます。(WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE | WS_EX_APPWINDOW)
  • これにより、境界線のないウィンドウが表示され、タスクバーにも表示されます。また、ヒットテストは、ウィンドウの背後にあるものに渡されます。
  • 他のウィンドウのウィンドウ プロシージャをサブクラス化し、
    • WM_CLOSE、 、またはをそれぞれウィンドウWM_DESTROYに送信しますWM_CLOSEWM_DESTROY
    • WM_SIZEWM_MOVE、他のウィンドウに従ってウィンドウのサイズを変更して移動する
    • WM_LBUTTONUPWM_RBUTTONUPWM_MBUTTONUP、自分のウィンドウを一番上に持ってきて、他のウィンドウにフォーカスしたままにして、自分のウィンドウが他のウィンドウの後ろに隠れないようにする
  • DirectX デバイスに 2 つのパスを持たせました。
    • 最初のパスでは、白い背景の上にすべての要素を黒で描画し、バックバッファ データを別のサーフェスにコピーします (したがって、白黒のバイナリ イメージが得られます)。
    • 2 番目のパスでは、通常通り描画します。
  • 関数を使用して、その白黒の表面を読み取ってウィンドウを透明にし続けるために、別のスレッドが作成されSetWindowRgn()ます。

これは完全に機能しています。唯一のことは、物事を透明にするのがあまり得意ではないということです。

もう 1 つの問題は、描画されたオブジェクトにアルファ ブレンディングを与えることです。

ただし、この関数を使用して合計アルファ (透明度) を簡単に設定できますSetLayeredWindowAttributes()

皆さんが提供してくれたすべての助けに感謝します。ご覧のとおり、皆さんが私に言ったことはすべて使用され、彼らは私を導きました。:)

残念なことに、効率の問題からこの方法を使用しないことにしました :(

しかし、多くのことを学び、素晴らしい経験になりました。そして、それが私にとって重要なすべてです:)

ありがとうございました :)

于 2012-05-30T05:24:20.117 に答える
2

Windows 8 以降WS_EX_LAYERED子ウィンドウに使用できます。

以前のバージョンのウィンドウをサポートするには、レベル レイヤード ウィンドウをポップアップ (クロムなし) として作成し、それがゲーム ウィンドウの適切な位置に配置されるようにします。ほとんどのユーザーは、作業中のウィンドウを常に移動するわけではありません。そのため、親ウィンドウの移動を監視し、HUD の位置を変更する必要がありますが、これはショー ストッパーにはなりません。

フォーカス (子ウィンドウの場合) やアクティブ化 (ポップアップの場合) を取得しない方が興味深いですが、それでも実行可能です:- オペレーティング システムは、実際にはフォーカスまたはアクティブ化を自動的に割り当てません。クリックされたウィンドウに - Windows WindowProc は、 を呼び出すか、またはそれ自体のバリアントを呼び出すことにより、常にフォーカスまたはアクティベーションを取得しSetFocusます。ここで重要なことは、すべてのマウス メッセージと非クライアント マウス メッセージを DefWindowProc に渡さずに消費する場合、クリックの結果として、HUD がゲーム ウィンドウからアクティブ化またはキーボード フォーカスを盗むことは決してないということです。SetActiveWindowSetForegroundWindow

ポップアップ ウィンドウまたは別のスレッドのウィンドウとして、ウィンドウ プロシージャが取得するマウス メッセージを手動で処理し、それらをゲーム ウィンドウにポストする必要がある場合があります。それ以外の場合、 with に応答するWM_NCHITTESTHTTRANSPARENT(達成される効果と同様の効果WS_EX_TRANSPARENT)、システムがターゲットを見つけるまでマウス メッセージをスタックに渡し続ける可能性があります。

于 2012-05-09T16:02:55.243 に答える
1

を使用して、親ウィンドウに穴を開けることができますSetWindowRgn

また、自分のウィンドウではないからといって、レイヤード ウィンドウにできないわけではありません。

http://msdn.microsoft.com/en-us/library/ms997507.aspx

最後に、サブクラス化を使用して別のウィンドウを制御できます。基本的には、Wndproc の代わりに自分の Wndproc を置き換えて、処理したいメッセージを処理し、残りを元の wndproc に渡します。

于 2012-05-09T12:43:08.873 に答える