(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。

  1. HBRUSH CMFC_NovelDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
  2. {
  3. HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
  4. //pDC为当前进入函数的DC
  5. //pWnd为当前进入函数的控件的句柄(MFC中的控件均为CWnd派生而来)
  6. //nCtlColor当前进入函数的控件风格
  7. COLORREF color1 = RGB(0, 0, 255);
  8. HBRUSH hbrush1 = CreateSolidBrush(color1);
  9. COLORREF color2 = RGB(0, 255, 0);
  10. HBRUSH hbrush2 = CreateSolidBrush(color2);
  11. //判断当前控件的类型
  12. switch (nCtlColor)
  13. {
  14. case CTLCOLOR_EDIT://若传入进来的控件是EDIT
  15. {
  16. //获取Edit父控件的ID
  17. UINT nParentID = pWnd->GetParent()->GetDlgCtrlID();
  18. if (IDC_COMBO1 == nParentID)
  19. {
  20. pDC->SetBkColor(color1);
  21. return hbrush1;
  22. }
  23. }
  24. default:
  25. break;
  26. }
  27. return hbr;
  28. }


效果如图

四、设置List Box的颜色

看了上面的代码,举一反三,大家觉得List Box部分的代码可以这样写:

  1. case CTLCOLOR_LISTBOX:
  2. {
  3. //获取Edit父控件的ID
  4. UINT nParentID = pWnd->GetParent()->GetDlgCtrlID();
  5. if (IDC_COMBO1 == nParentID)
  6. {
  7. pDC->SetBkColor(color2);
  8. return hbrush2;
  9. }
  10. }break;

事实上,这个想法是好的,但是运行,你会发现报错,因为Combo Box中的List Box与Combo box不是直接的父子关系,无法通过这个方式实现。

于是博主灵机一动,只要是个控件,他肯定有ID,只是ID我们不知道是多少而已,那么我们是否可以打印出所有进入case CTLCOLOR_LISTBOX:中的ID呢。

于是有了如下代码:

  1. case CTLCOLOR_LISTBOX:
  2. {
  3. TRACE1("ID == %d\r\n", pWnd->GetDlgCtrlID());
  4. }break;

为了对比,我们在对话框上再添加一个list box和一个edit, F5运行,在输出窗口查找查看所有的ID。

需要注意的是,Combo的ListBox是需要点击下拉按钮,加载出来,才有输出,所以可以在点击下拉按钮之后查看最后一个输出ID,该ID即为Combo的ID。

我们可以看到,一共输出了2个ID,1002属于后添加的listbox(右键ID名称转到定义即可看到,直接打开Resource.h也可)。

那么,Combo的list box ID为1000。

那么我们可以写代码了

  1. HBRUSH CMFC_NovelDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
  2. {
  3. HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
  4. //pDC为当前进入函数的DC
  5. //pWnd为当前进入函数的控件的句柄(MFC中的控件均为CWnd派生而来)
  6. //nCtlColor当前进入函数的控件风格
  7. COLORREF color1 = RGB(0, 0, 255);
  8. HBRUSH hbrush1 = CreateSolidBrush(color1);
  9. COLORREF color2 = RGB(0, 255, 0);
  10. HBRUSH hbrush2 = CreateSolidBrush(color2);
  11. if (pWnd->GetDlgCtrlID() == IDC_COMBO1)
  12. {
  13. pDC->SetBkColor(color1);
  14. return hbrush1;
  15. }
  16. //判断当前控件的类型
  17. switch (nCtlColor)
  18. {
  19. case CTLCOLOR_EDIT://若传入进来的控件是EDIT
  20. {
  21. //获取Edit父控件的ID
  22. UINT nParentID = pWnd->GetParent()->GetDlgCtrlID();
  23. if (IDC_COMBO1 == nParentID)
  24. {
  25. pDC->SetBkColor(color1);
  26. return hbrush1;
  27. }
  28. }break;
  29. case CTLCOLOR_LISTBOX:
  30. {
  31. if (1000 == pWnd->GetDlgCtrlID())
  32. {
  33. pDC->SetBkColor(color2);
  34. return hbrush2;
  35. }
  36. else
  37. {
  38. //用于和Combo Box中的ListBox区分,查看是不是只单独设置了Combo的下拉框为color2
  39. pDC->SetBkColor(color1);
  40. return hbrush1;
  41. }
  42. }break;
  43. default:
  44. break;
  45. }
  46. return hbr;
  47. }


效果如下:

上述代码的好处是,控件的ID是固定不变的,指定ID之后,只有该ID才会设置背景色。

还有另外一种写法:

  1. case CTLCOLOR_LISTBOX:
  2. {
  3. if (IDC_LIST1 != pWnd->GetDlgCtrlID())
  4. {
  5. pDC->SetBkColor(color2);
  6. return hbrush2;
  7. }
  8. }

这种写法的弊端就是,后期若存在很多单独的ListBox,均要添加到if中进行判定。但添加大量背景色相同的Combo时,又可以省去不少时间。可根据自己的需求不同来使用不同的写法。

五、优化处理(仅限Multi Byte)

我们看到Edit与Combo之间还有白边,这是为什么?因为当前工程字符集是Unicode.

在多字节字符集下,这个效果是可以被优化的(多字节下可以处理很多控件的颜色,而Unicode下不支持,要注意!)

将工程字符集切换到Multi Byte(多字节),菜单栏-项目-属性:更改后点击确定。


效果如下:

(0)

相关推荐