mfc 按钮自绘

MFC  按钮自绘

:songyanwu

如果你是大神就没必要看这个文章了!

说明

源码下载:mfc 按钮自绘

先说说自己的一些想法:我就想把按钮封装成一个类,每次在使用的时候会很方便,当然在自己的类中去重载也可以!

此文章可借鉴学习:MFC基础,MFC自绘控件学习总结.
(我也主要研究了自绘控件的子类化方法  ),看完前面推荐的文章,你似乎有何种感觉呢?

先实际操作吧;原理在后面介绍:

1 新建一个对画框 应用程序

2 新添加一个CMyButton继承CButton

3 为你自己添加的类 添加消息WM_LBUTTONDOWN,WM_LBUTTONUP消息,并重写DrawItem虚函数(函数从绘调用),

4 在你添加的类中 添加Bool  变量 m_BtnDown来判断按钮的状态

5 添加消息代码如下

[cpp] view plaincopyprint?

  1. <span style="font-size:14px;">void CMyButton::OnLButtonDown(UINT nFlags, CPoint point)
  2. {
  3. // TODO: 在此添加消息处理程序代码和/或调用默认值
  4. m_BtnDown = true;
  5. Invalidate();
  6. CButton::OnLButtonDown(nFlags, point);
  7. }</span>

[cpp] view plaincopyprint?

  1. <span style="font-size:14px;">void CMyButton::OnLButtonUp(UINT nFlags, CPoint point)
  2. {
  3. // TODO: 在此添加消息处理程序代码和/或调用默认值
  4. m_BtnDown=false;
  5. Invalidate();
  6. CButton::OnLButtonUp(nFlags, point);
  7. }</span>

注:Invalidate(BOOL bErase=TRUE)函数的作用是使整个窗口的客户区无效。客户区无效就意味着需要重绘。例如,如果一个被其它窗口遮住的窗口变成了前台窗口,那么原来被遮住的部分就是无效的,需要重绘。这时Windows会在应用程序的消息队列中放置WM_PAINT消息。MFC为窗口类提供了WM_PAINT的消息处理函数OnPaint,OnPaint负责重绘窗口。视图类有一些例外,在视图类的OnPaint函数中调用了OnDraw函数,实际的重绘工作由OnDraw来完成。参数bErase为TRUE时,重绘区域内的背景将被擦除,否则,背景将保持不变。

和UpdateWindow的区别是UpdateWindow是使窗口立即重绘。Invalidate只是发送一个WM_PAINT消息,WM_PAINT消息的优先级很低,需要等到消息队列中其他消息处理完成后才能被处理,所以窗口不会立即刷新。

窗口重绘时会重新生成按钮,按钮生成时会查看其风格,如果为OwnerDraw风格,则会调用DrawItem函数。关于OwnerDraw风格的设置,后边会讲。

6 重载DramItem

[cpp] view plaincopyprint?

  1. <span style="font-size:14px;">void CMyButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct/*lpDrawItemStruct*/)
  2. {
  3. // TODO:  添加您的代码以绘制指定项
  4. //通过DRAWITEMSTRUCT结构获取句柄,并且类型转换,这个FromHandle很常用
  5. CDC* pDC=CDC::FromHandle(lpDrawItemStruct->hDC);
  6. //下面两行来获取这个结构中的一个字段
  7. UINT state=lpDrawItemStruct->itemState;//按钮的状态
  8. CRect rect=lpDrawItemStruct->rcItem;//重绘的范围,也就是按钮
  9. //获取按钮上显示的文字
  10. CString str;
  11. GetWindowText(str);
  12. if (state & ODS_SELECTED)//如果按钮被选中
  13. {
  14. //绘制一个控件,并制定控件的类型和状态
  15. pDC->DrawFrameControl(&rect,DFC_BUTTON,DFCS_BUTTONPUSH | DFCS_PUSHED);
  16. }
  17. else
  18. {
  19. pDC->DrawFrameControl(&rect,DFC_BUTTON,DFCS_BUTTONPUSH);
  20. }
  21. if (m_BtnDown)
  22. {       //填充矩形
  23. pDC->FillSolidRect(rect,RGB(255,255,0));
  24. }
  25. else
  26. {
  27. pDC->FillSolidRect(rect,RGB(0,0,255));
  28. }
  29. if (!str.IsEmpty())
  30. {
  31. //以下是当按钮按下时要稍微移动按钮上文字的位置
  32. //使用当前字体计算一行文字的宽度和长度以确定尺寸
  33. CSize Extent=pDC->GetTextExtent(str);
  34. CPoint pt=CPoint(rect.CenterPoint().x-Extent.cx/2,rect.CenterPoint().y-Extent.cy/2);
  35. //如果被选中
  36. if (state & ODS_SELECTED)
  37. {
  38. //向一个点中添加x,y坐标
  39. pt.Offset(1,1);
  40. }
  41. //设置背景样式,值有两个:
  42. //OPAQUE   在文字,画刷,铅笔绘画之前,背景由当前背景颜色填充。这时默认的背景模式。
  43. //TRANSPARENT   在绘制前背景不变
  44. int nMode=pDC->SetBkMode(TRANSPARENT);
  45. if (state & ODS_DISABLED)
  46. {
  47. pDC->DrawState(pt,Extent,str,DSS_DISABLED,TRUE,0,(HBRUSH)NULL);
  48. }
  49. else
  50. {
  51. pDC->TextOut(pt.x,pt.y,str);
  52. }
  53. pDC->SetBkMode(nMode);
  54. }
  55. }
  56. </span>

注:

1. DrawItem函数用于重绘单个控件。其参数为指向DRAWITEMSTRUCT的一个长指针。

DRAWITEMSTRUCT为需要自绘的控件或者菜单项提供了必要的信息。在需要绘制的控件或者菜单项对应的WM_DRAWITEM消息函数中得到一个指向该结构的指针。

2

[cpp] view plaincopyprint?

  1. <span style="font-size:14px;"> typedef struct tagDRAWITEMSTRUCT {
  2. UINT CtlType;
  3. UINT CtlID;
  4. UINT itemID;
  5. UINT itemAction;
  6. UINT itemState;
  7. HWND hwndItem;
  8. HDC hDC;
  9. RECT rcItem;
  10. DWORD itemData;
  11. } DRAWITEMSTRUCT;
  12. </span><span style="font-size:14px;">
  13. </span>

CtlType:指定参数类型。例:ODT_BUTTON、ODT_COMBOBOX、ODT_LISTBOX等。

CtlID:combo
box, list box, 或者 button的控件ID。菜单项不需要此参数

itemID:菜单项的ID,也可以表示列表框或者组合框中某项的索引值。对于一个空的列表框或组合框此值为-1.这时应用程序只绘制焦点矩形(该矩形的坐标有rcItem成员给出)。虽然此时控件没有需要显示的项,但绘制焦点矩形还是很有必要的。因为这样能够提示用户该控件是否具有输入焦点。当然也可设置itemAction的值,使得无需绘制焦点。

itemAction:指定绘制行为,可取多值。ODA_DRAWENTIRE:当整个控件都需要被绘制时,设置该值。ODA_FOCUS:控件在获得或是去焦点时被绘制。此时应该检查itemState成员,以确定控件是否具有输入焦点。ODA_SELECT:控件在选中状态改变时被重绘。此时应检查itemState成员,以确定控件是否被选中。

itemState:指定当前绘制操作完成后,所绘项的可见状态。

ODS_CHECKED:菜单项被选中。该值只对菜单项有用。

             ODS_COMBOBOXEDIT:在自绘组合框控件中只绘制选择区域。

             ODS_DEFAULT:默认值。

             ODS_DISABLED:控件被禁止,则设置该值。

             ODS_FOCUS:控件需要输入焦点,则设置该值。

             ODS_GRAYED:控件被灰色显示。该值只在绘制菜单时使用。

             ODS_HOTLIGHT:Windows
XP: 如果鼠标指针位于控件之上,则设置该值,这时控件会显示高亮颜色。

       ODS_INACTIVE:
Windows XP: 表示没有激活的菜单项。

             ODS_NOACCEL:Windows
XP: 控件是否有快速键盘。

             ODS_NOFOCUSRECT:Windows
XP,不绘制捕获焦点的效果。

             ODS_SELECTED:选中的菜单项。

hwndItem:指定了组合框、列表框和按钮等自绘控件的窗口句柄;如果自绘的对象是菜单项,则表示包含该菜单项的菜单句柄。

hDC:指定了绘制操作所使用的设备环境。

rcItem:指定了将被绘制的矩形区域。这个矩形区域就是上面hDC的作用范围。系统会自动裁剪组合框、列表框或按钮等控件的自绘制区域以外的部分。也就是说rcItem中的坐标点(0,0)指的就是控件的左上角。但是系统不裁剪菜单项,所以在绘制菜单项的时候,必须先通过一定的换算得到该菜单项的位置,以保证绘制操作在我们希望的区域中进行.

3.       DC(设备上下文):设备上下文是一种包含有关某个设备(如显示器或打印机)的绘制属性信息的
Windows 数据结构。所有绘制调用都通过设备上下文对象进行,这些对象封装了用于绘制线条、形状和文本的
Windows API。设备上下文允许在
Windows 中进行与设备无关的绘制。设备上下文可用于绘制到屏幕、打印机或者图元文件

hDC是DC的一个DC的句柄。CDC是所有DC的基类。

4.       FromHandle(HANDLE
h)从网上查找的解释是,先进行查找,如果h与某个CWnd(窗口)对象相关联,就返回此CWnd对象的指针;如果h没有与任何CWnd对象关联,则new一个新的CWnd对象返回。

7.      自定义类与标准控件的关联

方法一:设置按钮的属性为Owner Drawn.

方法二:在程序中,重载PreSubClassWindow。此函数在CWnd::Create和DDX_Contorl之后调用,即在窗口子类化创建后和窗口显示前调用。在此函数中添加ModifyStyle(0,BS_OWNERDRAW);此函数用于改变控件的类型。

8.      创建子类化的自绘按钮

方法一、在
创建按钮时可以给这个按钮绑定一个CMyButton类对象,但是这个时候在classwizard中还不能看到这个类: 
可以删掉当前目录下的clw文件,然后重新打开程序,按下ctrl+w,然后一般选择add all,点击ok,这个时候再添加类对象,就会发现这个类了

方法二、上述方法不适合动态添加,下面用程序的方法动态添加

在窗口中拖入一个Button控件。在Dlg的头文件中加入成员函数CMyButton
m_MyButton(注意要加入头文件)。然后在此窗口的OnInitDialog函数中调用m_MyButton.SubClassDlgItem(IDC_BUTTON1,this).此函数可以动态的子类化一个由此窗口创建的控件并将此控件关联至此CWnd.

如果你已经有了一个窗口的指针,或者你的工作在一个CView或者其他CWnd的派生类中且里面的控件被动态创建,或者你不想用上边的函数,你可以使用下述方法。

CWnd* pWnd = GetDlgItem(IDC_BUTTON1); 
m_btnMyButton.SubclassWindow(pWnd->GetSafeHwnd());

时间: 2024-10-10 22:17:11

mfc 按钮自绘的相关文章

MFC按钮重绘

1 //按钮重绘函数 2 void CWeather091001Dlg::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) { 3 CDC buttonDC; 4 CBitmap bitmapTrans; 5 BITMAP bmp; 6 CDC mem; 7 CRect rc; 8 buttonDC.Attach(lpDrawItemStruct->hDC); 9 //得到用于绘制按钮的DC 10 mem.CreateCompat

VC MFC按钮(CButton)控件

VC MFC按钮(CButton)控件 2012年11月11日 19:15   作者:TCEO   分类:技术文章   浏览:4,298 按钮控件 1如何在按钮控件上显示图片 首先确定你要显示在按钮控件的图片类型是什么,这里我是ico图标,由于要在按钮里显示ico图标,所以要把按钮控件的属性改一下, 方法是右击按钮控件,选择属性,单击样式选项卡,把图标这一项给勾上. 然后为这个按钮控件关联一个变量如:m_Quit,类型是”Control”,以后不做说明的话,类型都是”Control”. 按钮控件

VC++ WIN32 sdk实现按钮自绘详解.

网上找了很多,可只是给出代码,没有详细解释,不便初学者理解.我就抄回冷饭.把这个再拿出来说说. 实例图片: 首先建立一个标准的Win32 Application 工程.选择a simple Win32 Application. 然后建立我们的资源文件首先新建一个对话框资源,资源ID改为IDD_MAIN_DLG 然后在其上新建一个按钮控件资源ID改为IDC_ODBUTTON,此按钮的styles中必须选中owenerdraw属性. 然后将其保存为.rc的资源文件.并将其导入我们的工程.同理新建一个

VC++ WIN32 sdk实现按钮自绘详解 之二.

网上找了很多,可只是给出代码,没有详细解释,不便初学者理解.我就抄回冷饭.把这个再拿出来说说. 实例图片: 首先建立一个标准的Win32 Application 工程.选择a simple Win32 Application. 然后建立我们的资源文件首先新建一个对话框资源,资源ID改为IDD_MAIN_DLG 然后在其上新建一个按钮控件资源ID改为IDC_ODBUTTON,此按钮的styles中必须选中owenerdraw属性. 然后将其保存为.rc的资源文件.并将其导入我们的工程.同理新建一个

vc 按钮自绘

按钮自绘,将按钮区域分成三部分,左边.右边.中间都由贴图绘制,可用于手动进度条按钮,或者左右选择项按钮 cpp代码部分: [cpp] view plaincopy // LRSkinButton.cpp : implementation file // #include "stdafx.h" #include "CRedrawButtonDemo.h" #include "LRSkinButton.h" #ifdef _DEBUG #define

MFC按钮控件

CButton按钮分为4种基本类型:下压按钮.复选.单选和自绘按钮. 按钮会向父窗口发送控件通知消息: 1,BN_CLICKED(Button News):单击消息 2,BN_DOUBLECLICKED:双击消息 3,BN_SETFOCUS:获得用户焦点 4,BN_KILLFOCUS:失去用户焦点 MFC中的CButton封装了按钮的基本操作,其中create函数如下: BOOL Create(LPCTSTR lpszCaption,DWORD dwStyle,const CRECT& rect

MFC之自绘控件

在描绘MFC界面时,MFC自带的控件样式是绝对不满足界面的需求的. 所以我们就要在MFC自带控件基础上对控件样式进行重绘. 在采用自绘前界面样式 采用自绘后界面样式 是不是自绘控件后看起来正常了很多? 自绘控件的步骤: 我们以做一个关闭按钮为例 先创建一个MFC类继承自CButton. 给这个类添加 一个虚函数DrawItem()和 一个afx BOOL OnEraseBkgnd()函数(一般以afx开头的函数都会在消息映射里面有一条映射) DrawItem()是控件的自绘处理函数,在这个函数中

【转】VC的MFC中重绘函数的使用总结(整理)

原文网址:http://www.cnblogs.com/x8023z/archive/2008/12/09/mfc33.html 在刷新窗口时经常要调用重绘函数MFC提供了三个函数用于窗口重绘InvalidateRect(&Rect)Invalidate()UpdateWindow()当需要更新或者重绘窗口时,一般系统会发出两个消息WM_PAINT(通知客户区有变化)和WM_NCPAINT(通知非客户区有变化)--WM_NVPAINT系统会自己搞定--WM_PAINT消息对应的函数是OnPain

vs2013_MFC使用文件之15.mfc 按钮CBitmapButton的使用

本文是居于对话框的 笔者使用mfc撑死2个星期,不过这是有c++基础的前提下接触mfc,昨天看到了网上对qt creator的评论,感觉好高大上,回去试了一下后发现,qt需要mfc的基础,若是直接接触qt的话会比较难,毕竟mfc是在vs的平台下,大家学起来会比较顺手. 回到正题,今天研究了下怎么使用mfc中的位图按键,发现实现方法挺多,但是对于小白来说,很多作者认为简单的都会略过,恰巧那些简单的就是我不会的,结果又看不懂.除了mfc自有的CBitmapButton外,在网上还看到有关于CButt