• 締切済み

ダイアログの一部を半透明化する C++(MFC)

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が表示されたり 半透明部分のイベントがとれなかったりするのですが まずは上記の問題を解決してからだと考えています。 まったく違う方法でも良いので、何かアイデアがある方はご教示下さい。よろしくお願いします。

みんなの回答

  • Dodonpa22
  • ベストアンサー率100% (4/4)
回答No.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の引数と同じような機能で、ビットマップの各  ピクセルだけでなくここでも透過情報を設定できますが、今回はここは非透過で設定したほうが  分かりやすいかも。

57s4ge7u
質問者

補足

大変遅くなってしまい申し訳ありません。 回答ありがとうございます。 ご教示頂いた内容を自分なりに解釈して試してみましたが、うまくいきません。 ダイアログ1からダイアログ2を表示させ、ダイアログ2上のピクチャコントロールを半透明化しようとしています。 現象としては、ピクチャコントロールがある位置に画像が表示されるのですが、それ以外の領域が消えてしまいます。タイトルバーなども消えてしまいます。 また半透明化もされていません。 (UpdateLayeredWindowの引数のBLENDFUNCTION構造体でalpha値を設定すれば半透明化はされるのですが) そのままだと何も操作できないのですが、一旦最小化して元のサイズに戻すと、 表示的にはあまり変わらないのですが、表示されている画像の上の方を触ると移動できたり、最小化ボタンや×ボタンを押しているように動作します。 画像で塗りつぶされているのですが、ピクチャコントロールのサイズのフォームができたイメージです。言葉で伝えるのは難しいのですが。 確かにけっこう複雑で全てをここでお聞きするのは難しいと思うのですが、参考サイトなどありましたらご教示頂けますでしょうか? 今更ながらのお願いで申し訳ありませんが、よろしくお願いします。

  • Dodonpa22
  • ベストアンサー率100% (4/4)
回答No.1

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

57s4ge7u
質問者

補足

遅くなってしまいましたが、回答ありがとうございます。 UpdateLayeredWindowというのはあまり知らなかったので調べてみたのですが、 SetLayeredWindowAttributesの代わりに使用するということでしょうか? SetLayeredWindowAttributesより処理が軽いという認識でしたが・・・ 「なぜUpdateLayeredWindowではなくSetLayeredWindowAttributesを使っているのか」 ということでしたら、恥ずかしながらSetLayeredWindowAttributesを 使う方法しか知らなかったためです。。。

