RgnButton.h
#pragma once #include "afxwin.h" class CRgnButton : public CButton { DECLARE_DYNAMIC(CRgnButton) public: CRgnButton(); ~CRgnButton(); virtual void SetImage(Image* img); virtual void SetImageHover(Image* img); virtual void Create(CWnd* pParentWnd, UINT nID); private: // 设置窗体区域 void SetRgn(CRgn *region); // 读取图片的非透明区生成区域 Region* CreateRegion(Image* img); Image* m_image; Point m_imgOffset; HRGN rgn, trgn; Image* m_imageHover; bool m_isHover; bool m_isHoverShowing; protected: DECLARE_MESSAGE_MAP() virtual void PreSubclassWindow(); public: virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); afx_msg void OnLButtonDown(UINT nFlags, CPoint point); afx_msg void OnLButtonUp(UINT nFlags, CPoint point); afx_msg void OnMouseLeave(); afx_msg void OnMouseMove(UINT nFlags, CPoint point); afx_msg void OnMouseHover(UINT nFlags, CPoint point); };
RgnButton.cpp
#include "stdafx.h" #include "RgnButton.h" IMPLEMENT_DYNAMIC(CRgnButton, CButton) CRgnButton::CRgnButton() { m_isHover = false; m_isHoverShowing = false; this->m_image = NULL; this->m_imageHover = NULL; this->m_imgOffset = Point(0, 0); } void CRgnButton::SetImage(Image* img) { this->m_image = img; Region* rgn = CreateRegion(img); Graphics g(GetWindowDC()->m_hDC); HRGN hrgn = rgn->GetHRGN(&g); CRgn * crgn = CRgn::FromHandle(hrgn); SetRgn(crgn); delete rgn; } void CRgnButton::SetImageHover(Image* img) { this->m_imageHover = img; /* Region* rgn = CreateRegion(img); Graphics g(GetWindowDC()->m_hDC); HRGN hrgn = rgn->GetHRGN(&g); CRgn * crgn = CRgn::FromHandle(hrgn); SetRgn(crgn); delete rgn; */ } CRgnButton::~CRgnButton() { if (m_image) { delete m_image; } } void CRgnButton::Create(CWnd*pParentWnd, UINT nID){ CWnd* target = pParentWnd->GetDlgItem(nID); CRect rc; target->GetWindowRect(&rc); pParentWnd->ScreenToClient(&rc); __super::Create(NULL, WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON | BS_OWNERDRAW, CRect(rc.left, rc.top, m_image->GetWidth() + rc.left, m_image->GetHeight() + rc.top), pParentWnd, nID); } Region* CRgnButton::CreateRegion(Image* img){ Bitmap* bmp = new Bitmap(img->GetWidth(), img->GetHeight()); Graphics* g = Graphics::FromImage(bmp); g->DrawImage(img, 0, 0, img->GetWidth(), img->GetHeight()); GraphicsPath gp; for (int i = 0; i < (int)bmp->GetWidth(); i++) { for (int j = 0; j < (int)bmp->GetHeight(); j++) { Color cl; bmp->GetPixel(i, j, &cl); if (cl.GetA() != 0) { gp.AddRectangle(Rect(i, j, 1, 1)); } } } delete g; delete bmp; return new Region(&gp); } void CRgnButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { SetWindowRgn(rgn, true); if (m_isHover&&m_imageHover){ m_isHoverShowing = true; Graphics g(lpDrawItemStruct->hDC); g.SetClip(trgn, CombineModeReplace); switch (lpDrawItemStruct->itemAction) { case ODA_SELECT: case ODA_DRAWENTIRE: case ODA_FOCUS: { g.DrawImage(m_imageHover, RectF((REAL)m_imgOffset.X, (REAL)m_imgOffset.Y, (REAL)m_image->GetWidth(), (REAL)m_image->GetHeight())); } break; } } else if (m_image) { Graphics g(lpDrawItemStruct->hDC); g.SetClip(trgn, CombineModeReplace); switch (lpDrawItemStruct->itemAction) { case ODA_SELECT: case ODA_DRAWENTIRE: case ODA_FOCUS: { g.DrawImage(m_image, RectF((REAL)m_imgOffset.X, (REAL)m_imgOffset.Y, (REAL)m_image->GetWidth(), (REAL)m_image->GetHeight())); } break; } } } BEGIN_MESSAGE_MAP(CRgnButton, CButton) ON_WM_LBUTTONDOWN() ON_WM_LBUTTONUP() ON_WM_MOUSELEAVE() ON_WM_MOUSEMOVE() ON_WM_MOUSEHOVER() END_MESSAGE_MAP() void CRgnButton::SetRgn(CRgn *region){ rgn = ::CreateRectRgn(0, 0, 0, 0); CombineRgn(rgn, region->operator HRGN(), NULL, RGN_COPY); trgn = ::CreateRectRgn(0, 0, 0, 0); CombineRgn(trgn, region->operator HRGN(), NULL, RGN_COPY); } void CRgnButton::PreSubclassWindow(){ ModifyStyle(0, BS_OWNERDRAW | WS_CLIPSIBLINGS); CButton::PreSubclassWindow(); } void CRgnButton::OnLButtonDown(UINT nFlags, CPoint point) { m_imgOffset.X = 1; m_imgOffset.Y = 1; CButton::OnLButtonDown(nFlags, point); } void CRgnButton::OnLButtonUp(UINT nFlags, CPoint point) { m_imgOffset.X = 0; m_imgOffset.Y = 0; CButton::OnLButtonUp(nFlags, point); } void CRgnButton::OnMouseLeave() { m_isHover = false; m_imgOffset.X = 0; m_imgOffset.Y = 0; m_isHoverShowing = false; InvalidateRect(NULL, FALSE); CButton::OnMouseLeave(); } void CRgnButton::OnMouseMove(UINT nFlags, CPoint point) { TRACKMOUSEEVENT tme; tme.cbSize = sizeof(TRACKMOUSEEVENT); tme.dwFlags = TME_LEAVE | TME_HOVER;//要触发的消息 tme.hwndTrack = this->m_hWnd; tme.dwHoverTime = 10;// 若不设此参数,则无法触发mouseHover ::_TrackMouseEvent(&tme); //MOUSELEAVE|MOUSEHOVER消息由此函数触发 CButton::OnMouseMove(nFlags, point); } void CRgnButton::OnMouseHover(UINT nFlags, CPoint point) { m_isHover = true; m_imgOffset.X = 0; m_imgOffset.Y = 0; if (!m_isHoverShowing)InvalidateRect(NULL); CButton::OnMouseHover(nFlags, point); }