ラジオボタンの透過

[戻る]
ebimayo 2006/03/30(木) 10:36:55
いつもお世話になりっぱなしなebimayoです
色々調べて、過去ログ見たりしてもどうしてもわからなかったので質問させてください


<<やろうとしている事>>
1.ダイアログの上にCtaticを派生したクラスにBitBltでビットマップを描画する
2.1のクラスを親とするCFrameWndの派生クラスを作成する
3.2のクラスの背景としてBitBltでビットマップを描画する。
4.2のクラスを親とするCButton::Createで動的に作成したラジオボタンを配置
5.3で描画しているビットマップがラジオボタンの隙間(?)から見えるような
  感じにラジオボタンを透過させたい
(最終的にやりたくて悩んでいるのは 5 の部分です)


<<実現のために試した方法と結果>>
1.CFrameWndの派生クラスでWM_CTLCOLORを以下のように処理するようにした
  HBRUSH CXXXFrameWnd::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 
  {
      HBRUSH hbr = CFrameWnd::OnCtlColor(pDC, pWnd, nCtlColor);
      if(nCtlColor==CTLCOLOR_STATIC){
          pDC->SetBkMode(TRANSPARENT);
          return (HBRUSH)::GetStockObject(NULL_BRUSH);
      }
      return hbr;
  }

この結果として、ラジオボタンは透過されずにラジオボタンの領域は背景が
白っぽい色で表示されました。

以下の情報なども参考にしましたが、出来ている人と出来ていない人がいるようで
http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200511/05110002.txt
http://forums.belution.com/ja/vc/000/209/78.shtml


気になったのでVC++6.0(Enterprise Edition)でダイアログベース(MFC)の
新規プロジェクトを作成し、以下のように試しました。
1.ダイアログにエディタでピクチャーボックスとラジオボタンを重なるように貼る
2.ピクチャーボックスを四角に変更する(ラジオボタンが透過出来てるか見るため)
3.<<実現のために試した方法と結果>>と同じ処理を追加

実行した結果、ラジオボタンの透過が上手くいきました。


さらに気になったので元の環境(Microsoft Visual C++ 2005)で
ダイアログベース(MFC)の新規ソリューションを作成し、上記の上手く透過出来た
方法と同じように試しました。

実行した結果、ラジオボタンの背景は灰色になり透過が出来ませんでした。

以上の結果からVC++6.0とVC++2005で何か動きが違ってきています。


<<知りたいこと>>
1.VC++2005でラジオボタンを透過させることは可能か?
2.透過可能であればその方法はどのようにすればいいのか?
3.VC++6.0とVC++2005で何故このように動きが違うのか?


いつも説明下手で長くなってすいません。
以上、宜しくお願いします。

開発環境
Microsoft WindowsXP(SP2)
Microsoft Visual C++ 2005
  ダイアログベースアプリケーション(MFC)

ebimayo 2006/04/03(月) 10:49:10
追記

未だにMicrosoft Visual C++ 2005では透過がうまくいきませんが、
VC++6.0(Enterprise Edition)とMicrosoft Visual C++ 2005で試した
単純なラジオボタンの透過処理をMicrosoft Visual C++ .NET2003でも
同様に処理を書いて試してみました。

実行した結果、ラジオボタンの透過が上手くいきました。

シロート 2006/04/03(月) 12:52:53
手元にVc6と2005があったので単純なラジオボタンの
透過処理をやってみたらできましたよ。

1.ダイアログアプリ作成
2.ピクチャ四角形背景白にラジオボタンのっける
3.CButtonのサブクラス作ってラジオにくっつける
4.CtlColorでNULLブラシ返す

環境は同じく
Microsoft WindowsXP(SP2)
Microsoft Visual C++ 6.0
Microsoft Visual C++ 2005
  ダイアログベースアプリケーション(MFC)
です。

ebimayo 2006/04/03(月) 14:45:05
シロートさん回答ありがとうございます。

いつも回答いただくときに自分の理解力の無さで返信するのが遅くなります。

> 3.CButtonのサブクラス作ってラジオにくっつける

 この部分がよくわからなかったのですが、
 CButtonの派生クラスを作ってそのクラスにサブクラス化したラジオボタン
 を割り当てるということでよかったでしょうか?
 自分の解釈で以下のようにサブクラス化しました。

  m_Radio1.SubclassDlgItem(IDC_RADIO1,this);
   ↑             ↑   ↑ 
   1             2   3 
