一、新建一个基于对话框的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。我们可以看到,一共输出了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(多字节),菜单栏-项目-属性:更改后点击确定。
效果如下:
联系客服