// XTButton.cpp : implementation of the CXTButton class. // // This file is a part of the XTREME CONTROLS MFC class library. // (c)1998-2012 Codejock Software, All Rights Reserved. // // THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE // RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN // CONSENT OF CODEJOCK SOFTWARE. // // THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED // IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO // YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A // SINGLE COMPUTER. // // CONTACT INFORMATION: // support@codejock.com // http://www.codejock.com // ///////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "Common/XTPColorManager.h" #include "Common/XTPDrawHelpers.h" #include "Common/XTPImageManager.h" #include "XTThemeManager.h" #include "XTButtonTheme.h" #include "XTButton.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #ifndef WM_QUERYUISTATE #define WM_UPDATEUISTATE 0x0128 #define WM_QUERYUISTATE 0x0129 #define UISF_HIDEACCEL 0x2 #define UISF_HIDEFOCUS 0x1 #endif ///////////////////////////////////////////////////////////////////////////// // CXTButton ///////////////////////////////////////////////////////////////////////////// IMPLEMENT_DYNAMIC(CXTButton, CButton) IMPLEMENT_THEME_HOST(CXTButton) IMPLEMENT_THEME_REFRESH(CXTButton, CButton) CXTButton::CXTButton(CRuntimeClass* pThemeFactoryClass/*=NULL*/) : CXTThemeManagerStyleHost(pThemeFactoryClass ? pThemeFactoryClass : GetThemeFactoryClass()) , m_nBorderGap(4) , m_nImageGap(8) , m_bUserPosition(false) , m_bChecked(false) , m_dwxStyle(BS_XT_FLAT | BS_XT_SHOWFOCUS) , m_sizeImage(CSize(0, 0)) , m_ptImage(CPoint(0, 0)) , m_ptText(CPoint(0, 0)) , m_pIcon(NULL) , m_bPreSubclassInit(true) { m_bOwnerDraw = FALSE; m_bPushed = FALSE; m_bHot = FALSE; } CXTButton::~CXTButton() { CleanUpGDI(); CMDTARGET_RELEASE(m_pIcon); } HICON CXTButton::GetNormalIcon() { return m_pIcon ? (HICON)m_pIcon->GetIcon() : NULL; } HICON CXTButton::GetSelectedIcon() { return m_pIcon ? (HICON)m_pIcon->GetHotIcon() : NULL; } BEGIN_MESSAGE_MAP(CXTButton, CButton) //{{AFX_MSG_MAP(CXTButton) ON_WM_ERASEBKGND() ON_WM_MOUSEMOVE() ON_WM_CREATE() ON_WM_SETFOCUS() ON_WM_KILLFOCUS() ON_MESSAGE(WM_PRINTCLIENT, OnPrintClient) ON_WM_PAINT() ON_WM_SYSCOLORCHANGE() //}}AFX_MSG_MAP ON_MESSAGE_VOID(WM_MOUSELEAVE, OnMouseLeave) ON_MESSAGE(BM_SETSTYLE, OnDefaultAndInvalidate) ON_MESSAGE(BM_SETCHECK, OnDefaultAndInvalidate) ON_MESSAGE(WM_CAPTURECHANGED, OnDefaultAndInvalidate) ON_MESSAGE_VOID(WM_ENABLE, OnInvalidate) ON_MESSAGE(WM_UPDATEUISTATE, OnUpdateUIState) ON_MESSAGE(BM_SETSTATE, OnSetState) ON_MESSAGE(WM_SETTEXT, OnSetText) //}}AFX_MSG_MAP ON_WM_GETDLGCODE() ON_MESSAGE(BM_SETSTYLE, OnSetStyle) END_MESSAGE_MAP() void CXTButton::DrawItem(LPDRAWITEMSTRUCT lpDIS) { GetTheme()->DrawItem(lpDIS, this); } void CXTButton::OnMouseMove(UINT nFlags, CPoint point) { if (GetButtonStyle() == BS_GROUPBOX) return; CButton::OnMouseMove(nFlags, point); CRect rc; GetClientRect(&rc); BOOL bHot = rc.PtInRect(point); if (bHot != m_bHot) { m_bHot = bHot; Invalidate(FALSE); if (m_bHot) { TRACKMOUSEEVENT tme = {sizeof(TRACKMOUSEEVENT), TME_LEAVE, m_hWnd, HOVER_DEFAULT}; _TrackMouseEvent(&tme); } } } LRESULT CXTButton::OnSetState(WPARAM wParam, LPARAM /*lParam*/) { BOOL bVisible = GetStyle() & WS_VISIBLE; if (bVisible) ModifyStyle(WS_VISIBLE, 0); Default(); if (bVisible) ModifyStyle(0, WS_VISIBLE); m_bPushed = (wParam != 0); Invalidate(FALSE); return 0; } void CXTButton::OnSetFocus(CWnd* pOldWnd) { CButton::OnSetFocus(pOldWnd); Invalidate(FALSE); } void CXTButton::OnKillFocus(CWnd* pNewWnd) { CButton::OnKillFocus(pNewWnd); Invalidate(FALSE); } LRESULT CXTButton::OnDefaultAndInvalidate(WPARAM, LPARAM) { LRESULT lResult = Default(); Invalidate(FALSE); return lResult; } void CXTButton::OnInvalidate() { Invalidate(FALSE); } LRESULT CXTButton::OnPrintClient(WPARAM wParam, LPARAM lParam) { if ((lParam & PRF_CLIENT) == 0) return Default(); CDC* pDC = CDC::FromHandle((HDC)wParam); if (pDC) OnDraw(pDC); return 1; } void CXTButton::OnPaint() { CPaintDC dcPaint(this); CXTPBufferDC dc(dcPaint); // device context for painting OnDraw(&dc); } void CXTButton::OnDraw(CDC* pDC) { DRAWITEMSTRUCT dis; ZeroMemory(&dis, sizeof(DRAWITEMSTRUCT)); dis.CtlType = ODT_BUTTON; dis.CtlID = GetDlgCtrlID(); dis.itemState = 0; if (::GetFocus() == m_hWnd) dis.itemState |= ODS_FOCUS; if (m_bPushed) dis.itemState |= ODS_SELECTED; LRESULT dwState = SendMessage(WM_QUERYUISTATE); if (dwState & UISF_HIDEACCEL) dis.itemState |= ODS_NOACCEL; if (dwState & UISF_HIDEFOCUS) dis.itemState |= ODS_NOFOCUSRECT; if (!IsWindowEnabled()) dis.itemState |= ODS_DISABLED; dis.hwndItem = m_hWnd; dis.hDC = pDC->GetSafeHdc(); dis.rcItem = CXTPClientRect(this); DrawItem(&dis); } BYTE CXTButton::GetButtonStyle() const { BYTE bStyle = BYTE(GetStyle() & 0xF); return bStyle; } LRESULT CXTButton::OnUpdateUIState(WPARAM wParam, LPARAM lParam) { LRESULT lResult = ::DefWindowProc(m_hWnd, WM_UPDATEUISTATE, wParam, lParam); Invalidate(FALSE); return lResult; } LRESULT CXTButton::OnSetText(WPARAM wParam, LPARAM lParam) { BOOL bVisible = GetStyle() & WS_VISIBLE; if (bVisible) ModifyStyle(WS_VISIBLE, 0); LRESULT lResult = DefWindowProc(WM_SETTEXT, wParam, lParam); if (bVisible) ModifyStyle(0, WS_VISIBLE); Invalidate(FALSE); return lResult; } BOOL CXTButton::OnEraseBkgnd(CDC* /*pDC*/) { return TRUE; } bool CXTButton::Init() { GetTheme()->RefreshMetrics(); m_bOwnerDraw = m_hWnd && ((GetStyle() & 0xF) == BS_OWNERDRAW); if (m_hWnd) Invalidate(FALSE); return true; } void CXTButton::PreSubclassWindow() { CButton::PreSubclassWindow(); if (m_bPreSubclassInit) { // Initialize the control. Init(); } } int CXTButton::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CButton::OnCreate(lpCreateStruct) == -1) return -1; // Initialize the control. Init(); return 0; } BOOL CXTButton::PreCreateWindow(CREATESTRUCT& cs) { if (!CButton::PreCreateWindow(cs)) return FALSE; // When creating controls dynamically Init() must // be called from OnCreate() and not from // PreSubclassWindow(). m_bPreSubclassInit = false; return TRUE; } UINT CXTButton::OnGetDlgCode() { if (m_bOwnerDraw) { if (GetFocus() == this) return DLGC_DEFPUSHBUTTON | DLGC_BUTTON; return DLGC_BUTTON ; } return CButton::OnGetDlgCode(); } LRESULT CXTButton::OnSetStyle(WPARAM wParam, LPARAM lParam) { if (m_bOwnerDraw) { DWORD dwOldStyle = GetStyle(); ModifyStyle(0, (long)wParam | BS_OWNERDRAW,0); if ((dwOldStyle != GetStyle()) && LOWORD(lParam)) Invalidate(); return 0; } return OnDefaultAndInvalidate(wParam, lParam); } void CXTButton::OnMouseLeave() { OnMouseMove(0, CPoint(-1, -1)); } ////////////////////////////////////////////////////////////////////////// // CSize CXTButton::GetImageSize() const { if (!GetTheme()->IsIconVisible()) return CSize(0, 0); return m_sizeImage; } CPoint CXTButton::GetImagePoint() const { if (!GetTheme()->IsIconVisible()) return CPoint(0, 0); return m_ptImage; } CPoint CXTButton::GetTextPoint() const { if (!GetTheme()->IsIconVisible()) return CPoint(0, 0); return m_ptText; } void CXTButton::CleanUpGDI() { if (m_pIcon) { m_pIcon->Refresh(); } } BOOL CXTButton::SetIcon(CSize size, UINT nID, UINT nHotID/*= 0*/, BOOL bRedraw/*= TRUE*/) { return CXTButton::SetIcon( size, MAKEINTRESOURCE(nID), MAKEINTRESOURCE(nHotID), bRedraw); } BOOL CXTButton::SetIcon(CSize size, LPCTSTR lpszID, LPCTSTR lpszHotID/*= NULL*/, BOOL bRedraw/*= TRUE*/) { CXTPImageManagerIconHandle hIcon; CXTPImageManagerIconHandle hIconHot; hIcon.CreateIconFromResource(lpszID, size); // Return false if the icon handle is NULL. if (hIcon.IsEmpty()) { TRACE0("Failed to load Icon resource.\n"); return FALSE; } // If we are using a pushed image as well... if (lpszHotID) { hIconHot.CreateIconFromResource(lpszHotID, size); // Return false if the icon handle is NULL. if (hIconHot.IsEmpty()) { TRACE0("Failed to load Icon resource.\n"); return FALSE; } } return CXTButton::SetIcon(size, hIcon, hIconHot, bRedraw); } BOOL CXTButton::SetIcon(CSize size, CXTPImageManagerIcon* pIcon, BOOL bRedraw/*= TRUE*/) { m_sizeImage = size; // Construct the icon manager. CMDTARGET_RELEASE(m_pIcon); m_pIcon = pIcon; // Redraw the button. if (::IsWindow(m_hWnd) && bRedraw) Invalidate(); return TRUE; } BOOL CXTButton::SetIcon(CSize size, const CXTPImageManagerIconHandle& hIcon, const CXTPImageManagerIconHandle& hIconHot, BOOL bRedraw/*= TRUE*/) { ASSERT(!hIcon.IsEmpty()); // Save the image size and set the icon // handles to NULL. size = size != CSize(0) ? size : hIcon.GetExtent(); CXTPImageManagerIcon* pIcon = new CXTPImageManagerIcon(0, size.cx, size.cy); pIcon->SetIcon(hIcon); if (!hIconHot.IsEmpty()) pIcon->SetHotIcon(hIconHot); return SetIcon(size, pIcon, bRedraw); } BOOL CXTButton::SetIcon(CSize size, HICON hIcon, HICON hIconHot/*= NULL*/, BOOL bRedraw/*= TRUE*/) { return SetIcon(size, CXTPImageManagerIconHandle(hIcon), CXTPImageManagerIconHandle(hIconHot), bRedraw); } BOOL CXTButton::SetBitmap(CSize size, UINT nID, BOOL bRedraw/*= TRUE*/) { // Free previous resources (if any). CXTPImageManagerIconHandle hIconHandle; BOOL bAlphaBitmap = FALSE; HBITMAP hBitmap = CXTPImageManagerIcon::LoadBitmapFromResource(MAKEINTRESOURCE(nID), &bAlphaBitmap); if (!hBitmap) return FALSE; if (bAlphaBitmap) { hIconHandle = hBitmap; // Will call DeleteObject; } else { CBitmap bmpIcon; bmpIcon.Attach(hBitmap); // convert the bitmap to a transparent icon. HICON hIcon = CXTPTransparentBitmap(bmpIcon).ConvertToIcon(); hIconHandle = hIcon; // Will call DestoyIcon; } if (hIconHandle.IsEmpty()) return FALSE; return CXTButton::SetIcon(size, hIconHandle, CXTPImageManagerIconHandle(), bRedraw); } BOOL CXTButton::SetTextAndImagePos(CPoint ptImage, CPoint ptText, BOOL bRedraw/*= TRUE*/) { m_ptImage = ptImage; m_ptText = ptText; // Redraw the button. if (::IsWindow(m_hWnd) && bRedraw) Invalidate(); m_bUserPosition = TRUE; return TRUE; } DWORD CXTButton::SetXButtonStyle(DWORD dwxStyle, BOOL bRedraw/*= TRUE*/) { DWORD dwOldStyle = m_dwxStyle; m_dwxStyle = dwxStyle; if ((m_dwxStyle & BS_XT_XPFLAT) == BS_XT_XPFLAT) SetTheme(new CXTButtonThemeOfficeXP()); else if ((m_dwxStyle & BS_XT_FLAT) == BS_XT_FLAT) SetTheme(new CXTButtonTheme()); // Redraw the button. if (::IsWindow(m_hWnd) && bRedraw) Invalidate(); return dwOldStyle; } BOOL CXTButton::IsThemeValid() const { return (GetTheme() != NULL); } CXTPImageManagerIcon* CXTButton::GetIcon() const { return m_pIcon; } CString CXTButton::GetButtonText(BOOL bRemoveAmpersand) { CString strText; GetWindowText(strText); if (bRemoveAmpersand) XTPDrawHelpers()->StripMnemonics(strText); return strText; } void CXTButton::SetAlternateColors(COLORREF clr3DFace, COLORREF clr3DHilight, COLORREF clr3DShadow, COLORREF clrBtnText) { if (IsThemeValid()) { GetTheme()->SetAlternateColors( clr3DFace, clr3DHilight, clr3DShadow, clrBtnText); } } void CXTButton::SetColorFace(COLORREF clrFace) { if (IsThemeValid()) { GetTheme()->SetColorFace(clrFace); } } COLORREF CXTButton::GetColorFace() { if (IsThemeValid()) { return GetTheme()->GetColorFace(); } return GetXtremeColor(COLOR_3DFACE); } void CXTButton::SetColorHilite(COLORREF clrHilite) { if (IsThemeValid()) { GetTheme()->SetColorHilite(clrHilite); } } void CXTButton::SetColorShadow(COLORREF clrShadow) { if (IsThemeValid()) { GetTheme()->SetColorShadow(clrShadow); } } void CXTButton::SetColorText(COLORREF clrText) { if (IsThemeValid()) { GetTheme()->SetColorText(clrText); } } void CXTButton::SetXPFlatColors(COLORREF clrBorder, COLORREF clrHighlight, COLORREF clrPressed) { if (IsThemeValid()) { CXTButtonTheme* pButtonTheme = GetTheme(); if (pButtonTheme->GetTheme() == xtThemeOfficeXP) { ((CXTButtonThemeOfficeXP*)pButtonTheme)->SetColorHilite(clrBorder); ((CXTButtonThemeOfficeXP*)pButtonTheme)->SetColorShadow(clrBorder); ((CXTButtonThemeOfficeXP*)pButtonTheme)->SetBackHiliteColor(clrHighlight); ((CXTButtonThemeOfficeXP*)pButtonTheme)->SetBackPushedColor(clrPressed); } } } void CXTButton::ResetImage() { if (IsThemeValid()) { if (GetTheme()->IsIconVisible()) { GetTheme()->ShowIcon(FALSE); } else { GetTheme()->ShowIcon(TRUE); } Invalidate(); } } CFont* CXTButton::SetFontEx(CFont* pFont) { CFont* pOldFont = GetFont(); CButton::SetFont(pFont); return pOldFont; }