1.CButtonの派生クラスの宣言
2.ダイアログに貼り付けているラジオボタンのID
3.ダイアログ自身
(1は class CRadio : public CButton で派生したCRadioです)

CButtonを派生したCRadioの.hファイルに
    afx_msg HBRUSH CtlColor(CDC*,UINT);

.cppファイルに
    BEGIN_MESSAGE_MAP(CRadio, CButton)
        ON_WM_CTLCOLOR_REFLECT()
    END_MESSAGE_MAP()

    HBRUSH CRadio::CtlColor(CDC* pDC, UINT nCtlColor){
        pDC->SetBkMode(TRANSPARENT);
        return (HBRUSH)::GetStockObject(NULL_BRUSH);
    }

としてVC++6.0とVC++2005の両方でそれぞれ実行してみましたが、
VC++6.0では透過処理が出来ていましたが、
VC++2005では透過しませんでした。


同じことをしてシロートさんの環境では透過できているのか、
もしくは、私のやり方がシロートさんのやり方と違っているのか
教えていただければ幸いです。

シロート 2006/04/03(月) 15:34:22
同じやり方のようです。
うっかりm_Radio1がCButtonになってるとか
IDC_RADIO1が別のコントロールのIDだったとかはないですよね?
それでないとしたらわかりません…

ebimayo 2006/04/03(月) 15:51:15
シロートさん何度もありがとうございます。

m_Radio1とIDC_RADIO1を再確認しましたが、間違いありませんでした。

今は試すための新規に作成したソースで、余分なコードや
コントロールは貼り付けていないので予想外なところの処理が
影響してることも考えにくいです。


VC++6.0と2003で透過出来るのに2005だけダメとは・・・
他にも同じような現象が出ている方がいたら教えていただければ幸いです。

自分なりに考えた一つの回避策としてラジオボタンになってくる箇所を
全て自分でDrawしてあげるようにしようかと思います。
(ラジオボタンの○枠とか、チェック時のマークとか全てDraw)

標準のコントロールを出来るだけ使いたかったのですが、現状こうするしか
方法が思いつきません。最初の質問と変わってきてしまっているのですが、
良い回避策を知っている方がいたら教えてもらえないでしょうか?


以上、宜しくお願いします。

シロート 2006/04/03(月) 16:13:57
テーマをクラシックスタイルにしてると問題が起こらないようです。
WindowsXPスタイルにしたら同じ現象が起こりました。
テーマがらみの問題かな…どこかで見た気がしますがど忘れした…

ebimayo 2006/04/03(月) 16:52:56
シロートさん回答ありがとうございます。

こちらでもテーマをクラシックスタイルにして実行してみたところ
透過処理がうまくいきました。

しかし、実行する環境を全てクラシックスタイルにするというのは
今のところ不可能らしいです。
テーマ絡みのようなので、VC++のコード以外(VSなどの関連ファイル?)
でも何か回避出来る方法がないか調べてみようと思います。

これだけに時間も取れず中々調査が進みませんが、
分ったことがあれば逐次書き込んでいこうと思います。

また、これらの情報を知っている方がいましたら教えてもらえないでしょうか?

以上、宜しくお願いします。

シロート 2006/04/03(月) 17:00:44
SetWindowThemeでコントロール個別に設定できるみたいですよ。
見た目が変わってしまいますけど。

ebimayo 2006/04/03(月) 17:48:09
[[解決]]
シロートさんありがとうございます。

教えていただいた関数を使用して以下のようにすることで
クラシックスタイルとXPスタイルに切り替えることができました。

クラシックスタイル
    ::SetWindowTheme(m_Radio1.m_hWnd, TEXT (" "), TEXT (" "));

XPスタイル
    ::SetWindowTheme(m_Radio1.m_hWnd, NULL, NULL);


これで解決チェックを付けさせていただきます。

ただ、気になるのがXPスタイルで透過は不可能なのかどうかです。
上記の処理で回避できましたが、今後どうなるか分からないので
引き続き時間があれば調べてみようと思います。

古いスレッドには追加発言できません。