VC++2005 MFC ダイアログベース
ダイアログBOXにドロップダウン コンボボックスが2個あり、
そのそれぞれに違った色を付けたいと思っています。
IDC_COMBO1 → 赤
IDC_COMBO1 → 緑
-------------------------------------------------------------------------------
-
ComboBox を基本クラスとする
CColorComboBox クラスを新規作成して
WM_CTLCOLOR をオーバーライドして色を付ける事はできたのですが、
それぞれのコンボボックスに違った色を指定する方法がわかりません。
どうしたら良いでしょうか?
------------------------------------------------------------------------------
// CMainDlg.h メインダイアログのヘッダファイル
#include CColorComboBox.h
class CMainDlg : public CDialog
{
CColorComboBox m_combo1;
CColorComboBox m_combo2;
}
// CMainDlg.cpp メインダイアログ
void CMainDlg::DoDataExchange( CDataExchange* pDX )
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_COMBO1,m_combo1);
DDX_Control(pDX, IDC_COMBO2,m_combo2);
}
// CColorComboBox.cpp コンボボックスを基本クラスするクラス
#include CColorComboBox.h
HBRUSH CColorComboBox::OnCtrColor( CDC* pDC,CWnd* pWnd, UINT nCtlColor )
{
HBRUSH hBr = CCOmbobox::OnCtlColor(pDC,pWnd,nCtlColor);
pDC->SetBkColor( RGB( 255, 0, 0) ); //赤
hBr = m_RedBrush; //m_RedBrush.CleateSolidBrush(RGB( 255, 0, 0));
}
間違えて連投してしまいました。
CColorComboBox に文字の色と背景色と、背景色用のブラシを設定する関数と
設定を持てば良いのでは
とおりすがりさんコメントありがとうございます。
2つのコンボボックスの色をそれぞれ違う色に設定しようとしているのですが、
方法がわかりません。
pWnd->GetDlgCtrID()が全部 「1001」 で、
コンボボックスコンボボックスを識別できません。
#include CColorComboBox.h
HBRUSH CColorComboBox::OnCtrColor( CDC* pDC,CWnd* pWnd, UINT nCtlColor )
{
HBRUSH hBr = CCOmbobox::OnCtlColor(pDC,pWnd,nCtlColor);
if(pWnd->GetDlgCtrID() == IDC_COMBO1){
pDC->SetTextColor( RGB( 0, 0, 0) ); //黒文字
pDC->SetBkColor( RGB( 255, 0, 0) ); //赤
hBr = m_RedBrush; //m_RedBrush.CleateSolidBrush(RGB( 255, 0, 0));
}
else if(pWnd->GetDlgCtrID() == IDC_COMBO2){
pDC->SetTextColor( RGB( 0, 0, 0) ); //黒文字
pDC->SetBkColor( RGB( 0, 255, 0) ); //赤
hBr = m_GreenBrush; //m_GreenBrush.CleateSolidBrush(RGB( 0, 255, 0));
}
return hBr;
}
>aetos 2009/07/23(木) 11:04:58
>OnCtlColor の nCtlColor がコントロール ID なので、これでどのコントロールの
>OnCtlColor が呼ばれているのかを識別して処理を分けます。
>…ん? OnCtlColor を CComboBox の派生クラスに実装してるの?
>CMainDlg で処理するなら上記のようになります。
ヘルプを読んだらドロップダウンコンボボックスのリストボックスでは、
OnCtlColorは呼び出されません。
と書いてあったので、オーバーライドしてみました。
>今の形で行くなら、CColorComboBox に「自分の色」を何らかの形で伝えてやればよい
>の
>では。メンバ関数増やすとか。
試行錯誤中ですが、まだうまくいっていません。
> ヘルプを読んだらドロップダウンコンボボックスのリストボックスでは、
> OnCtlColorは呼び出されません。
> と書いてあったので、オーバーライドしてみました
はい。
俺嘘言いました。ごめんなさい。
しかも、nCtlColor はコントロールの ID じゃなくてコントロールのタイプでした。
で、自分でやってみました。
うまくいったので手順を書いておきます。
1:CComboBox から派生した CColorComboBox クラスを作ります。
2:CColorComboBox にメンバ変数 HBRUSH m_hBrush を追加します。
3:CColorComboBox で OnCtlColor をオーバーライドし、nCtlColor が
CTLCOLOR_LISTBOX のときに pDC->SetBkMode( TRANSPARENT ) してから
m_hBrush を返すように書きます。
4:リソースエディタでダイアログ上に配置したコンボボックスを選択して
「変数の追加」をし、CColorComboBox 型のメンバ変数を追加します。
5:ダイアログの OnInitDialog で、CColorComboBox の m_hBrush に
任意の色のブラシを設定します。
コードも載せちゃいますね。
== CColorComboBox.h ==
#pragma once
// CColorComboBox
class CColorComboBox : public CComboBox
{
DECLARE_DYNAMIC(CColorComboBox)
public:
CColorComboBox();
virtual ~CColorComboBox();
protected:
DECLARE_MESSAGE_MAP()
public:
HBRUSH GetBrush(void) const
{
return m_hBrush;
}
void SetBrush(HBRUSH hBrush)
{
DeleteObject( m_hBrush );
m_hBrush = hBrush;
}
private:
afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
HBRUSH m_hBrush;
};
== CColorComboBox.cpp ==
// ColorComboBox.cpp : 実装ファイル
//
#include stdafx.h
#include ColorCombo.h
#include ColorComboBox.h
// CColorComboBox
IMPLEMENT_DYNAMIC(CColorComboBox, CComboBox)
CColorComboBox::CColorComboBox()
: m_hBrush( static_cast< HBRUSH >( GetSysColorBrush(
COLOR_WINDOW ) ) )
{
}
CColorComboBox::~CColorComboBox()
{
}
BEGIN_MESSAGE_MAP(CColorComboBox, CComboBox)
ON_WM_CTLCOLOR()
END_MESSAGE_MAP()
// CColorComboBox メッセージ ハンドラ
HBRUSH CColorComboBox::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CComboBox::OnCtlColor(pDC, pWnd, nCtlColor);
// TODO: ここで DC の属性を変更してください。
// TODO: 既定値を使用したくない場合は別のブラシを返します。
if( nCtlColor == CTLCOLOR_LISTBOX )
{
pDC->SetBkMode( TRANSPARENT );
return m_hBrush;
}
return hbr;
}
== CColorComboDlg.cpp(抜粋) ==
// CColorComboDlg メッセージ ハンドラ
BOOL CColorComboDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// バージョン情報... メニューをシステム メニューに追加します。
// IDM_ABOUTBOX は、システム コマンドの範囲内になければなりません。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX,
strAboutMenu);
}
}
// このダイアログのアイコンを設定します。アプリケーションのメイン ウィ
ンドウがダイアログでない場合、
// Framework は、この設定を自動的に行います。
SetIcon(m_hIcon, TRUE); // 大きいアイコンの設定
SetIcon(m_hIcon, FALSE); // 小さいアイコンの設定
// TODO: 初期化をここに追加します。
m_combo1.SetBrush( CreateSolidBrush( RGB( 255, 0, 0 ) ) );
m_combo2.SetBrush( CreateSolidBrush( RGB( 0, 255, 0 ) ) );
return TRUE; // フォーカスをコントロールに設定した場合を除き、TRUE を
返します。
}
改良しました。
== CColorComboBox.h ==
#pragma once
// CColorComboBox
class CColorComboBox : public CComboBox
{
DECLARE_DYNAMIC(CColorComboBox)
public:
CColorComboBox();
virtual ~CColorComboBox();
protected:
DECLARE_MESSAGE_MAP()
public:
COLORREF GetBackgroundColor() const
{
return m_color;
}
void SetColor( COLORREF color )
{
DeleteObject( m_hBrush );
m_color = color;
m_hBrush = CreateSolidBrush( color );
}
private:
afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
afx_msg HBRUSH CtlColor(CDC* pDC, UINT nCtlColor);
COLORREF m_color;
HBRUSH m_hBrush;
};
== ColorComboBox.cpp ==
// ColorComboBox.cpp : 実装ファイル
//
#include stdafx.h
#include ColorCombo.h
#include ColorComboBox.h
// CColorComboBox
IMPLEMENT_DYNAMIC(CColorComboBox, CComboBox)
CColorComboBox::CColorComboBox()
:
m_color( GetSysColor( COLOR_WINDOW ) ),
m_hBrush( static_cast< HBRUSH >( GetSysColorBrush( COLOR_WINDOW ) ) )
{
}
CColorComboBox::~CColorComboBox()
{
DeleteObject( m_hBrush );
}
BEGIN_MESSAGE_MAP(CColorComboBox, CComboBox)
ON_WM_CTLCOLOR()
ON_WM_CTLCOLOR_REFLECT()
END_MESSAGE_MAP()
// CColorComboBox メッセージ ハンドラ
HBRUSH CColorComboBox::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CComboBox::OnCtlColor(pDC, pWnd, nCtlColor);
switch( nCtlColor )
{
case CTLCOLOR_EDIT:
case CTLCOLOR_LISTBOX:
pDC->SetBkMode( TRANSPARENT );
pDC->SetBkColor( m_color );
return m_hBrush;
}
return hbr;
}
HBRUSH CColorComboBox::CtlColor(CDC* pDC, UINT nCtlColor)
{
switch( nCtlColor )
{
case CTLCOLOR_EDIT:
pDC->SetBkMode( TRANSPARENT );
pDC->SetBkColor( m_color );
return m_hBrush;
}
return NULL;
}
== ColorComboDlg.cpp(抜粋) ==
// CColorComboDlg メッセージ ハンドラ
BOOL CColorComboDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// バージョン情報... メニューをシステム メニューに追加します。
// IDM_ABOUTBOX は、システム コマンドの範囲内になければなりません。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX,
strAboutMenu);
}
}
// このダイアログのアイコンを設定します。アプリケーションのメイン ウィ
ンドウがダイアログでない場合、
// Framework は、この設定を自動的に行います。
SetIcon(m_hIcon, TRUE); // 大きいアイコンの設定
SetIcon(m_hIcon, FALSE); // 小さいアイコンの設定
// TODO: 初期化をここに追加します。
m_combo1.SetColor( RGB( 255, 0, 0 ) );
m_combo2.SetColor( RGB( 0, 255, 0 ) );
return TRUE; // フォーカスをコントロールに設定した場合を除き、TRUE を
返します。
}
書き忘れ。
ON_WM_CTLCOLOR_REFLECT メッセージハンドラを追加するには、クラス ビューで
CColorComboBox が選択されている状態で、プロパティ ウィンドウでメッセージを選択
し、「=WM_CTLCOLOR」を選びます。
頭に = がない方だと OnCtlColor になっちゃいますので注意。
aetosさん丁寧に教えて頂きありがとうございます。
載せて頂いたコードを参考にして
希望していた動作ができました。
サブクラス化がPOINTと考え、その辺を色々調べていたのですが、
色々方法があるのですね!
勉強になりました。
今後ともよろしくお願い致します。