何時もお世話になります。
ブロック崩しの色付けにAboutDialogBoxの背景色をセットしようとして、以下のコードを
CAboutDlgにOnEraseBkgndメッセージハンドラを付け加えて、以下のコードを書きました。
BOOL CAboutDlg::OnEraseBkgnd(CDC* pDC)
{
// TODO: この位置にメッセージ ハンドラ用のコードを追加するかまたはデフォル
トの処理を呼び出してください
CBrush backBrush(RGB(200,20,200));
CBrush *oldBrush = pDC->SelectObject(&backBrush);
CRect rect;
pDC->GetClipBox(&rect);
pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(),
PATCOPY);
pDC->SelectObject(oldBrush);
return CDialog::OnEraseBkgnd(pDC);
}
しかし、背景色はdefaultのままで変化ありません。ちなみにreturn文の前にAfxMessageBox()
を置けば背景色は思いどおりに変わりますが、無限ループに入ります。
どなたかご教示下さい。
書き忘れました。申し訳ありません。
Win2K, VC++6.0, MFCです。
> return CDialog::OnEraseBkgnd(pDC);
return TRUE;
でよいのでは?
HBRUSH BOOL CAboutDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
COLOREF backColor=RGB(200,20,200);
CBrush backBrush(backColor);
if (nCtlColor == CTLCOLOR_DLG || nCtlColor == CTLCOLOR_STATIC)
{
pDC->SetBkColor(backColor);
return (HBRUSH) backBrush.GetSafeHandle();
}
return CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
}
小悪魔恭子様、
ありがとうございます。仰る通りreturn TRUE;に変更するとうまくいきました。ただ、Dialog
の中のstatic_textについては背景色は変わりません。
123様、
ご教授ありがとうございます。
試みましたが、WM_CTLCOLORのメッセージがAboutDlgに送られないのか、ダイアロクもテキス
トも背景色は変化しませんでした。どのようにすればWM_CTLCOLORのメッセージがAboutDlgを
開いた時に送られるようになるでしょうか?
小悪魔恭子様、
今、発見しました。
要するにdefaultでメッセージハンドラの最後に付け加えられる
return CDialog::OnEraseBkgnd(pDC);
を実行させずに
return FALSE;でも
return TRUE;でも
何でも良いから戻せば良いようです。
結果は同じになります。
何だか良く分かりません。
要するに
return CDialog::OnEraseBkgnd(pDC);
を返せば、折角その前に行った背景描画処理が無駄になって、派生元クラスのdefaultの関数が
実行されてしまうからでしょうか?
CDialog::OnEraseBkgnd(pDC);
これを実行していることが、デフォルトの処理を実施させていることになります。
> CBrush backBrush(backColor);
>
> if (nCtlColor == CTLCOLOR_DLG || nCtlColor == CTLCOLOR_STATIC)
> {
> pDC->SetBkColor(backColor);
> return (HBRUSH) backBrush.GetSafeHandle();
> }
これでは、関数から出た時にブラシが削除されてしまいます。
backBrushを関数より寿命の長いスコープに置いてみてください。
(メンバ変数、クラス変数、グローバル変数など)
dairygoods様、
ご指導のようにbackBrushをAboutDlgのメンバー変数に持っていきましたが、ビルドすると
BlockHitGame.obj : error LNK2001: 外部シンボル "protected: int __thiscall
CAboutDlg::OnEraseBkgnd(class CDC *) (?
OnEraseBkgnd@CAboutDlg@@IAEHPAVCDC@@@Z) は未解決です
のようなエラーがでてしまいます。
何のことだかさっぱり分かりません。
また、123様のコードでもreturnでbackBrushへのハンドルを返すことになるので、backBrush
が関数を出たときに削除されるとは思えないのですが。
ご指導宜しくお願いします。
> のようなエラーがでてしまいます。
CBrushの件とは関係ないと思います。
OnEraseBkgnd()関数を削除したが、MESSAGE_MAPが
そのままとかではないですか。
> 関数を出たときに削除されるとは思えないのですが。
イメージだけで捉えずに、疑問に思った点は
テストプログラムを作って確かめてみると良いでしょう。
HBRUSH GetHandle() {
CBrush brush(RGB(0,0,0));
return (HBRUSH)brush.GetSafeHandle();
}
...
HBRUSH hbr = GetHandle();
LOGBRUSH lb;
int ret = ::GetObject(hbr, sizeof(lb), &lb);
if (ret == 0) {
// hbrは削除されている
} else {
// hbrは削除されていない
}
dairygoods様、
仰る通り、小生が勝手にハンドラをコメントアウトして、MESSAGE_MAPに残ったままだからでし
た。そこの部分もコメントアウトするとOKでした。
しかし、未だ問題があります。
やはりAbouDlgの背景色は変化しません。残念ながらSPY++などの使い方も分からないのです
が、きっとWM_CTLCOLORメッセージがAboutDlgに届いていないのだと思います。
> 残念ながらSPY++などの使い方も分からないのです
> が、きっとWM_CTLCOLORメッセージがAboutDlgに届いていないのだと思います。
SPY++など使えなくても簡単に調べられます。
OnCtlColor()関数の中にブレークポイントを設置して
デバッガで実行するだけです。
で、本当に呼ばれていない場合ですが、
MESSAGE_MAPにON_WM_CTLCOLOR()はありますか?
dairygoods様、
そうですね。馬鹿でした。ブレークポイントを
BRUSH CAboutDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
// TODO: この位置で DC のアトリビュートを変更してください
// TODO: デフォルトのブラシが望みのものでない場合には、違うブラシを返してく
ださい
if (nCtlColor==CTLCOLOR_DLG||nCtlColor==CTLCOLOR_STATIC) {
pDC->SetBkColor(backColor);
return (HBRUSH) backBrush.GetSafeHandle();
}
return hbr;
}
の中のifの頭に設定しましたところ、ちゃんとAboutDlgを表示しようとするとそのブレークポ
イントで停止しました。ということはちゃんとこのハンドラが呼ばれているということですね。
では、どうして思いどおりに行かないのでしょうか?
backBrushは、作っていますか?
(CBrush::CreateSolidBrushを呼んでいますか?)
akey様、
ご指摘ありがとうございます。
CBrushのコンストラクタを調べたのですが、
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
backColor = RGB(200,100,100);
CBrush backBrush(backColor);
}
でCreateSolidBrushが呼ばれているように思います。
ですから、backBrushはちゃんと作成されていると思いますが......