• 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.添加按钮事件:

  • 相关阅读:
    K8S 之Pod简单提供持久化存储
    K8S 备份所有Namespace的yaml应用配置文件
    Ceph 集群部署
    Django cookie使用
    Django CBV使用
    hashlib模块
    如何序列化之json和pickle:
    os模块
    random模块
    os模块
  • 原文地址:https://www.cnblogs.com/poissonnotes/p/4398928.html
Copyright © 2020-2023  润新知