现在的位置: 首页 > 综合 > 正文

利用按钮自绘制作图形按钮

2013年06月17日 ⁄ 综合 ⁄ 共 3174字 ⁄ 字号 评论关闭
我们要举的例子是利用一张包含按钮的三种状态(鼠标移动,鼠标离开,鼠标单击)的位图来绘制按钮,因为三种状态
在一张位图上,所以每种状态的图片高度都相等,而宽度是位图总长度的1/3。

  1.首先创建一个CBitmapButton的子类CHoverButton,并创建四个类成员变量:
    //指示鼠标是否在按钮上面
    BOOL m_bHover;
    //按钮是否跟踪到鼠标
    BOOL m_bTracking;
    //保存图片的变量
    CBitmap mybitmap;
    //按钮尺寸
    CSize m_ButtonSize;
  
  2.在类的构造函数中,初始化和鼠标相关的变量
  CHoverButton::CHoverButton()
  {
    m_bHover = FALSE;       
    m_bTracking = FALSE;
  }  

  3.创建一个载入位图的成员函数,参数为位图的资源标识符。在按钮自绘之前,必须有相应的位图已经载入。
    
    BOOL LoadBitmap(UINT bitmapid);  
    
    其实现为:
    
  BOOL CHoverButton::LoadBitmap(UINT bitmapid)
  {
    //载入图片
    mybitmap.Attach(::LoadImage(::AfxGetInstanceHandle(),MAKEINTRESOURCE(bitmapid), IMAGE_BITMAP,0,0,LR_LOADMAP3DCOLORS));
    BITMAP    bitmapbits;
    //获取位图信息并存入bitmapbits结构中
    mybitmap.GetBitmap(&bitmapbits);
    
    //取位图相应的高度和1/3宽度。
    m_ButtonSize.cy=bitmapbits.bmHeight;
    m_ButtonSize.cx=bitmapbits.bmWidth/3;
    
    SetWindowPos( NULL, 0,0, m_ButtonSize.cx,m_ButtonSize.cy,SWP_NOMOVE |SWP_NOOWNERZORDER );
    return TRUE;
  }
  
  4.重载按钮的虚拟函数DrawItem()成员函数
  当一个自绘按钮的外观发生变化时由框架调用.其函数原型为:
  virtual void DrawItem(
   LPDRAWITEMSTRUCT lpDrawItemStruct 
);
  DRAWITEMSTRUCT结构包含被绘制项目的信息。
  
  下面是该函数的实现
 void CHoverButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
    //获取保存在DRAWITEMSTRUCT结构中且在绘制按钮时必须使用的设备上下文
    CDC* mydc=CDC::FromHandle(lpDrawItemStruct->hDC);

    //创建兼容的设备上下文
    CDC* pMemDC = new CDC;
    pMemDC -> CreateCompatibleDC(mydc);

    //保存旧对象
    CBitmap * pOldBitmap;
    pOldBitmap = pMemDC -> SelectObject(&mybitmap);
    
    CPoint point(0,0);    
    
    //判断按钮是否处于选择状态,如果是则绘制选择状态的按钮位图,在我们提供的位图中,选中状态的按钮图片是第二个
    if(lpDrawItemStruct->itemState & ODS_SELECTED)
    {
        mydc->BitBlt(0,0,m_ButtonSize.cx,m_ButtonSize.cy,pMemDC,m_ButtonSize.cx,0,SRCCOPY);
    }
    else
    {   //判断鼠标是否离开还是在按钮上面,以便绘制相应的位图
        if(m_bHover)
        {
            mydc->BitBlt(0,0,m_ButtonSize.cx,m_ButtonSize.cy,pMemDC,m_ButtonSize.cx*2,0,SRCCOPY);
        }else
        {
            mydc->BitBlt(0,0,m_ButtonSize.cx,m_ButtonSize.cy,pMemDC,0,0,SRCCOPY);
        }    
    }

    // clean up
    pMemDC -> SelectObject(pOldBitmap);
    delete pMemDC;
    

  5.对于按钮的鼠标移动处理,我们可以使用其WM_MOUSEMOVE消息来处理,而对于按钮的鼠标悬停和离开消息,我们必须使用
TrackMouseEvent()函数来处理,该函数在鼠标指针离开窗体或悬停在窗体上是发送消息.可以发送的消息有(WM_MOUSELEAVE,
WM_MOUSEHOVER,WM_NCMOUSELEAVE,WM_NCMOUSEHOVER)

该函数带有一个TRACKMOUSEEVENT结构参数,它包含跟踪鼠标的信息。
对于鼠标在按钮上移动,离开按钮,在按钮上悬停的处理代码如下:

void CHoverButton::OnMouseMove(UINT nFlags, CPoint point)
{
    if (!m_bTracking)
    {
        TRACKMOUSEEVENT tme;
        tme.cbSize = sizeof(tme);
        tme.hwndTrack = m_hWnd;
        tme.dwFlags = TME_LEAVE|TME_HOVER;
        tme.dwHoverTime = 1;
        m_bTracking = _TrackMouseEvent(&tme);
    }
    CBitmapButton::OnMouseMove(nFlags, point);
}

LRESULT CHoverButton::OnMouseLeave(WPARAM wparam, LPARAM lparam)
{
    m_bTracking = FALSE;
    m_bHover=FALSE;
    //重画按钮
    Invalidate(TRUE);
    return 0;
}

LRESULT CHoverButton::OnMouseHover(WPARAM wparam, LPARAM lparam) 
{

    m_bHover=TRUE;
    Invalidate(TRUE);
    return 0;
}

  6.我们把这个按钮放入对话框进行测试,首先在基于对话框的应用程序中加入一个按钮,设置其Owner Draw
的属性为true。然后添加一个按钮控件变量,然后用CHoverButton类代替CButton类
CHoverButton m_HoverButton;
最后在对话框的OnInitDialog()处理函数中加入下面一行代码来为按钮的自绘作准备:
m_HoverButton.LoadBitmap(IDB_BITMAP1);

抱歉!评论已关闭.