最近练习VC的界面设计,想给Edit的颜色改改,在父对话框的CtlColor函数中可通过if(nCtlColor==CTLCOLOR_EDIT){……}控制,但是由于软件中有多个对话框(20多),所以在每个父对话框都重写CtlColor函数非常麻烦(程序中所有Edit均用同一种颜色,虽然代码完全可以复制,但是觉得这不是一个好方法),于是就想到了重载CEdit类,从CEdit派生了一个CMyEdit类,同时对CEdit的CtlColor函数进行重写,如下:
HBRUSH CMyEdit::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 
{
// HBRUSH hbr = CEdit::OnCtlColor(pDC, pWnd, nCtlColor);

// TODO: Change any attributes of the DC here
//       MessageBox("CTLCOLOR");
pDC->SetBkColor(RGB(255,0,0));
pDC->SetTextColor(RGB(0,255,0));
         CBrush brush;
         brush.CreateSolidBrush(RGB(0,255,0));
return brush;
// TODO: Return a different brush if the default is not desired
// return hbr;
}再对父对话框的Edit控件关联CMyEdit类型的控件成员变量m_MyEdit
然后运行程序,发现所关联CMyEdit变量的控件颜色并无改变,还是原来的白色
于是在CMyEdit::OnCtlColor函数中添加了以个MessageBox,并加一个断点,在CMyEdit::CMyEdit中增加一个断点,调试运行,发现运行时在CMyEdit::CMyEdit中最先停下,继续调试运行,并没有转到CMyEdit::OnCtlColor中,也没有MessageBox窗口出现,就直接出现了父对话框,并且关联CMyEdit的控件颜色是白色的
请大虾们指教下,这么做可以实现Edit控件的颜色控制吗?如果可以,是哪里出了问题?如果不可以,还有别的方法吗?

解决方案 »

  1.   

    你需要添加对=WM_CTLCOLOR消息的处理,注意前面有个=号
      

  2.   

    非常感谢,还没见过=WM_CTLCOLOR这个消息
    按这位大虾说的,添加后函数如下:HBRUSH CMyEdit::CtlColor(CDC* pDC, UINT nCtlColor) 
    {
    // TODO: Change any attributes of the DC here
    pDC->SetBkColor(RGB(255,0,0));
    pDC->SetTextColor(RGB(0,255,0));
    CBrush brush;
    brush.CreateSolidBrush(RGB(0,255,0));
    // TODO: Return a non-NULL brush if the parent's handler should not be called
    return NULL;
    }
    增加断点,调试运行到了这个函数中
    调试运行时无法看到Edit控件的颜色,于是正常运行
    但是正常运行后,发现Edit控件的颜色还是没有改变
    请这位大虾再赐教下。。
      

  3.   

    不好意思,在HBRUSH CMyEdit::CtlColor(CDC* pDC, UINT nCtlColor)函数中最后的return时return错了,问题已解决,谢谢!能不能麻烦告诉下=WM_CTLCOLOR这个消息与WM_CTLCOLOR的区别呢?
      

  4.   

    OnCtlColor一般是修改自己子窗口的颜色。
    而你CMyEdit类没有子窗口,你需要更改的是自己的背景颜色。
    建议响应WM_ERASEBKGND消息。
    重载CMyEdit::OnEraseBkgnd(CDC*)消息响应函数
      

  5.   


    表示是反射消息,就是父窗口收到这个消息后,反射给子窗口处理
    看它的定义ON_WM_CTLCOLOR_REFLECT(),有个REFLECT
      

  6.   

    CMyEdit::OnEraseBkgnd(CDC*)好像只是更改背景颜色,而不能设置字体颜色吧?
      

  7.   

    每个窗口对应一个DC,所有的绘制工作都在改DC上完成。
    我的理解只要改变了DC的字体颜色,同样能完成你的目的。
    你试一试吧
      

  8.   

    如果真的说方便的,最好还是写个CDialog派生类,在类中的处理WM_CTLCOLOR,这样比较方便
      

  9.   

    Windows controls frequently send notification messages to their parent windows. For instance, many controls send a control color notification message (WM_CTLCOLOR or one of its variants) to their parent to allow the parent to supply a brush for painting the background of the control.In Windows and in MFC before version 4.0, the parent window, often a dialog box, is responsible for handling these messages. This means that the code for handling the message needs to be in the parent window's class and that it has to be duplicated in every class that needs to handle that message. In the case above, every dialog box that wanted controls with custom backgrounds would have to handle the control color notification message. It would be much easier to reuse code if a control class could be written that would handle its own background color.In MFC 4.0, the old mechanism still works — parent windows can handle notification messages. In addition, however, MFC 4.0 facilitates reuse by providing a feature called "message reflection" that allows these notification messages to be handled in either the child control window or the parent window, or in both. In the control background color example, you can now write a control class that sets its own background color by handling the reflected WM_CTLCOLOR message — all without relying on the parent. (Note that since message reflection is implemented by MFC, not by Windows, the parent window class must be derived from CWnd for message reflection to work.)http://msdn.microsoft.com/en-us/library/eeah46xd(VS.80).aspx
      

  10.   

    曾经有过这个想法,在Insert->New Class中想建一个派生自CDialog的类CMyDialog,选中CDialog作为基类,但是点击确定时,提示说没有关联对话框ID,就是说自己派生的CDialog类好像必须和一个Dialog模板绑定的,在这个问题上遇到了点困点,能不能指教下?
      

  11.   

    直接从CWnd派生,然后将基类改为CDialog,然后你还需要定义一下CDialog的构造函数。
      

  12.   

    你先把这个类关联到新建的对话框中,再再类申明中把enum{IDD_DIALOG}这句去掉,同时把CxxDlg(CWnd*pParent=NULL)改为CxxDlg(UINT nID,CWnd *pParent =NULL),记得在你要添加的对话框中把CDialog都改为CxxDlg
      

  13.   

    再请教下这位大虾,
    HBRUSH CMyEdit::CtlColor(CDC* pDC, UINT nCtlColor) 
    {
        // TODO: Change any attributes of the DC here
        pDC->SetBkColor(RGB(255,0,0));
        pDC->SetTextColor(RGB(0,255,0));
        CBrush brush;
        brush.CreateSolidBrush(RGB(0,255,0));    
        // TODO: Return a non-NULL brush if the parent's handler should not be called
        return NULL;
    }在这个函数中,当return NULL;时,pDC->SetBkColor(RGB(255,0,0));和pDC->SetTextColor(RGB(0,255,0));似乎都是等于白设了,但是当CBrush brush;  brush.CreateSolidBrush(RGB(0,255,0));      return brush;时却可以实现对Edit控件的颜色控制,这是为什么呢?并且在brush.CreateSolidBrush(RGB(0,255,0));中,不管你选的是什么颜色,最后Edit控件的背景颜色和字体颜色好像只和pDC->SetBkColor(RGB(255,0,0));和pDC->SetTextColor(RGB(0,255,0));这两条语句有关,请问下这里的return是怎么个意思?还有这句注释语句也不太理解// TODO: Return a non-NULL brush if the parent's handler should not be called
    希望多多指教!
      

  14.   

    按我的理解是如果要在消息反射中处理文字和背景颜色,就不要再让父窗口去处理了,返回任意一个非空的画刷句柄就可以让父窗口收不到该消息,这个画刷不用创建,创建了也没什么意义,只要非空就可以了所以你可以直接返回GetStockObject(NULL_BRUSH)。
    如果你返回NULL,那么父窗口的WM_CTLCOLOR就会被调用,而父窗口OnCtlColor如果没有对EDIT控件做处理的话,那就跟什么都没写一样了。