www.pudn.com > vc开发的精美界面.zip > BCGButton.cpp
//******************************************************************************* // COPYRIGHT NOTES // --------------- // This source code is a part of BCGControlBar library. // You may use, compile or redistribute it as part of your application // for free. You cannot redistribute it as a part of a software development // library without the agreement of the author. If the sources are // distributed along with the application, you should leave the original // copyright notes in the source code without any changes. // This code can be used WITHOUT ANY WARRANTIES on your own risk. // // For the latest updates to this library, check my site: // http://welcome.to/bcgsoft // // Stas Levin//******************************************************************************* // BCGButton.cpp : implementation file // #include "stdafx.h" #include "bcgcontrolbar.h" #include "bcglocalres.h" #include "bcgbarres.h" #include "BCGButton.h" #include "globals.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif static const int nImageHorzMargin = 10; static const int nVertMargin = 5; ///////////////////////////////////////////////////////////////////////////// // CBCGButton IMPLEMENT_DYNAMIC(CBCGButton, CButton) CBCGButton::CBCGButton() { m_bPushed = FALSE; m_bHighlighted = FALSE; m_bCaptured = FALSE; m_nFlatStyle = BUTTONSTYLE_3D; m_sizeImage = CSize (0, 0); m_nStdImageId = (CMenuImages::IMAGES_IDS) -1; m_bAutoDestroyImage = FALSE; m_hIcon = NULL; m_hBitmap = NULL; m_hIconHot = NULL; m_hBitmapHot = NULL; m_bRighImage = FALSE; m_hCursor = NULL; m_sizePushOffset = CSize (2, 2); m_bHover = FALSE; } //**************************************************************************** CBCGButton::~CBCGButton() { CleanUp (); } //**************************************************************************** void CBCGButton::CleanUp () { if (m_bAutoDestroyImage) { if (m_hBitmap != NULL) { ::DeleteObject (m_hBitmap); } if (m_hIcon != NULL) { ::DestroyIcon (m_hIcon); } if (m_hBitmapHot != NULL) { ::DeleteObject (m_hBitmapHot); } if (m_hIconHot != NULL) { ::DestroyIcon (m_hIconHot); } } m_hBitmap = NULL; m_hIcon = NULL; m_hIconHot = NULL; m_hBitmapHot = NULL; m_nStdImageId = (CMenuImages::IMAGES_IDS) -1; m_bAutoDestroyImage = FALSE; m_sizeImage = CSize (0, 0); } BEGIN_MESSAGE_MAP(CBCGButton, CButton) //{{AFX_MSG_MAP(CBCGButton) ON_WM_ERASEBKGND() ON_WM_CANCELMODE() ON_WM_MOUSEMOVE() ON_WM_LBUTTONDOWN() ON_WM_LBUTTONUP() ON_WM_SETCURSOR() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CBCGButton message handlers void CBCGButton::DrawItem(LPDRAWITEMSTRUCT lpDIS) { ASSERT (lpDIS != NULL); ASSERT (lpDIS->CtlType == ODT_BUTTON); CDC* pDC = CDC::FromHandle (lpDIS->hDC); ASSERT_VALID (pDC); CRect rectClient = lpDIS->rcItem; //-------------- // Fill coltrol: //-------------- pDC->FillRect (rectClient, &globalData.brBtnFace); if (lpDIS->itemState & ODS_FOCUS) { OnDrawFocusRect (pDC, rectClient); } //---------------- // Draw 3d border: //---------------- if (m_nFlatStyle != BUTTONSTYLE_NOBORDERS) { if (m_bPushed && m_bHighlighted || (lpDIS->itemState & ODS_SELECTED)) { pDC->Draw3dRect (rectClient, globalData.clrBtnDkShadow, globalData.clrBtnHilite); rectClient.DeflateRect (1, 1); if (m_nFlatStyle != BUTTONSTYLE_FLAT) { pDC->Draw3dRect (rectClient, globalData.clrBtnShadow, globalData.clrBtnLight); } rectClient.DeflateRect (1, 1); rectClient.left += m_sizePushOffset.cx; rectClient.top += m_sizePushOffset.cy; } else if (m_nFlatStyle != BUTTONSTYLE_FLAT || m_bHighlighted) { pDC->Draw3dRect (rectClient, globalData.clrBtnHilite, globalData.clrBtnDkShadow); rectClient.DeflateRect (1, 1); if (m_nFlatStyle == BUTTONSTYLE_3D || (m_nFlatStyle == BUTTONSTYLE_SEMIFLAT && m_bHighlighted)) { pDC->Draw3dRect (rectClient, globalData.clrBtnLight, globalData.clrBtnShadow); } rectClient.DeflateRect (1, 1); } else { rectClient.DeflateRect (2, 2); } } else { rectClient.DeflateRect (2, 2); } //--------------------- // Draw button content: //--------------------- OnDraw (pDC, rectClient, lpDIS->itemState); } //**************************************************************************** void CBCGButton::PreSubclassWindow() { ModifyStyle (BS_DEFPUSHBUTTON, BS_OWNERDRAW); CButton::PreSubclassWindow(); } //**************************************************************************** BOOL CBCGButton::PreCreateWindow(CREATESTRUCT& cs) { cs.style |= BS_OWNERDRAW; cs.style &= ~BS_DEFPUSHBUTTON; return CButton::PreCreateWindow(cs); } //**************************************************************************** BOOL CBCGButton::OnEraseBkgnd(CDC* /*pDC*/) { return TRUE; } //**************************************************************************** void CBCGButton::OnDraw (CDC* pDC, const CRect& rect, UINT uiState) { CRect rectText = rect; CRect rectImage = rect; CString strText; GetWindowText (strText); if (m_sizeImage.cx != 0) { if (!strText.IsEmpty ()) { if (m_bRighImage) { rectText.right -= m_sizeImage.cx + nImageHorzMargin / 2; rectImage.left = rectText.right; rectImage.right -= nImageHorzMargin / 2; } else { rectText.left += m_sizeImage.cx + nImageHorzMargin / 2; rectImage.left += nImageHorzMargin / 2; rectImage.right = rectText.left; } } // Center image: rectImage.DeflateRect ((rectImage.Width () - m_sizeImage.cx) / 2, max (0, (rect.Height () - m_sizeImage.cy) / 2)); } else { rectImage.SetRectEmpty (); } //----------- // Draw text: //----------- CFont* pOldFont = pDC->SelectObject (&globalData.fontRegular); ASSERT(pOldFont != NULL); pDC->SetBkMode (TRANSPARENT); pDC->SetTextColor (globalData.clrBtnText); UINT uiDTFlags = DT_CENTER | DT_VCENTER | DT_SINGLELINE; if (uiState & ODS_DISABLED) { COLORREF clrText = pDC->SetTextColor (globalData.clrBtnHilite); CRect rectShft = rectText; rectShft.OffsetRect (1, 1); pDC->DrawText (strText, rectShft, uiDTFlags); pDC->SetTextColor (clrText); } pDC->DrawText (strText, rectText, uiDTFlags); //------------ // Draw image: //------------ if (!rectImage.IsRectEmpty ()) { if (m_nStdImageId != (CMenuImages::IMAGES_IDS) -1) { CMenuImages::Draw (pDC, m_nStdImageId, rectImage.TopLeft ()); } else { UINT uiFlags = (uiState & ODS_DISABLED) == 0 ? DSS_NORMAL : DSS_DISABLED; if (m_hIcon != NULL) { ASSERT (m_hBitmap == NULL); HBRUSH hbr = NULL; pDC->DrawState (rectImage.TopLeft (), m_sizeImage, m_bHighlighted && m_hIconHot != NULL ? m_hIconHot : m_hIcon, uiFlags, hbr); } else { ASSERT (m_hBitmap != NULL); pDC->DrawState (rectImage.TopLeft (), m_sizeImage, m_bHighlighted && m_hBitmapHot != NULL ? m_hBitmapHot : m_hBitmap, uiFlags); } } } pDC->SelectObject (pOldFont); } //**************************************************************************** void CBCGButton::SetImage (HICON hIcon, BOOL bAutoDestroy, HICON hIconHot) { CleanUp (); if (hIcon == NULL) { return; } m_hIcon = hIcon; m_hIconHot = hIconHot; m_bAutoDestroyImage = bAutoDestroy; ICONINFO info; ::GetIconInfo (m_hIcon, &info); BITMAP bmp; ::GetObject (info.hbmColor, sizeof (BITMAP), (LPVOID) &bmp); m_sizeImage.cx = bmp.bmWidth; m_sizeImage.cy = bmp.bmHeight; } //**************************************************************************** void CBCGButton::SetImage (HBITMAP hBitmap, BOOL bAutoDestroy, HBITMAP hBitmapHot) { CleanUp (); if (hBitmap == NULL) { return; } m_hBitmap = hBitmap; m_hBitmapHot = hBitmapHot; m_bAutoDestroyImage = bAutoDestroy; BITMAP bmp; ::GetObject (m_hBitmap, sizeof (BITMAP), (LPVOID) &bmp); m_sizeImage.cx = bmp.bmWidth; m_sizeImage.cy = bmp.bmHeight; } //**************************************************************************** void CBCGButton::SetImage (UINT uiBmpResId, UINT uiBmpHotResId) { CleanUp (); if (uiBmpResId == 0) { return; } HBITMAP hbmp = (HBITMAP) ::LoadImage ( AfxGetResourceHandle (), MAKEINTRESOURCE (uiBmpResId), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADMAP3DCOLORS); ASSERT (hbmp != NULL); HBITMAP hbmpHot = NULL; if (uiBmpHotResId != 0) { hbmpHot = (HBITMAP) ::LoadImage ( AfxGetResourceHandle (), MAKEINTRESOURCE (uiBmpHotResId), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADMAP3DCOLORS); ASSERT (hbmp != NULL); } SetImage (hbmp, TRUE /* AutoDestroy */, hbmpHot); } //**************************************************************************** void CBCGButton::SetStdImage (CMenuImages::IMAGES_IDS id) { CleanUp (); m_sizeImage = CMenuImages::Size (); m_nStdImageId= id; } //**************************************************************************** void CBCGButton::OnCancelMode() { CButton::OnCancelMode(); if (m_bCaptured) { ReleaseCapture (); m_bCaptured = FALSE; Invalidate (); UpdateWindow (); } } //**************************************************************************** void CBCGButton::OnMouseMove(UINT nFlags, CPoint point) { m_bHover = FALSE; if ((nFlags & MK_LBUTTON) || m_nFlatStyle != BUTTONSTYLE_3D) { BOOL bRedraw = FALSE; CRect rectClient; GetClientRect (rectClient); if (rectClient.PtInRect (point)) { m_bHover = TRUE; if (!m_bHighlighted) { m_bHighlighted = TRUE; bRedraw = TRUE; } if ((nFlags & MK_LBUTTON) && !m_bPushed) { m_bPushed = TRUE; bRedraw = TRUE; } if (!m_bCaptured) { SetCapture (); m_bCaptured = TRUE; bRedraw = TRUE; } } else { if (nFlags & MK_LBUTTON) { if (m_bPushed) { m_bPushed = FALSE; bRedraw = TRUE; } } else if (m_bHighlighted) { m_bHighlighted = FALSE; bRedraw = TRUE; } if (m_bCaptured && (!nFlags & MK_LBUTTON)) { ReleaseCapture (); m_bCaptured = FALSE; bRedraw = TRUE; } } if (bRedraw) { Invalidate (); UpdateWindow (); } } CButton::OnMouseMove(nFlags, point); } //**************************************************************************** void CBCGButton::OnLButtonDown(UINT nFlags, CPoint point) { m_bPushed = TRUE; m_bHighlighted = TRUE; if (!m_bCaptured) { SetCapture (); m_bCaptured = TRUE; } Invalidate (); UpdateWindow (); CButton::OnLButtonDown(nFlags, point); } //**************************************************************************** void CBCGButton::OnLButtonUp(UINT nFlags, CPoint point) { m_bPushed = FALSE; m_bHighlighted = FALSE; Invalidate (); UpdateWindow (); CButton::OnLButtonUp(nFlags, point); if (m_bCaptured) { ReleaseCapture (); m_bCaptured = FALSE; } } //**************************************************************************** CSize CBCGButton::SizeToContent (BOOL bCalcOnly) { ASSERT (GetSafeHwnd () != NULL); CClientDC dc (this); CFont* pOldFont = dc.SelectObject (&globalData.fontRegular); ASSERT(pOldFont != NULL); CString strText; GetWindowText (strText); CSize sizeText = dc.GetTextExtent (strText); int cx = sizeText.cx + m_sizeImage.cx + nImageHorzMargin; if (sizeText.cx > 0) { cx += nImageHorzMargin; } int cy = max (sizeText.cy, m_sizeImage.cy) + nVertMargin * 2; if (!bCalcOnly) { SetWindowPos (NULL, -1, -1, cx, cy, SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER); } dc.SelectObject (pOldFont); return CSize (cx, cy); } //**************************************************************************** BOOL CBCGButton::PreTranslateMessage(MSG* pMsg) { if (m_wndToolTip.GetSafeHwnd () != NULL) { if (pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_LBUTTONUP || pMsg->message == WM_MOUSEMOVE) { m_wndToolTip.RelayEvent(pMsg); } } return CButton::PreTranslateMessage(pMsg); } //**************************************************************************** void CBCGButton::SetTooltip (LPCTSTR lpszToolTipText) { ASSERT (GetSafeHwnd () != NULL); if (lpszToolTipText == NULL) { if (m_wndToolTip.GetSafeHwnd () != NULL) { m_wndToolTip.Activate (FALSE); } } else { if (m_wndToolTip.GetSafeHwnd () != NULL) { m_wndToolTip.UpdateTipText (lpszToolTipText, this); } else { m_wndToolTip.Create (this, TTS_ALWAYSTIP); m_wndToolTip.AddTool (this, lpszToolTipText); } m_wndToolTip.Activate (TRUE); } } //**************************************************************************** void CBCGButton::SetMouseCursor (HCURSOR hcursor) { m_hCursor = hcursor; } //**************************************************************************** void CBCGButton::SetMouseCursorHand () { if (globalData.m_hcurHand == NULL) { CBCGLocalResource locaRes; globalData.m_hcurHand = AfxGetApp ()->LoadCursor (IDC_BCGBARRES_HAND); } SetMouseCursor (globalData.m_hcurHand); } //***************************************************************************** BOOL CBCGButton::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) { if (m_hCursor != NULL) { CRect rectClient; GetClientRect (rectClient); CPoint ptCursor; ::GetCursorPos (&ptCursor); ScreenToClient (&ptCursor); if (rectClient.PtInRect (ptCursor)) { ::SetCursor (m_hCursor); return TRUE; } } return CButton::OnSetCursor(pWnd, nHitTest, message); } //***************************************************************************** void CBCGButton::OnDrawFocusRect (CDC* pDC, const CRect& rectClient) { ASSERT_VALID (pDC); CRect rectFocus = rectClient; if (m_nFlatStyle == BUTTONSTYLE_FLAT) { rectFocus.DeflateRect (2, 2); } else { rectFocus.DeflateRect (3, 3); } pDC->DrawFocusRect (rectFocus); }