プロが教えるわが家の防犯対策術!

WindowsXP、VisualStudio2010でC++(MFC)で開発を行っています。

ダイアログの一部を半透明化したいのですが、どうすれば実現できるでしょうか?


なんとかやってみたのですが、途中で手詰まりしていまい質問した次第です。

以下、詳細と挑戦した内容です。
ダイアログ1からダイアログ2を表示し(モーダレス)、
ダイアログ2の一部を半透明化したいです。
半透明化と、一部を透明化するの両立はできなそうだったため、
ダイアログ2を2枚のダイアログで表示しようとしています。

ダイアログ2にはピクチャコントロールが一つあり、そこをRGB(1,0,0)などで塗り、
SetLayeredWindowAttributesでRGB(1,0,0)を透明化しています。
ダイアログ2の裏に表示するダイアログ3は画像(自分で描画しています)を表示し
SetLayeredWindowAttributesを使い半透明化しています。

OnMoveやOnWindowPosChangingで使い一見、うまく表示できているのですが、
ダイアログ1を選択したときに、裏にあるべきはずのダイアログ3がダイアログ1の前に
表示されてしまいます。
というよりもダイアログ2以外のウィンドウがアクティブになると、
ダイアログ3がそれより前に来てしまいます。


他にもタスクバーにダイアログ3が表示されたり
半透明部分のイベントがとれなかったりするのですが
まずは上記の問題を解決してからだと考えています。

まったく違う方法でも良いので、何かアイデアがある方はご教示下さい。よろしくお願いします。

A 回答 (2件)

>UpdateLayeredWindowというのはあまり知らなかったので調べてみたのですが、


>SetLayeredWindowAttributesの代わりに使用するということでしょうか?
はい。SetLayeredWindowAttributesを使用して、UpdataLayeredWindowを使うと
失敗します。

>SetLayeredWindowAttributesより処理が軽いという認識でしたが・・・
軽いかどうかはわかりませんが、Set~~はウィンドウ全体のα値や透過色を
設定するのに対して、Update~~は一部を半透明にしたり(もちろん全体も可能)、
細かいレイヤードな作業ができます。ただし、当然のことながら複雑かつめんどくさいです。

>「なぜUpdateLayeredWindowではなくSetLayeredWindowAttributesを使っているのか」
>ということでしたら、恥ずかしながらSetLayeredWindowAttributesを
>使う方法しか知らなかったためです。。。
細かいやり方はとても書ききれませんので、ざっくりとしたとこだけ。
1.CBitmap::CreateCompatibleBitmapでビットマップと、CDC::CreateCompatibleDCでスクリーン互換のDCを作って、半透明したい部分をBitBltで転送する。

2.1で出来たビットマップは透過情報がないDDBビットマップなので、透過情報をもつDIBSectionビットマップに変換する。手順は次のとおり。

2a.CreateDIBSectionでDIBSectionビットマップを作ってそのハンドルを取得する(戻値)。その際、
  第二引数はBITMAP型へのポインタを指定するが、これでは透過情報があるピットマップは作成
  できないので、BITMAPV5HEADER型へのポインタを指定すること。

2b.CreateDIBSectionの第四引数に作られた透過情報入力可能なビットマップのピクセルの配列ができているので、GetDIBitsで1.のDDBビットマップを転送する。

3.これで透過情報をもったDIBSectionビットマップが出来たので、2bの第四引数で受け取ったピクセルの透明度を任意に設定して、CDC::CreateCompatibleDCでスクリーン互換のDCを作ってSelectObjectでこのビットマップハンドルを結びつける。

4.これで準備ができたので、3.で取得したCDCへのポインタをCWnd::UpdateLayeredWindowの第四引数
 に指定する。第一引数はスクリーンのDCへのポインタを指定して、第二、第三引数は透過させたい
 左上の位置をスクリーン座標で、その幅、高さ(つまり、作ったビットマップの幅、高さと同じ)を
 指定。第五引数は、作ったビットマップをどこからウィンドウに表示するかを指定するので、余分な
 ビットマップを作っていなかったら(0, 0)位置からレイヤ表示する。

 最後の3つの引数はSetLayeredWindowAttributesの引数と同じような機能で、ビットマップの各
 ピクセルだけでなくここでも透過情報を設定できますが、今回はここは非透過で設定したほうが
 分かりやすいかも。

この回答への補足

大変遅くなってしまい申し訳ありません。
回答ありがとうございます。

ご教示頂いた内容を自分なりに解釈して試してみましたが、うまくいきません。
ダイアログ1からダイアログ2を表示させ、ダイアログ2上のピクチャコントロールを半透明化しようとしています。

現象としては、ピクチャコントロールがある位置に画像が表示されるのですが、それ以外の領域が消えてしまいます。タイトルバーなども消えてしまいます。
また半透明化もされていません。
(UpdateLayeredWindowの引数のBLENDFUNCTION構造体でalpha値を設定すれば半透明化はされるのですが)

そのままだと何も操作できないのですが、一旦最小化して元のサイズに戻すと、
表示的にはあまり変わらないのですが、表示されている画像の上の方を触ると移動できたり、最小化ボタンや×ボタンを押しているように動作します。
画像で塗りつぶされているのですが、ピクチャコントロールのサイズのフォームができたイメージです。言葉で伝えるのは難しいのですが。


確かにけっこう複雑で全てをここでお聞きするのは難しいと思うのですが、参考サイトなどありましたらご教示頂けますでしょうか?
今更ながらのお願いで申し訳ありませんが、よろしくお願いします。

補足日時:2012/03/21 16:02
    • good
    • 0

いろいろ工夫されているみたいですが、



>まったく違う方法でも良いので、何かアイデアがある方
アイディアではないですが、UpdateLayeredWindowは使えない状況ですか?

この回答への補足

遅くなってしまいましたが、回答ありがとうございます。

UpdateLayeredWindowというのはあまり知らなかったので調べてみたのですが、
SetLayeredWindowAttributesの代わりに使用するということでしょうか?

SetLayeredWindowAttributesより処理が軽いという認識でしたが・・・


「なぜUpdateLayeredWindowではなくSetLayeredWindowAttributesを使っているのか」
ということでしたら、恥ずかしながらSetLayeredWindowAttributesを
使う方法しか知らなかったためです。。。

補足日時:2012/02/07 14:48
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています