MFC之自绘控件

在描绘MFC界面时,MFC自带的控件样式是绝对不满足界面的需求的。

所以我们就要在MFC自带控件基础上对控件样式进行重绘。

在采用自绘前界面样式

 

采用自绘后界面样式

 

是不是自绘控件后看起来正常了很多?

自绘控件的步骤:

我们以做一个关闭按钮为例

  1. 先创建一个MFC类继承自CButton。
  2. 给这个类添加 一个虚函数DrawItem(),一个虚函数PreSubclassWindow()和 一个afx BOOL OnEraseBkgnd()函数(一般以afx开头的函数都会在消息映射里面有一条映射)
  3. DrawItem()是控件的自绘处理函数,在这个函数中可以对控件的样式进行描绘。

    附一段代码为例: 

    复制代码
     1 void CDhsButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
     2 {
     3     CDC* pDC= CDC::FromHandle(lpDrawItemStruct->hDC);
     4     CRect rect = &lpDrawItemStruct->rcItem;
     5     UINT uID = lpDrawItemStruct->CtlID;
     6  
     7     Graphics g(pDC->m_hDC);
     8     g.SetSmoothingMode(SmoothingModeHighQuality);
     9  
    10 
    11     if (::GetWindowLong(m_hWnd, GWL_STYLE) & WS_DISABLED)
    12     {
    13         if (m_pImageDisable != NULL)
    14             g.DrawImage(m_pImageDisable, 0, 0, rect.Width(), rect.Height());
    15         else
    16             g.DrawImage(m_pImageNormal, 0, 0, rect.Width(), rect.Height());
    17     }
    18     else if (m_nMouseState == Down)
    19     {
    20         if (m_pImageOver != NULL)
    21             g.DrawImage(m_pImageOver, 0, 0, rect.Width(), rect.Height());
    22         else
    23             g.DrawImage(m_pImageNormal, 0, 0, rect.Width(), rect.Height());
    24     }
    25     else if (m_bSelected)
    26     {
    27         if (m_pImageSelected != NULL)
    28             g.DrawImage(m_pImageSelected, 0, 0, rect.Width(), rect.Height());
    29         else
    30             g.DrawImage(m_pImageNormal, 0, 0, rect.Width(), rect.Height());
    31     }
    32     else
    33     {
    34         g.DrawImage(m_pImageNormal, 0, 0, rect.Width(), rect.Height());
    35     }
    36 
    37     if (!m_strCaption.IsEmpty())
    38     {
    39         rect.left += 5;
    40 
    41         if (::GetWindowLong(m_hWnd, GWL_STYLE) & WS_DISABLED)
    42         {
    43             PublicFun::GDIDrawText(pDC, m_strCaption, rect, m_pFont, RGB(120, 120, 120), FALSE, TRUE);
    44         }
    45         else if (m_bSelected)
    46         {
    47             PublicFun::GDIDrawText(pDC, m_strCaption, rect, m_pFont, RGB(0, 0, 0), FALSE, TRUE);
    48         }
    49         else if (m_nMouseState == Over)
    50         {
    51             PublicFun::GDIDrawText(pDC, m_strCaption, rect, m_pFont, RGB(0, 0, 0), FALSE, TRUE);
    52         }
    53         else
    54         {
    55             PublicFun::GDIDrawText(pDC, m_strCaption, rect, m_pFont, RGB(0, 0, 0), FALSE, TRUE);
    56         }
    57     }
    58 
    59     ReleaseDC(pDC);
    60 }
    复制代码

     

  4. 添加OnEraseBkgnd()函数代码,一般都是固定的

    BOOL CDhsButton::OnEraseBkgnd(CDC* pDC)
    {
    
        return TRUE;
    
    }

     

     

     

  5. 添加虚函数PreSubclassWindow函数代码(PreSubclassWindow函数实际上是在CWnd::CeateEx方法中的 AfxHookWindowCreate(this)方法中实现的,AfxHookWindowCreate作用是设置钩子函数,所以你如果想在创建窗口之前将窗口与自己的派生类进行关联,这时候建立前的处理就要在PreSubclassWindow中写。)

    具体来说,

  • 如果你定义一个窗口(CButton派生类CMyButton),然后使用对话框数据交换比如通过DDX将一个按钮与自己的派生类对象关联,这时候,一些"建立前"的处理就应该写在"PreSubclassWindow"中。 
  • 如果你用的不是"对话框数据关联",而是在OnInitDialg中自己创建.这时候,一些"建立前"的处理就应该写在   "PreCreateWindow"中。

在PreSubclassWindow函数中,设置ModifyStyle(0, BS_OWNERDRAW);
代码如下

 

复制代码
1 void CDhsButton::PreSubclassWindow()
2 {
3     ModifyStyle(0, BS_OWNERDRAW);
4 
5     CButton::PreSubclassWindow();
6 }
复制代码

 

使用BS_OWNERDRAW属性 是要求创建CButton的继承类,并在其中重载DrawItem方法才可以。你要是不想改变Button的外观不要用这个属性。

意思就是如果你要重载派生类按钮中的DrawItem方法,必须要设置了BS_OWNERDRAW 才能重载

 

6.因为是通过DDX关联的方式,所以在使用上,要用DoDataExchange方法将派生类与资源中的按钮进行关联。

 

  7.添加按钮事件:

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值