zoukankan      html  css  js  c++  java
  • WM_CTLCOLOR消息 .

    参考文章:白乔原创:VC之美化界面篇

            在每个控件开始绘制之前,都会向其父窗口发送WM_CTLCOLOR通告消息,在该消息的处理函数中,可以设置控件显示文本的前景色、背景色以及字体。该消息处理函数还要求返回一个画刷的句柄,用于在控件具体的绘制之前擦除其客户区。

            WM_CTLCOLOR映射消息处理函数为afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)。
        常用代码为:

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

            简单示例如下:

    1. //   
    2. //m_font1与m_font2为CTestDlg的成员,类型为CFont   
    3. //   
    4. BOOL CTestDlg::OnInitDialog()  
    5. {  
    6.         ......  
    7.     // TODO: Add extra initialization here   
    8.         m_font1.CreatePointFont(120,  TEXT("Impact"));   
    9.         m_font2.CreatePointFont(120,  TEXT("Arial"));  
    10.         ......  
    11. }  
    12.   
    13. HBRUSH CTestDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)  
    14. {  
    15.     HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);  
    16.   
    17.     // TODO:  Change any attributes of the DC here   
    18.     if (nCtlColor == CTLCOLOR_STATIC)  
    19.     {  
    20.         switch (pWnd->GetDlgCtrlID())  
    21.         {  
    22.         case IDC_STATIC_1:  
    23.             pDC->SetTextColor(RGB(255, 0, 0));  
    24.             pDC->SetBkColor(RGB(255, 255, 255));  
    25.             pDC->SetBkMode(TRANSPARENT);  
    26.             pDC->SelectObject(&m_font1);  
    27.             return (HBRUSH)::GetStockObject(BLACK_BRUSH);  
    28.             break;  
    29.         case IDC_STATIC_2:  
    30.             pDC->SetTextColor(RGB(255, 255, 0));  
    31.             pDC->SetBkColor(RGB(255, 255, 255));  
    32.             pDC->SelectObject(&m_font2);  
    33.             return (HBRUSH)::GetStockObject(BLACK_BRUSH);  
    34.             break;  
    35.         default:  
    36.             break;  
    37.         }  
    38.     }  
    39.   
    40.     // TODO:  Return a different brush if the default is not desired   
    41.     return hbr;  
    42. }  
    //
    //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;
    }
    


            说明一

    OnCtlColor中的nCtlColor可为:
        CTLCOLOR_BTN       Button control
        CTLCOLOR_DLG       Dialog box
        CTLCOLOR_EDIT      Edit control
        CTLCOLOR_LISTBOX    List-box control
        CTLCOLOR_MSGBOX     Message box
        CTLCOLOR_SCROLLBAR  Scroll-bar control
        CTLCOLOR_STATIC     Static control
    

            可见,WM_CTLCOLOR可作用于按钮控件CButton、编辑框控件CEdit、ListBox控件、Static控件、滚动条控件,也可作用于对话框本身。
            注意:前面讲WM_CTLCOLOR为通告消息,也即是子控件发送给父窗口的,但对于对话框本身,它能收到nCtlColor为CTLCOLOR_DLG的WM_CTLCOLOR消息,这是自身发给自身的,显然,这时不是通告消息。

    示例:

    1. HBRUSH CTestDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)  
    2. {  
    3.     HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);  
    4.   
    5.     // TODO:  Change any attributes of the DC here   
    6.     if (nCtlColor == CTLCOLOR_DLG)  
    7.         return (HBRUSH)::GetStockObject(BLACK_BRUSH);  
    8.     else  
    9.         pDC->SetTextColor(RGB(255, 0, 0));  
    10.   
    11.     // TODO:  Return a different brush if the default is not desired   
    12.     return hbr;  
    13. }  
    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_DLG)
    		return (HBRUSH)::GetStockObject(BLACK_BRUSH);
    	else
    		pDC->SetTextColor(RGB(255, 0, 0));
    
    	// TODO:  Return a different brush if the default is not desired
    	return hbr;
    }
    


        说明二
    
        OnCtlColor消息里面的处理对PushButton是不起作用的,由说明一中的示例效果也可以看出,而对CheckBox和RadioButton是OK的。附上CSDN给出的解释:
        Buttons with the BS_PUSHBUTTON, BS_DEFPUSHBUTTON, or BS_PUSHLIKE styles do not use the returned brush. Buttons with these styles are always drawn with the default system colors. Drawing push buttons requires several different brushes-face, highlight, and shadow-but the WM_CTLCOLORBTN message allows only one brush to be returned. To provide a custom appearance for push buttons, use an owner-drawn button.
        所以,对PushButton只能将其设置为owner-drawn button,然后响应控件通告消息WM_DRAWITEM来处理,该消息的响应函数原型为afx_msg void OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)。
    

        
        说明三:对ComboBox控件的应用
    
    ComboBox控件包含一个EditBox,当单击展开的时候,会出现一个ListBox列出所有的项目,注意,这时ListBox控件的父窗口不是这个ComboBox,而是ComboBox的父窗口。
        所以,如果要在代码中设置某个ComboBox所显示文字的字体颜色为红色(EditBox以及下拉ListBox中的文字),假设该ComboBox的ID为IDC_COMBO,则使用如下代码将无任何作用。
    1. if (pWnd->GetDlgCtrlID() == IDC_COMBO)  
    2. {  
    3.     pDC->SetTextColor(RGB(255, 0, 0));  
    4. }  
    if (pWnd->GetDlgCtrlID() == IDC_COMBO)
    {
        pDC->SetTextColor(RGB(255, 0, 0));
    }
    
    EditBox以及下拉ListBox中的文字颜色均没有改变。
        以下对话框中有两个ComboBox控件m_combo1,m_combo2。现要使m_combo1中显示的文字颜色为红色,而m_combo2为默认。代码如下
    
    1. HBRUSH CTestDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)  
    2. {  
    3.     HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);  
    4.   
    5.     // TODO:  Change any attributes of the DC here   
    6.   
    7.     //对m_combo1的EditBox(该EditBox的父窗口为m_combo1)   
    8.     if (nCtlColor == CTLCOLOR_EDIT  
    9.         && pWnd->GetParent()->GetDlgCtrlID() == m_combo1.GetDlgCtrlID())  
    10.     {  
    11.         pDC->SetTextColor(RGB(255, 0, 0));  
    12.     }  
    13.   
    14.     //对m_combo1下拉的ListBox   
    15.     if (nCtlColor == CTLCOLOR_LISTBOX  
    16.         && m_combo1.GetParent()->GetDlgCtrlID() == pWnd->GetParent()->GetDlgCtrlID())  
    17.     {  
    18.         //获取ListBox和m_combo1的屏幕坐标范围   
    19.         RECT rectListBox;  
    20.         RECT rectComboBox;  
    21.         pWnd->GetWindowRect(&rectListBox);  
    22.         m_combo1.GetWindowRect(&rectComboBox);  
    23.         //如果该ListBox刚好在m_combo1的下面,则是单击m_combo1产生的下拉ListBox   
    24.         if (rectListBox.left == rectComboBox.left  
    25.             && rectListBox.top == rectComboBox.bottom)  
    26.         {  
    27.             pDC->SetTextColor(RGB(255, 0, 0));  
    28.         }  
    29.     }  
    30.   
    31.     // TODO:  Return a different brush if the default is not desired   
    32.     return hbr;  
    33. }  
    HBRUSH CTestDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
    {
    	HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
    
    	// TODO:  Change any attributes of the DC here
    
    	//对m_combo1的EditBox(该EditBox的父窗口为m_combo1)
    	if (nCtlColor == CTLCOLOR_EDIT
    		&& pWnd->GetParent()->GetDlgCtrlID() == m_combo1.GetDlgCtrlID())
    	{
    		pDC->SetTextColor(RGB(255, 0, 0));
    	}
    
    	//对m_combo1下拉的ListBox
    	if (nCtlColor == CTLCOLOR_LISTBOX
    		&& m_combo1.GetParent()->GetDlgCtrlID() == pWnd->GetParent()->GetDlgCtrlID())
    	{
    		//获取ListBox和m_combo1的屏幕坐标范围
    		RECT rectListBox;
    		RECT rectComboBox;
    		pWnd->GetWindowRect(&rectListBox);
    		m_combo1.GetWindowRect(&rectComboBox);
    		//如果该ListBox刚好在m_combo1的下面,则是单击m_combo1产生的下拉ListBox
    		if (rectListBox.left == rectComboBox.left
    			&& rectListBox.top == rectComboBox.bottom)
    		{
    			pDC->SetTextColor(RGB(255, 0, 0));
    		}
    	}
    
    	// TODO:  Return a different brush if the default is not desired
    	return hbr;
    }
    

    效果如下:

    更简单的办法是:利用向导新增MFC类CMyComboBox : CComboBox,再增加WM_CTLCOLOR消息的响应函数。(注意:ComboBox下的EditBox和ListBox均会向ComboBox窗口发送WM_CTLCOLOR消息,如果在ComboBox对应的消息映射表没有找到对应的处理函数,再向CComboBox的父窗口发送WM_CTLCOLOR消息,具体可参考文章WM_NOTIFY消息流程实例分析
    1. BEGIN_MESSAGE_MAP(CMyComboBox, CComboBox)  
    2.     ON_WM_CTLCOLOR()  
    3. END_MESSAGE_MAP()  
    4.   
    5. HBRUSH CMyComboBox::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)  
    6. {  
    7.     HBRUSH hbr = CComboBox::OnCtlColor(pDC, pWnd, nCtlColor);  
    8.   
    9.     // TODO:  Change any attributes of the DC here   
    10.     pDC->SetTextColor(RGB(255, 255, 0));  
    11.   
    12.     // TODO:  Return a different brush if the default is not desired   
    13.     return hbr;  
    14. }  
    BEGIN_MESSAGE_MAP(CMyComboBox, CComboBox)
    	ON_WM_CTLCOLOR()
    END_MESSAGE_MAP()
    
    HBRUSH CMyComboBox::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
    {
    	HBRUSH hbr = CComboBox::OnCtlColor(pDC, pWnd, nCtlColor);
    
    	// TODO:  Change any attributes of the DC here
    	pDC->SetTextColor(RGB(255, 255, 0));
    
    	// TODO:  Return a different brush if the default is not desired
    	return hbr;
    }
    
    pDC->SetTextColor(RGB(255, 255, 0));一句代码就可以实现上面的功能。

        说明四、WM_CTLCOLOR为通告消息,所以也可以在反射消息中处理。
    ON_WM_CTLCOLOR_REFLECT()
    

    from:http://blog.csdn.net/wangyao1052/article/details/8070393
  • 相关阅读:
    [React] Cleaning up Functional Components with Custom Hooks
    [React] useCallback + useMemo to avoid re-render
    [React] Replacing Instance Variables with the useRef Hook
    [Cloud Architect] 4. Introduction to Design for Cost, Performance, & Scalability
    [Cloud Architect] 3. Monitor, React, and Recover
    [Cloud Architect] 3. Business Objectives
    1314:【例3.6】过河卒(Noip2002)
    1313:【例3.5】位数问题
    rk3568 linux sdk Buildroot 开发
    AcWing 873. 欧拉函数
  • 原文地址:https://www.cnblogs.com/lidabo/p/2804246.html
Copyright © 2011-2022 走看看