头文件:
//头文件 #pragma once // CLhsButton #define MYWM_BTN_CLICK WM_USER+3001 //关闭按钮单击响应 //tab按钮的状态 enum ButtonState { BTN_STATE_NOR = 0, BTN_STATE_DOWN = 1, }; class CLhsButton : public CWnd { DECLARE_DYNAMIC(CLhsButton) public: CLhsButton(); virtual ~CLhsButton(); bool Create(CWnd* pParent,CRect rc,CString text,DWORD id = 0,DWORD style = WS_VISIBLE|WS_CHILD); DECLARE_MESSAGE_MAP() public: protected: CString szClassName; bool m_isMouseHover; //鼠标是否悬浮 bool m_isMouseClicked; //鼠标是否单击 CString m_strShowText; //要显示的文字 Image* m_pImgNor; //正常时的图片 Image* m_pImgHot; //鼠标悬浮时的图片 Image* m_pImgDown; //单击按下时的图片 void PostClickEvent(); afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); afx_msg void OnMouseMove(UINT nFlags, CPoint point); afx_msg void OnMouseHover(UINT nFlags, CPoint point); afx_msg void OnMouseLeave(); afx_msg void OnLButtonDown(UINT nFlags, CPoint point); afx_msg void OnLButtonUp(UINT nFlags, CPoint point); afx_msg BOOL OnEraseBkgnd(CDC* pDC); afx_msg void OnPaint(); afx_msg void OnSize(UINT nType, int cx, int cy); virtual BOOL PreTranslateMessage(MSG* pMsg); public: void SetTabState(ButtonState state){m_btnState = state; Invalidate();} //设置tab状态 ButtonState GetTabState(){return m_btnState;} void SetToolTipText(CString spText, BOOL bActivate = TRUE); void LoadBtnImg(LPCTSTR tType, UINT nNorID, UINT nHotID, UINT nDownID); //加载按钮图片 private: ButtonState m_btnState; //tab的状态 CToolTipCtrl* m_pToolTip; CString m_tooltext; public: afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor); }; //源文件 // CLhsButton.cpp : 实现文件 // #include "stdafx.h" #include "../Lander_mini.h" #include "memdc.h" #include "../Utility.h" #include "LhsButton.h" // CLhsButton IMPLEMENT_DYNAMIC(CLhsButton, CWnd) CLhsButton::CLhsButton() { m_isMouseHover = false; m_isMouseClicked = false; // 注册控件类 szClassName = AfxRegisterWndClass(0); m_pImgNor = NULL; m_pImgHot = NULL; m_pImgDown = NULL; m_btnState = BTN_STATE_NOR; m_pToolTip = NULL; } CLhsButton::~CLhsButton() { SAFE_RELEASE(m_pToolTip); SAFE_RELEASE(m_pImgNor); SAFE_RELEASE(m_pImgHot); SAFE_RELEASE(m_pImgDown); } BEGIN_MESSAGE_MAP(CLhsButton, CWnd) ON_WM_MOUSEMOVE() ON_WM_MOUSEHOVER() // 此消息系统并不会给我们发送 ON_WM_MOUSELEAVE() ON_WM_LBUTTONDOWN() ON_WM_LBUTTONUP() ON_WM_PAINT() ON_WM_SIZE() ON_WM_ERASEBKGND() ON_WM_CREATE() ON_WM_CTLCOLOR() END_MESSAGE_MAP() // CLhsButton 消息处理程序 bool CLhsButton::Create(CWnd* pParent,CRect rc,CString text,DWORD id /* = 0 */,DWORD style /* = WS_VISIBLE|WS_CHILD */) { // 动态创建控件 BOOL ret = CWnd::CreateEx(0, szClassName, text, style, rc, pParent, id); return ret ? true : false; } int CLhsButton::OnCreate(LPCREATESTRUCT lpCreateStruct) { //::SetWindowLong(m_hWnd, GWL_EXSTYLE, GetWindowLong(m_hWnd, GWL_EXSTYLE) ^ WS_EX_LAYERED); //ModifyStyle(WS_CLIPCHILDREN, 0); //ModifyStyle(0, WS_CLIPCHILDREN , 0); return 0; } void CLhsButton::PostClickEvent() { // 该函数用来向父窗口发送 单击 消息 CWnd* parent = GetParent(); if(parent) parent->SendMessage(MYWM_BTN_CLICK, 0,0); } void CLhsButton::OnMouseHover(UINT nFlags, CPoint point) { // 鼠标进入 Invalidate(); } void CLhsButton::OnMouseMove(UINT nFlags, CPoint point) { // 只处理鼠标第一次进入时的情况 if(!m_isMouseHover) { m_isMouseHover = true; TRACKMOUSEEVENT evt = { sizeof(evt), TME_LEAVE|TME_HOVER, m_hWnd, 0 }; TrackMouseEvent(&evt); OnMouseHover(0,CPoint()); } } void CLhsButton::OnMouseLeave() { // 鼠标离开 m_isMouseHover = false; m_isMouseClicked = false; Invalidate(); } void CLhsButton::OnLButtonDown(UINT nFlags, CPoint point) { // 鼠标按下 m_isMouseClicked = true; Invalidate(); } void CLhsButton::OnLButtonUp(UINT nFlags, CPoint point) { // 鼠标松开 if(m_isMouseClicked) { m_isMouseClicked = false; Invalidate(); PostClickEvent(); } } BOOL CLhsButton::OnEraseBkgnd(CDC* pDC) { // return CWnd::OnEraseBkgnd(pDC); return TRUE; // 阻止擦除背景,防止闪烁 } void CLhsButton::OnPaint() { CPaintDC dc(this); CRect rc; GetClientRect(&rc); // 采用双缓存,防止闪烁 CMemDC memdc(&dc,&rc,TRUE); Graphics graphic(memdc); if (!m_pImgNor || !m_pImgHot || !m_pImgDown) {//没有提供按钮图片就刷下背景 // 刷背景 COLORREF bkgnd = RGB(100,0,0); if(m_isMouseHover) { if(m_isMouseClicked) bkgnd = RGB(250,0,0); else bkgnd = RGB(180,0,0); } memdc.FillSolidRect(&rc,bkgnd); } if (m_isMouseClicked || m_btnState == BTN_STATE_DOWN) {//单击一定画单击状态 graphic.DrawImage(m_pImgDown, 0, 0, m_pImgDown->GetWidth(), m_pImgDown->GetHeight()); } else if (m_isMouseHover && !m_isMouseClicked) { //悬浮,但是没单击 graphic.DrawImage(m_pImgHot, 0, 0, m_pImgHot->GetWidth(), m_pImgHot->GetHeight()); } else { graphic.DrawImage(m_pImgNor, 0, 0, m_pImgNor->GetWidth(), m_pImgNor->GetHeight()); } // 使绘制生效 graphic.ReleaseHDC(memdc); } BOOL CLhsButton::PreTranslateMessage(MSG* pMsg) { if (m_pToolTip) { if (::IsWindow(m_pToolTip->m_hWnd)) { m_pToolTip->RelayEvent(pMsg); } } return CWnd::PreTranslateMessage(pMsg); } void CLhsButton::OnSize(UINT nType, int cx, int cy) { } void CLhsButton::SetToolTipText(CString spText, BOOL bActivate) { if (m_pToolTip == NULL) { m_pToolTip = new CToolTipCtrl; // Create ToolTip control m_pToolTip->Create(this); m_pToolTip->Activate(TRUE); } m_tooltext = spText; // If there is no tooltip defined then add it if (m_pToolTip->GetToolCount() == 0) { CRect rectBtn; GetClientRect(rectBtn); m_pToolTip->AddTool(this, m_tooltext, rectBtn, 1); } // Set text for tooltip m_pToolTip->UpdateTipText(m_tooltext, this, 1); m_pToolTip->SetDelayTime(2000); m_pToolTip->Activate(bActivate); } HBRUSH CLhsButton::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { HBRUSH hbr = CWnd::OnCtlColor(pDC, pWnd, nCtlColor); // TODO: 在此更改 DC 的任何属性 // TODO: 如果默认的不是所需画笔,则返回另一个画笔 return hbr; } //加载按钮图片 void CLhsButton::LoadBtnImg(LPCTSTR tType, UINT nNorID, UINT nHotID, UINT nDownID) { m_pImgNor = CQYUtility::LoadImgFromRes(_T("PNG"), nNorID); m_pImgHot = CQYUtility::LoadImgFromRes(_T("PNG"), nHotID); m_pImgDown = CQYUtility::LoadImgFromRes(_T("PNG"), nDownID); }
内存DC
<pre name="code" class="cpp">#ifndef _MEMDC_H_ #define _MEMDC_H_ ////////////////////////////////////////////////// // CMemDC - memory DC // class CMemDC : public CDC { private: CBitmap m_bitmap; // Offscreen bitmap CBitmap* m_oldBitmap; // bitmap originally found in CMemDC CDC* m_pDC; // Saves CDC passed in constructor CRect m_rect; // Rectangle of drawing area. BOOL m_bMemDC; // TRUE if CDC really is a Memory DC. public: void Build( CDC* pDC ) { ASSERT(pDC != NULL); m_pDC = pDC; m_oldBitmap = NULL; m_bMemDC = !pDC->IsPrinting(); if( m_bMemDC ) { CreateCompatibleDC(pDC); pDC->LPtoDP(&m_rect); m_bitmap.CreateCompatibleBitmap(pDC, m_rect.Width(), m_rect.Height()); m_oldBitmap = SelectObject(&m_bitmap); SetMapMode(pDC->GetMapMode()); pDC->DPtoLP(&m_rect); SetWindowOrg(m_rect.left, m_rect.top); } else { m_bPrinting = pDC->m_bPrinting; m_hDC = pDC->m_hDC; m_hAttribDC = pDC->m_hAttribDC; } FillSolidRect( m_rect, pDC->GetBkColor() ); } CMemDC(CDC* pDC, const CRect* pRect = NULL, BOOL bBg = FALSE) : CDC() { ASSERT(pDC != NULL); // Some initialization m_pDC = pDC; m_oldBitmap = NULL; m_bMemDC = !pDC->IsPrinting(); // Get the rectangle to draw if (pRect == NULL) { pDC->GetClipBox(&m_rect); } else { m_rect = *pRect; } if (m_bMemDC) { // Create a Memory DC CreateCompatibleDC(pDC); pDC->LPtoDP(&m_rect); m_bitmap.CreateCompatibleBitmap(pDC, m_rect.Width(), m_rect.Height()); m_oldBitmap = SelectObject(&m_bitmap); SetMapMode(pDC->GetMapMode()); SetWindowExt(pDC->GetWindowExt()); SetViewportExt(pDC->GetViewportExt()); pDC->DPtoLP(&m_rect); SetWindowOrg(m_rect.left, m_rect.top); } else { // Make a copy of the relevent parts of the current DC for printing m_bPrinting = pDC->m_bPrinting; m_hDC = pDC->m_hDC; m_hAttribDC = pDC->m_hAttribDC; } // Fill background if( bBg ) BitBlt(m_rect.left, m_rect.top, m_rect.Width(), m_rect.Height(), m_pDC, m_rect.left, m_rect.top, SRCCOPY); else FillSolidRect(m_rect, pDC->GetBkColor()); } ~CMemDC() { if (m_bMemDC) { // Copy the offscreen bitmap onto the screen. m_pDC->BitBlt(m_rect.left, m_rect.top, m_rect.Width(), m_rect.Height(), this, m_rect.left, m_rect.top, SRCCOPY); //Swap back the original bitmap. SelectObject(m_oldBitmap); } else { // All we need to do is replace the DC with an illegal value, // this keeps us from accidently deleting the handles associated with // the CDC that was passed to the constructor. m_hDC = m_hAttribDC = NULL; } } // Allow usage as a pointer CMemDC* operator->() { return this; } // Allow usage as a pointer operator CMemDC*() { return this; } CMemDC( HDC hDC ) : CDC() { CDC::FromHandle( hDC )->GetClipBox( &m_rect ); Build( CDC::FromHandle( hDC ) ); } }; #endif
调用方法:
//使用例子 RECT rc = {0, 0, 20, 20}; m_btnClose.LoadBtnImg(_T("PNG"),IDB_PNG_TAB_CLOSE_NOR, IDB_PNG_TAB_CLOSE_HOT,IDB_PNG_TAB_CLOSE_HOT); m_btnClose.Create(this, rc, L"",ID_BTN_MYTAB_CLOSE); m_btnClose.SetToolTipText(_T("关闭"));
源文地址:http://blog.csdn.net/huasonl88/article/details/43226011