博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
MFC之自绘控件
阅读量:4320 次
发布时间:2019-06-06

本文共 3172 字,大约阅读时间需要 10 分钟。

 

在描绘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         else16             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         else23             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         else30             g.DrawImage(m_pImageNormal, 0, 0, rect.Width(), rect.Height());31     }32     else33     {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         else54         {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.添加按钮事件:

转载于:https://www.cnblogs.com/poissonnotes/p/4398928.html

你可能感兴趣的文章
MTK android 设置里 "关于手机" 信息参数修改
查看>>
单变量微积分笔记6——线性近似和二阶近似
查看>>
补几天前的读书笔记
查看>>
HDU 1829/POJ 2492 A Bug's Life
查看>>
CKplayer:视频推荐和分享插件设置
查看>>
CentOS系统将UTC时间修改为CST时间
查看>>
redis常见面试题
查看>>
导航控制器的出栈
查看>>
玩转CSS3,嗨翻WEB前端,CSS3伪类元素详解/深入浅出[原创][5+3时代]
查看>>
iOS 9音频应用播放音频之播放控制暂停停止前进后退的设置
查看>>
Delphi消息小记
查看>>
HNOI2016
查看>>
JVM介绍
查看>>
将PHP数组输出为HTML表格
查看>>
Java中的线程Thread方法之---suspend()和resume() 分类: ...
查看>>
经典排序算法回顾:选择排序,快速排序
查看>>
BZOJ2213 [Poi2011]Difference 【乱搞】
查看>>
c# 对加密的MP4文件进行解密
查看>>
AOP面向切面编程C#实例
查看>>
AngularJs学习笔记-慕课网AngularJS实战
查看>>