自绘制按钮(通过重载DrawItem函数实现)

来源:互联网 发布:vb中static 编辑:程序博客网 时间:2024/05/29 15:06

实现方法:先建一个自定义类继承CButtoon类,重载一些消息和函数。

1.       设置数据成员:

private:

       BOOL m_bMouseMove;//鼠标是否在按钮上

public:

       int m_nStyle;//有外部设置按钮为几态

       Gdiplus::Image* m_pImage;//按钮图片

 

2.       设置成员函数

// Overrides

       // ClassWizard generated virtual function overrides

       //{{AFX_VIRTUAL(CXXXButton)

       public:

       virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);//重载自绘制

       //}}AFX_VIRTUAL

protected:

       //{{AFX_MSG(CXXXButton)     

       afx_msg void OnMouseMove(UINT nFlags, CPoint point);//重载WM_MOUSEMOVE消息

       afx_msg LRESULT OnMouseLeave(WPARAM wParam, LPARAM lParam); //重载WM_MOUSELEAVE消息

       //}}AFX_MSG

       DECLARE_MESSAGE_MAP()

private:

       CSize GetImageBlockSize() const;//通过m_nStyle和图片的大小来得到每次需要得到的图片的长和宽

       BOOL TrackMouseEventEx(HWND hWnd, DWORD flags = TME_LEAVE, DWORD hoverTime = HOVER_DEFAULT); // 追踪鼠标事件

 

3.       构造函数的实现

CXXXButton::CXXXButton()

{

       m_bMouseMove = false;//默认设置鼠标不再按钮上

}

4.       消息的定义

BEGIN_MESSAGE_MAP(CXXXButton, CButton)

       //{{AFX_MSG_MAP(CXXXButton)   

       ON_WM_MOUSEMOVE()

       ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)

       //}}AFX_MSG_MAP

END_MESSAGE_MAP()

 

5.       个函数的实现

void CXXXButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)

{

 

       UINT uStyle = DFCS_BUTTONPUSH;

 

   // This code only works with buttons.

   ASSERT(lpDrawItemStruct->CtlType == ODT_BUTTON);

 

   CRect imgRc;

   CRect txtRc = lpDrawItemStruct->rcItem;

   CRect dstRc = lpDrawItemStruct->rcItem;

   COLORREF textColor = RGB(77,77,77);

   CSize block = GetImageBlockSize();     

  

   if (lpDrawItemStruct->itemState & ODS_DISABLED) //按钮不可用状态

   {

          textColor = RGB(77,77,77);

          imgRc = CRect(block.cx*(m_nStyle - 1), 0, block.cx*m_nStyle, block.cy);

   }

   else if (lpDrawItemStruct->itemState & ODS_SELECTED) //按钮按下状态

   {

          textColor = RGB(77,77,77); //设置文字颜色

          imgRc = CRect(block.cx,0,2*block.cx,block.cy);//设置按钮的图片在Load的图片上面的位置

   }

   else

   {

          if(!m_bMouseMove) //鼠标不在按钮上面

          {

                 textColor = RGB(77,77,77);

                 imgRc = CRect(0,0,block.cx,block.cy);

          }

          Else //鼠标在按钮上面

          {

                 textColor = RGB(255,255,255);

                 imgRc = CRect(block.cx*2, 0, block.cx*3, block.cy);

          }

   }

  

   //Draw the Background

   CDC* dcMem = CDC::FromHandle(lpDrawItemStruct->hDC);

   Graphics grap(dcMem->GetSafeHdc());

   grap.DrawImage(m_pImage, Rect(dstRc.top,dstRc.left,dstRc.Width(),dstRc.Height()),

          imgRc.left,imgRc.top,imgRc.Width(),imgRc.Height(),UnitPixel);

 

   // Get the button's text.

   CString strText;

   GetWindowText(strText);

 

   // Draw the button text using the text color red.

   SetBkMode(lpDrawItemStruct->hDC,TRANSPARENT);

   COLORREF crOldColor = ::SetTextColor(lpDrawItemStruct->hDC, textColor);

   ::DrawText(lpDrawItemStruct->hDC, strText, strText.GetLength(),

      &lpDrawItemStruct->rcItem, DT_SINGLELINE|DT_VCENTER|DT_CENTER);

   ::SetTextColor(lpDrawItemStruct->hDC, crOldColor);

}

 

void CXXXButton::SizeToContent()

{

       CRect rc;

       GetWindowRect(&rc);

       CSize block = GetImageBlockSize();

 

       if(rc.Width() != block.cx || rc.Height() != block.cy)

       {

              SetWindowPos(NULL, -1, -1, block.cx, block.cy,

                     SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOACTIVATE);

       }

}

 

CSize CXXXButton::GetImageBlockSize() const

{

 

       CSize block;

       block.cy = m_pImage->GetHeight();

       block.cx = m_pImage->GetWidth()/m_nStyle;

       return block;

}

 

void CXXXButton::OnMouseMove(UINT nFlags, CPoint point)

{

       // TODO: Add your message handler code here and/or call default

      

       if(!m_bMouseMove)

       {

              TrackMouseEventEx(m_hWnd);

              m_bMouseMove = TRUE;

              Invalidate();

       }

      

       CButton::OnMouseMove(nFlags, point);

}

 

BOOL CXXXButton::TrackMouseEventEx(HWND hWnd, DWORD flags, DWORD hoverTime)

{    

       TRACKMOUSEEVENT tme;

       tme.cbSize = sizeof(tme);

       tme.hwndTrack = hWnd;

       tme.dwFlags = flags;

       tme.dwHoverTime = hoverTime;

       return _TrackMouseEvent(&tme);

}

 

LRESULT CXXXButton::OnMouseLeave(WPARAM wParam, LPARAM lParam)

{

       m_bMouseMove = FALSE;

       Invalidate();

       return LRESULT(0);

}

 

6.       应用

通过MFC产生一个按钮,将按钮的属性改为Owner draw,在ClassWizard中为按钮关联一个CButton对象,如m_btnMyButton;在头文件里面将按钮的类型CButton改为我们自绘制按钮类,CXXXButton。再在实现文件的构造函数里面定义自绘制按钮的参数,设置如下:

m_btnMyButton.m_nStyle = 3;

m_btnClearList.m_pImage = LoadImage();//自定义按钮图片

基本完成了。

 

 

注意:按钮的图标必须为三态或者四态,如:

原创粉丝点击