(6条消息) [VC/MFC]Combo控件背景色更改(非自绘)
一、新建一个基于对话框的MFC工程并在Dialog上添加一个Combo Box
这个步骤,即使是新手,也会吧。如果不会请自行百度。
二、重载OnCtlColor()函数
方法一:点击“类视图”,找到向导创建的窗口类,右键,属性。
方法二:点击“资源视图”,选中整个对话框,右键,属性。
此时,界面会自动跳转到*Dlg.cpp的OnCtlColor()中。我们可以开始写代码了。
三、设置Combo Box编辑框的颜色
不修改Combo Box的ID时,ID默认为IDC_COMBO1 。
Combo Box可以简单的看成三部分组成:Edit、Button以及List Box
那么Eidt就可以认为是Combo Box的子控件。我们虽然不知道Edit的ID,但是知道Combo Box的ID。
HBRUSH CMFC_NovelDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
//pDC为当前进入函数的DC
//pWnd为当前进入函数的控件的句柄(MFC中的控件均为CWnd派生而来)
//nCtlColor当前进入函数的控件风格
COLORREF color1 = RGB(0, 0, 255);
HBRUSH hbrush1 = CreateSolidBrush(color1);
COLORREF color2 = RGB(0, 255, 0);
HBRUSH hbrush2 = CreateSolidBrush(color2);
//判断当前控件的类型
switch (nCtlColor)
{
case CTLCOLOR_EDIT://若传入进来的控件是EDIT
{
//获取Edit父控件的ID
UINT nParentID = pWnd->GetParent()->GetDlgCtrlID();
if (IDC_COMBO1 == nParentID)
{
pDC->SetBkColor(color1);
return hbrush1;
}
}
default:
break;
}
return hbr;
}
效果如图
四、设置List Box的颜色
看了上面的代码,举一反三,大家觉得List Box部分的代码可以这样写:
case CTLCOLOR_LISTBOX:
{
//获取Edit父控件的ID
UINT nParentID = pWnd->GetParent()->GetDlgCtrlID();
if (IDC_COMBO1 == nParentID)
{
pDC->SetBkColor(color2);
return hbrush2;
}
}break;
事实上,这个想法是好的,但是运行,你会发现报错,因为Combo Box中的List Box与Combo box不是直接的父子关系,无法通过这个方式实现。
于是博主灵机一动,只要是个控件,他肯定有ID,只是ID我们不知道是多少而已,那么我们是否可以打印出所有进入case CTLCOLOR_LISTBOX:中的ID呢。
于是有了如下代码:
case CTLCOLOR_LISTBOX:
{
TRACE1("ID == %d\r\n", pWnd->GetDlgCtrlID());
}break;
为了对比,我们在对话框上再添加一个list box和一个edit, F5运行,在输出窗口查找查看所有的ID。
需要注意的是,Combo的ListBox是需要点击下拉按钮,加载出来,才有输出,所以可以在点击下拉按钮之后查看最后一个输出ID,该ID即为Combo的ID。
我们可以看到,一共输出了2个ID,1002属于后添加的listbox(右键ID名称转到定义即可看到,直接打开Resource.h也可)。
那么,Combo的list box ID为1000。
那么我们可以写代码了
HBRUSH CMFC_NovelDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
//pDC为当前进入函数的DC
//pWnd为当前进入函数的控件的句柄(MFC中的控件均为CWnd派生而来)
//nCtlColor当前进入函数的控件风格
COLORREF color1 = RGB(0, 0, 255);
HBRUSH hbrush1 = CreateSolidBrush(color1);
COLORREF color2 = RGB(0, 255, 0);
HBRUSH hbrush2 = CreateSolidBrush(color2);
if (pWnd->GetDlgCtrlID() == IDC_COMBO1)
{
pDC->SetBkColor(color1);
return hbrush1;
}
//判断当前控件的类型
switch (nCtlColor)
{
case CTLCOLOR_EDIT://若传入进来的控件是EDIT
{
//获取Edit父控件的ID
UINT nParentID = pWnd->GetParent()->GetDlgCtrlID();
if (IDC_COMBO1 == nParentID)
{
pDC->SetBkColor(color1);
return hbrush1;
}
}break;
case CTLCOLOR_LISTBOX:
{
if (1000 == pWnd->GetDlgCtrlID())
{
pDC->SetBkColor(color2);
return hbrush2;
}
else
{
//用于和Combo Box中的ListBox区分,查看是不是只单独设置了Combo的下拉框为color2
pDC->SetBkColor(color1);
return hbrush1;
}
}break;
default:
break;
}
return hbr;
}
效果如下:
上述代码的好处是,控件的ID是固定不变的,指定ID之后,只有该ID才会设置背景色。
还有另外一种写法:
case CTLCOLOR_LISTBOX:
{
if (IDC_LIST1 != pWnd->GetDlgCtrlID())
{
pDC->SetBkColor(color2);
return hbrush2;
}
}
这种写法的弊端就是,后期若存在很多单独的ListBox,均要添加到if中进行判定。但添加大量背景色相同的Combo时,又可以省去不少时间。可根据自己的需求不同来使用不同的写法。
五、优化处理(仅限Multi Byte)
我们看到Edit与Combo之间还有白边,这是为什么?因为当前工程字符集是Unicode.
在多字节字符集下,这个效果是可以被优化的(多字节下可以处理很多控件的颜色,而Unicode下不支持,要注意!)
将工程字符集切换到Multi Byte(多字节),菜单栏-项目-属性:更改后点击确定。
效果如下: