VC按钮自绘的简单实现

本文介绍了如何在VC中实现按钮的自绘,包括文字位置自由偏移和按钮的不同状态(正常、悬停、按下、禁用)。通过创建CSkinButton类并重写DrawItem()函数,结合WM_DRAWITEM消息,实现了控件的自绘功能,同时讲解了鼠标响应和图片绘制的相关实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  之前一直使用公司开发的界面库来进行VC界面设计,今天偶然发现其中一个按钮类不能实现特定需求,例如文字的位置不能随意显示在按钮上。于是唯有重新定义了该按钮类的自绘功能,添加新的属性和操作。
  通过这次修改,感觉控件自绘也还是蛮有意思的,本来不能实现的功能,通过类的派生和自绘就能实现,感觉真爽,符合人性欲望无限扩展的本性。
  说起VC的界面设计,大家都应该很清楚,MFC提供了很多标准的控件,例如按钮,下拉框等等,但是这些控件本身并不美观。要想改变它们的形状和外观,就必须要进行控件的自绘。我们常常看到QQ,360的界面设计,之所以那么狂吊炸天,就是因为他们有自己的界面库,能实现控件的自绘。现以一个简单的例子来介绍按钮自绘的方法实现。(部分函数代码和实现原理还是要列出的,因为代码才是王道啊,步骤就略过哈。)

   1. 功能需求

   1) 实现按钮文字任意位置的偏移。效果图如下:

这里写图片描述

这里写图片描述

   2) 实现按钮的几种状态
   Normal:
  Normal
    Over:
  这里写图片描述
  Down:
  这里写图片描述
  Disable:
  这里写图片描述

  2. 方法实现

   首先定义一个CSkinButton类,它继承于CButton类。
   1) 自绘属性
  要想实现按钮自绘,需要把按钮风格修改为自绘属性BS_OWNERDRAW,从而系统会发送WM_DRAWITEM消息给CButton类,才会调用重载函数DrawItem实现自绘。可选择在对话框属性中或者在重载函数PreSubclassWindow中添加ModifyStyle(0,BS_OWNERDRAW);。

void CSkinButton::PreSubclassWindow() 
{
    // TODO: Add your specialized code here and/or call the base class
    ModifyStyle(0,BS_OWNERDRAW);
    CButton::PreSubclassWindow();
}

   2) 重载DrawItem()函数
   DrawItem()函数主要是根据按钮的状态来绘制自身的形状和外观,按钮控件自绘的功能就是在这里实现的。它主要包含了一个LPDRAWITEMSTRUCT的指针。声明如下:

typedef struct tagDRAWITEMSTRUCT {
UINT CtlType;         //控件的类型
UINT CtlID;           //自绘控件ID
UINT itemID;          //菜单项ID
UINT itemAction;      //绘制行为
UINT itemState;       //当前绘制操作完成后,所绘项的可见状态
HWND hwndItem;        //指定了组合框、列表框和按钮等自绘控件的窗口句柄
HDC hDC;              //绘制操作所使用的设备环境
RECT rcItem;          //绘制的矩形区域。这个区域就是上面hDC的作用范围。
ULONG_PTR itemData;   //菜单项数据
} DRAWITEMSTRUCT, NEAR *PDRAWITEMSTRUCT, FAR *LPDRAWITEMSTRUCT

  具体实现如下:

void CSkinButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) 
{
    // TODO: Add your code to draw the specified item
    CRect rcItem(lpDrawItemStruct->rcItem);
    CString strText,strPath;
    CString strWorkPath;

    //按钮状态
    int nStatus = CONTROL_STATUS_NORMAL;
    if ( !IsWindowEnabled() )
    {
        nStatus = CONTROL_STATUS_DISABLE;
    }
    else
    {
        if ( m_bTrackMouseEvent )
        {
            if ( m_bLButtonDown )
            {
                nStatus = CONTROL_STATUS_DOWN;
            }
            else
            {
                nStatus = CONTROL_STATUS_OVER;
            }
        }
        else
        {
//          if ( ::GetFocus()==m_hWnd )
//          {
   
//              nStatus = CONTROL_STATUS_FOCUS;
//          }
//          else
            {
                nStatus = CONTROL_STATUS_DISABLE/*CONTROL_STATUS_NORMAL*/;
            }
        }
    }

    if ( m_hBitmap[nStatus] )
    {
        //绘图
        Draw9gridTransparent(lpDrawItemStruct->hDC, lpDrawItemStruct->rcItem, m_rcBorder9grid, m_hBitmap[nStatu
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值