• 【VS开发】VS2010 MFC中控件、对话框等背景颜色动态修改的方法


    【VS开发】VS2010 MFC中控件、对话框等背景颜色动态修改的方法

    标签(空格分隔):【VS开发】


    声明:引用请注明出处http://blog.csdn.net/lg1259156776/


    说明:最近突发奇想想完成两件新的人机交互工程,一个是基于眼动仪的眼动控制,另一个是基于camera的手动控制,最直观的方法就是使用slider滑块,眼睛或手左右动,slider也左右动,眼睛或手上下动,slider也上下动,并配合着对话框的背景颜色的改变,来增强互动的效果,本文所记录的就是其中关于动态修改控件颜色的方法。


    首先说基于眼动仪的眼动控制,由于提供的matlab接口开发起来比较方便,所以采用了matlab gui设计,而在matlab中关于dialog或者某个控件的颜色的修改简直太方便了,如下一行代码就可以搞定:

    set(handles.axes1,'color',[0.5,0.5,0.5])
    

    所以matlab gui设置各种事情是比较方便的。毕竟是解释性开发语言。

    由于好久没有在VS2010下开发对话框的应用,以前都是在VC下开发dialog程序,在VS2010上开发的多是具有office风格的文档应用,但是曾经积累的经验是非常有帮助的。就不多说如何按照经验一步一步的尝试了,直接给出最终的较为简单的解决方案:

    通过类向导,或者手动添加消息:WM_CTLCOLOR,其消息响应函数为:

    afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
    

    在每个控件开始绘制之前,都会向其父窗口发送WM_CTLCOLOR通告消息,在该消息的处理函数中,可以设置控件显示文本的前景色、背景色以及字体。该消息处理函数还要求返回一个画刷的句柄,用于在控件具体的绘制之前擦除其客户区。当窗口重绘时,也会重新绘制每个控件,从而分别调用该函数,这就给了动态修改控件相关颜色特性的机会。

    比如在对应的控件下的OnCtrColor函数中写入:

    pDC->SetTextColor(RGB(255, 0, 0));    //设置文本前景色   
    pDC->SetBkColor(RGB(255, 255, 255));  //设置文本背景色   
    pDC->SetBkMode(TRANSPARENT);          //TRANSPARENT或OPAQUE   
    pDC->SelectObject(...)  
    

    就可以实现修改某个控件的绘制属性。具体的实现可以参考下面的一段代码:

    //   
    //m_font1与m_font2为CTestDlg的成员,类型为CFont   
    //   
    BOOL CTestDlg::OnInitDialog()  
    {  
            ......  
        // TODO: Add extra initialization here   
            m_font1.CreatePointFont(120,  TEXT("Impact"));   
            m_font2.CreatePointFont(120,  TEXT("Arial"));  
            ......  
    }  
    
    HBRUSH CTestDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)  
    {  
        HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);  
    
        // TODO:  Change any attributes of the DC here   
        if (nCtlColor == CTLCOLOR_STATIC)  
        {  
            switch (pWnd->GetDlgCtrlID())  
            {  
            case IDC_STATIC_1:  
                pDC->SetTextColor(RGB(255, 0, 0));  
                pDC->SetBkColor(RGB(255, 255, 255));  
                pDC->SetBkMode(TRANSPARENT);  
                pDC->SelectObject(&m_font1);  
                return (HBRUSH)::GetStockObject(BLACK_BRUSH);  
                break;  
            case IDC_STATIC_2:  
                pDC->SetTextColor(RGB(255, 255, 0));  
                pDC->SetBkColor(RGB(255, 255, 255));  
                pDC->SelectObject(&m_font2);  
                return (HBRUSH)::GetStockObject(BLACK_BRUSH);  
                break;  
            default:  
                break;  
            }  
        }  
    
        // TODO:  Return a different brush if the default is not desired   
        return hbr;  
    }  
    

    当然如果是修改dialog的属性,可以直接在最后的return上返回一个画刷,填充dialog的背景颜色。

    上面这种方法只是一种静态的修改,因为所有的属性都是一次性设定好了,似乎没有根据情况进行改变的可能。这个是时候就要用到上面所提到的一种方法:强迫窗口重绘,可用的函数有Invalidate()和UpdateWindow(),两者的区别如下:

    Invalidate在消息队列中加入一条WM_PAINT消息,其无效区为整个客户区。而UpdateWindow直接发送一个WM_PAINT消息,其无效区范围就是消息队列中WM_PAINT消息(最多只有一条)的无效区。效果很明显,调用Invalidate之后,屏幕不一定马上更新,因为WM_PAINT消息不一定在队列头部,而调用UpdateWindow会使WM_PAINT消息马上执行的,绕过了消息队列。如果你调用Invalidate之后想马上更新屏幕,那就加上UpdateWindow()这条语句。

    那么剩下的事情就比较简单了,可以通过设置一个COLORREF m_BrushColor;的成员变量,在调用窗口重绘的函数之前,修改m_BrushColor,然后在OnCtlColor函数中将画刷的颜色创建为该m_BrushColor:

    m_bkBrush.DeleteObject();
    m_bkBrush.CreateSolidBrush(m_BrushColor); //创建一把黄色的背景刷子
    

    下面是我所修改的函数:

    HBRUSH ChandControllerDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
    {
        HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
    
        // TODO:  在此更改 DC 的任何特性
        if((CTLCOLOR_SCROLLBAR)&&(pWnd->GetDlgCtrlID()==IDC_SLIDER1 || pWnd->GetDlgCtrlID()==IDC_SLIDER2))
        {
    
            //此处设置背景的颜色
            m_bkBrush.DeleteObject();
            m_bkBrush.CreateSolidBrush(RGB(0,255,0)); //创建一把黄色的背景刷子
            return m_bkBrush;       
        }
    
        if((CTLCOLOR_BTN)&&(pWnd->GetDlgCtrlID()==IDOK))
        {
            m_bkBrush.DeleteObject();
            m_bkBrush.CreateSolidBrush(RGB(0,255,0)); //创建一把黄色的背景刷子
            return m_bkBrush; 
        }
        m_bkBrush.DeleteObject();
        m_bkBrush.CreateSolidBrush(m_BrushColor); //创建一把黄色的背景刷子
    
        // TODO:  如果默认的不是所需画笔,则返回另一个画笔
        return m_bkBrush;
    }
    

    通过上面的函数,可以实现对对话框中的控件或者对话框的背景颜色进行动态修改。


    2015-10-31 调试记录 张朋艺

  • 相关阅读:
    ioremap函数
    kmalloc、kzalloc和vmalloc
    C语言 snprintf函数
    C语言 memset函数
    消息队列
    mount -a
    linux系统查看服务状态和启动停止服务
    Java中创建对象的内存图
    Java中数组在内存中的图解
    socket编程(Java实现)
  • 原文地址:https://www.cnblogs.com/huty/p/8518969.html
Copyright © 2020-2023  润新知