関連するQ&A

  • ダイアログボックスについて。

    ダイアログボックスについての質問です。 開発環境はVisual C++ 2005.netでありSDKを利用しています。 ダイアログボックスにPicture Controlを貼り付け、Combo Boxの内容が変わるたびにそのPicture Controlに画像を表示するようなプログラムを作りたいと考えています。 自分が考える手順としてはまずPicture Controlについてサブクラス化を行い、親のダイアログボックスが表示されると同時にPicture ControlのプロシージャでWM_CREATEメッセージを受け取り描画を行う。 そして親のダイアログボックスに貼り付けたCombo Boxの内容が変更された場合に、Picture ControlのウィンドウハンドルにむけてWM_PAINTメッセージを送信する。 こんな手順で行いたいのですが、少し不安な部分が出てきました。 Combo Boxの内容が変更され、Picture Controlのウィンドウハンドルに向けてWM_PAINTメッセージを送信し、Picture ControlプロシージャではWM_PAINTメッセージがきたとき画像の描画を行う場合、このプロシージャではどの画像を描画してよいか不明です。 そのため何番の画像の表示命令が来たのかを示すために、親のダイアログボックスに貼り付けたCombo Boxが変更された場合、Picture Controlに向けてWM_PAINTメッセージと表示画像番号をパラメータとして送信したいのです。 もちろんグローバル変数を用意すれば簡単なのですが、できるだけ使用しないように記述をしたいのです。そこで考えたのが、 SendMessage(GetDlgItem(hDlgWnd, IDC_PICTURE), WM_PAINT, 0, MAKELPARAM(0, number)); このようにnumberをLPARAMの下位ワードとして送信しようと考えました。 このメッセージ送信を行い、Picture ControlプロシージャでWM_PAINTメッセージが到着したとき、LOWORD(lparam)からnumberを取り出す。 実現したい目的のため、このような方法を考えましたが、エラーなく実行できるでしょうか? もしあやしい部分が見つかった場合はアドバイスをお願いします。そしてこの方法よりも簡単に処理できる方法があれば教えていただきたいです。 自分としてはサブクラス化は面倒なので、Picture Controlをオーナードローとして扱う方法も考えましたが、うまく動きませんでしたTT

  • ダイアログボックス・・・・・ bySDK

    現在SDKにて画像処理ソフトを作成しています。もちろん個人にて。 そこで確実にほしい機能”ヒストグラム”の表示を行おうと思ったのですが、問題が起こりました。 目的は”2値化"という処理に伴い、ダイアログボックスに入力した画像のヒストグラムを表示させたいということです。 もちろんヒストグラムは単に白黒だけで表示させたいと思っています。 問題というのはダイアログボックスに任意の図形をどのように描画するかです。ビットマップの描画は以前行ったことがあるのですが、任意の図形は行ったことがありませんでした。 試しに、ダイアログボックスにPicture Controlを貼り付け、そのPicture ControlのデバイスコンテキストをGetDCにより無理やり取得し、そのデバイスコンテキストに直線などの描画を行ってみましたが、表示はされませんでした。(あたりまえかも・・・・) そこでまず、ダイアログボックスに使用するコントロール類は何を設定したらよいか? そして、そのコントロールから取得したデバイスコンテキストに直接描画は可能か? これらの質問に答えられる方はアドバイスをお願いしたいと思います。 よろしくお願いします。

  • CDHtmlDialog で子ダイアログがアクティブになりません

    現在CDHtmlDialogクラスを使って、ダイアログベースのプログラム開発を試みています。開発環境はVisualStudio2008です。 親ダイアログにあるボタンをクリックすると、子ダイアログが親ダイアログに重なる位置に表示され、子ダイアログにあるHTML コントロールのイベント処理等ができるようにしたいのですが、うまくいかず困っています。 子ダイアログの表示まではできたのですが、アクティブになっていないようです。ただ画面に表示されているだけといいますか・・・ 子ダイアログに配置したボタンはクリックできず(カーソルが変わりません)、親ダイアログに配置したボタンはクリックできる、というような状態です。 また、ダイアログの一部が画面外になるように動かしてから元の位置に戻すと、子ダイアログの再描画がされず、その下に隠されていた親ダイアログが出てきてしまいます。 子ダイアログのプロパティは Style:子、Border:なし にしています。 手順は、 1.親ダイアログのOnInitDialogで子ダイアログをCreate。MoveWindowで位置調整。子ダイアログはShowWindowで非表示にする。 2.親ダイアログのボタンをクリックすると、子ダイアログをShowWindowで表示させる。 としています。 CDialogで同じ方法でやっていたときは何も問題なかったのですが・・・ CDHtmlDialogに関する情報はあまり出回っていないようで、こちらに質問させていただきました。 説明が分かり難い点もあるかと思いますが、ご教示よろしくお願いいたします。

  • ダイアログでの再描画

    こんばんわ。 ダイアログに2つBMPが表示されているとします。 説明上、AとBとします。 なんらかの処理後、 Aを表示したまま。 Bを表示されないよう消去したいのです。 コントロールを指定して描画をできないものでしょうか? 現在、 Invalidate(FALSE); GetDlgItem(IDCxxx)->Invalidate(TRUE); と、AもBも消去されないように残した後、 Bだけ再描画させて表示しないようにさせたのですが、 うまく動きません・・・。 宜しくお願いします。 Win98、VC++6.0、MFCで作成してます。

  • VC++のダイアログボックスに絵を描くには?

    VC++初心者なんですが、画像処理関係のプログラムをVC++で作っています。で、子ウィンドウに表示されている画像のRGBそれぞれのヒストグラムをダイアログボックスに表示したいのですが、ダイアログボックスに絵(グラフ)を描く方法がわかりません。どういう手順でやればいいですか?エディットボックスにGDIとかで絵を描くことは可能なんですか?またはピクチャーボックスですか?

  • FlexGridの一部のみ表示を更新したいのです。

    FlexGridの一部のみ表示を更新したいのです。 VisualStudio2003、C#でWindowsアプリを開発しています。 一覧表示にFlexGridを使用しています。 とある処理の中で、FlexGridに表示するデータの一部が変更されるので、 その変更値を画面に反映するためにFlexGridを再描画する必要があり、 Refreshしているのですが、一覧の再描画に時間がかかっています。 変更のあったセル、または1行のみ、再描画(表示を更新)する事は可能でしょうか?

  • VC++でタスクバーに表示させない方法。(非MFC)

    VC++6.0 で常駐アプリの開発をしているのですが、 MFCを使わずにダイアログを作成し、 タスクトレイにアイコンを表示するのはできたのですが、タスクバーには表示が残ってしまいます。 タスクバーに表示させない方法を教えてください。 よろしくお願いします。

  • MFC 6.0 VC++ で、処理が重くなります。

    MFC 6.0 VC++ で、処理が重くなります。 上記の環境でダイアログベースで処理を作成しています。 画面の再描画を繰り返すと、同じ処理をしていても処理が重くなります。 OnPainメッセージを受け取ったあとに、描画処理を行っているのですが、画面に表示に必要な計算も描画時に行っています。 仮想ウィンドウに描画してBitBlt()を実行する方法も試しましたが、ちらつかなくなった代わりに余計に処理が重くなりました。 描画のやり方が問題なのか、内部の処理が問題なのか良く分からないのですが、何か良い方法が無いでしょうか? そもそもダイアログベースで画像処理をしているのが間違いな気もするのですが・・・。

  • MFC XPでのTextOutのボヤケについて

    はじめまして。 質問させてください。 CImageを使用して OnPaint( )でBMP画像を描画するアプリを作成しております。 仕様といたしまして ダイアログのDC部にBMPを全体に描画して RGB( 255, 255, 255 )を透明化(背景が完全に見える)する ようにしております。 OnInitDialog( )で透過、透明処理をしています。 OnPaint( )で PaintDC PDC; //背景を透過 PDC.SetBkMode( TRANSPARENT ); PDC.SetTextColor( RGB( 255, 0, 0 ) ); PDC.SetBkColor( RGB( 255, 255, 255 ) ); PDC.TextOutW( 100, 100, _T( "TEST" ) ); 上記のように実装して、EXEで実行して確認しますと Windows2000の場合、正常に文字(TEST)が赤字で描画されるのですが WindowsXPの場合、赤字で描画されるのですが文字の周りがぼやけてしまいます。 イメージとしては文字描画部分が 2000の場合、BMP表示 XPの場合、JPG表示 のようになります。 これは仕様なのでしょうか? それとも何かコードレベルで解決できるのでしょうか? お詳しい方がおりましたらご教授お願いいたします。 よろしくお願いいたします。

  • IEのダイアログが隠れてしまう

     IEを使っているとページが替わるときに確認のダイアログが出たりしますが、そのダイアログがウィンドウの下に出るらしく、画面上に表示されません。  そのことに気が付けば、タスクバーのIEをクリックすればダイアログが前に表示されるのでページの表示が出来ますが、それに気付かないとIEがフリーズした様に全く反応しなくなります。(当然です)  確実に『ダイアログが一番上』に表示されるようにするにはどうしたらいいのでしょうか。 よろしくお願いします。    Me:最新パッチでアップデート済み  IE:5.5SP2(6をマイクロソフトでインストールしようとしても出来なかった/原因不明との事)  

専門家に質問してみよう