プロパティシートで追加した画面の背景色について

[戻る]
2015/01/27(火) 23:39:52
プロパティシートで表示する画面の背景色を変えたいのですが、
OnCtlColorで変更をするとタブの外側やボタンの周りは色が変えられたのですが
タブの右側の空白部分の色が変えられません。

■・・・タブ
□・・・色が変わらない空白部分

■■□□□□□□□
|----------------|
|      画面      |
|                |
|----------------|


ここの色を変えるにはどうすれば良いのでしょうか?
現在のコードはこんな感じで書いてます。

CBrush m_brush;
m_brush.CreateSolidBrush( RGB(255,  0,  0) );

〜〜〜〜

HBRUSH CMyPropSheet::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
    HBRUSH hbr = CPropertySheet::OnCtlColor(pDC, pWnd, nCtlColor);
    
    if (nCtlColor == CTLCOLOR_DLG || nCtlColor == CTLCOLOR_BTN)
    {
        pDC->SetBkColor( RGB(255,  0,  0) );
        hbr = m_brush;
    }
    return hbr;
}


Windows7、VS2012、MFC

2015/01/28(水) 19:31:29
試していませんので、憶測で申し訳ないですが
OnEraseBkgndはどうでしょうか。

OnEraseBkgndを捕まえて、そこで引数のpDCで好みの背景色を塗る形になると思います。

2015/01/29(木) 14:36:55
ありがとうございます。

OnEraseBkgndも試してみましたが、結果はOnCtlColorと同じでした。
タブの右側だけ、何故か色を変える事ができません・・・

2015/01/29(木) 18:33:15
こちらでも試しました。
確かにOnCtlColorでもOnEraseBkgndでも、タブの右側は色変更出来ませんね。

これは結局、表示されているタブはCTabCtrlであり、CTabCtrlはタブ右側の色が変更出来ないためです。
幸いCPropertySheet::GetTabControlにより、CTabCtrlのポインタが取得出来ますので
後は煮るなり焼くなり好きにできます。

パッと思いつくのは
@タブをオーナードロー化して、タブ及びタブの右側全てを自前のコードにより描画する。
 背景を変えたいだけなのに描画コードを全て書くデメリットは有りますが何でも出来ます。

Aカスタムドローを用い、ピンポイントで描き換えます。
 ただ、こちらは実現可能かはわかりません。(したことが無いので...)

B別コントロールを使用する
 「背景色を変更したい」という要件と「タブ右側が描画出来ない」という現象がぶつかるなら
 別コントロールを使った方が早い場合もあります。

 例えば、VC2008 SP1以降に追加されたCMFCPropertySheet及びPageなら、見た目をタブコントロール形式だけでなく
 リスト形式なども選べて、リスト形式なら常に四角です。
 「変更出来ない背景が存在しない」という事になります。

以上、ざっと思いついた限り書いてみました。
参考になれば幸いです。

2015/02/02(月) 23:38:39
試していただいてありがとうございます。

通常の方法では変更不可なのですか。

知識不足ですが、オーナードローにチャレンジして実装してみたいと思います。

タブの部分をサブクラス化してDrawItem()でオーナードローを
行う事になると思いますが、CTabCtrlで取得したポインタを
サブクラス化って可能なんでしょうか?
ボタンや既存のクラスをサブクラス化したことはあるのですが、
ポインタをサブクラス化した事は無くて・・・・

それともサブクラス化ではない方法でオーナードローするんでしょうか?
知識が無くてすみません。宜しくお願いいたします。

2015/02/03(火) 15:24:39
>タブの部分をサブクラス化してDrawItem()でオーナードローを
>行う事になると思いますが、CTabCtrlで取得したポインタを
>サブクラス化って可能なんでしょうか?
これについては可能です。
私の理解では、CTabCtrlがウィンドウである限りSubclassWindow関数などでサブクラス化可能という事になります。

>それともサブクラス化ではない方法でオーナードローするんでしょうか?
具体的な話をしますと、自前のプロパティクラスを用意します。(CMyPropetySheetなど)
CMyPropetySheetでOnInitDialogをオーバーライドし、GetTabControl()した結果に
ModifyStyle等でTCS_OWNERDRAWFIXEDスタイルを付加します。

これでCMyPropetySheetでWM_DRAWITEMをキャッチできるようになります。
(MFC風にいうと、OnDrawItem関数ですかね)
後はWM_DRAWITEMをキャッチし、オーナードローにより自由に描画をすれば完成です。
描画したいタブコントロールのオーナーである、ダイアログ(ここではPropetySheet)で描画するのでオーナードロー、という事なのでしょう。

これに対し、タブコントロールをサブクラス化して、タブクラス内でWM_DRAWITEMを処理するのを
(私個人は)セルフドローと呼んでいます。
こちらは「WM_PAINTを捕まえて描画する方法に比べmstateが取れるなどのメリット」がありますし
クラス化してしまえば色んな場所でインスタンス化しやすいですし、オーナードロー、セルフドロー、一長一短かと思います。


自己流のコードもありますので、参考にならない箇所もありますが
助けになれば幸いです。

2015/02/04(水) 00:47:28
なるほど、オーナードローの意味を良く理解していませんでした。
自分で描画する=オーナードローだとばかり・・・
勉強になります。今回はオーナードローで対応しようと思います。

教えていただいた方法で、
OnDrawItem()は動作するようになったのですが、
追加しているタブの情報しか取れず、まだ背景の描画ができていません。

現在はタブを二つ追加しているのですが、
OnDrawItemは2回しかコールされません。
タブの右側の背景のDRAWイベントは飛んでこないのでしょうか?

※下記で、タブ本体の色は変えられました

CBrush m_brush;
m_brush.CreateSolidBrush( RGB(255,  0,  0) );

〜〜〜〜

HBRUSH CMyPropSheet::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDIS)
{
    CDC *dc = CDC::FromaHandle(lpDIS->hDC);

    dc->FillRect(&lpDIS->rcItem, &m_brush);
    dc->SetBkColor( RGB(255,  0,  0) );

    CPropertySheet::OnDrawItem(nIDCtl, lpDIS);
}

2015/02/04(水) 01:05:21
2回しかコールされない、では無く
2種類の値しか入ってこない、でした。

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