// XTPControl.cpp : implementation of the CXTPControl class. // // This file is a part of the XTREME COMMANDBARS 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 "Resource.h" #include "Common/Resource.h" #include "Common/XTPResourceManager.h" #include "Common/XTPImageManager.h" #include "Common/XTPSystemHelpers.h" #include "Common/XTPHookManager.h" #include "Common/XTPColorManager.h" #include "Common/XTPDrawHelpers.h" #include "XTPCommandBarsDefines.h" #include "XTPShortcutManager.h" #include "XTPControl.h" #include "XTPControls.h" #include "XTPMouseManager.h" #include "XTPCommandBar.h" #include "XTPPaintManager.h" #include "XTPCommandBars.h" #include "XTPPopupBar.h" #include "XTPCustomizeTools.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif IMPLEMENT_DYNAMIC(CXTPControlAction, CCmdTarget) ////////////////////////////////////////////////////////////////////////// // CXTPControlAction CXTPControlAction::CXTPControlAction(CXTPControlActions* pActions) { m_nId = 0; m_nIconId = 0; m_nHelpId = 0; m_nTag = 0; m_bVisible = TRUE; m_bChecked = FALSE; m_bEnabled = TRUE; m_pTarget = NULL; m_pActions = pActions; } CXTPControlAction::~CXTPControlAction() { ASSERT(m_arrControls.GetSize() == 0); if (m_pTarget) { CMDTARGET_RELEASE(m_pTarget); } } void CXTPControlAction::AddControl(CXTPControl* pControl) { for (int i = 0; i < m_arrControls.GetSize(); i++) { if (m_arrControls[i] == pControl) return; } m_arrControls.Add(pControl); pControl->m_bEnabled = -1; pControl->m_bChecked = -1; pControl->m_nId = m_nId; pControl->m_strCaption.Empty(); pControl->m_strTooltipText.Empty(); pControl->m_strDescriptionText.Empty(); pControl->m_strCategory.Empty(); pControl->m_strShortcutText.Empty(); pControl->m_strKeyboardTip.Empty(); } void CXTPControlAction::RemoveControl(CXTPControl* pControl) { for (int i = 0; i < m_arrControls.GetSize(); i++) { if (m_arrControls[i] == pControl) { m_arrControls.RemoveAt(i); pControl->m_bEnabled = TRUE; pControl->m_bChecked = FALSE; return; } } } void CXTPControlAction::OnChanged(int nProperty) { for (int i = 0; i < m_arrControls.GetSize(); i++) { m_arrControls[i]->OnActionChanged(nProperty); } } void CXTPControlAction::OnChanging(int nProperty) { for (int i = 0; i < m_arrControls.GetSize(); i++) { m_arrControls[i]->OnActionChanging(nProperty); } } void CXTPControlAction::RedrawControls() { for (int i = 0; i < m_arrControls.GetSize(); i++) { m_arrControls[i]->RedrawParent(); } } void CXTPControlAction::RepositionControls() { for (int i = 0; i < m_arrControls.GetSize(); i++) { m_arrControls[i]->DelayLayoutParent(); } } void CXTPControlAction::OnRemoved() { while (m_arrControls.GetSize() > 0) { m_arrControls[0]->SetAction(NULL); } } void CXTPControlAction::SetCaption(UINT nIDCaption) { CString strCaption; if (strCaption.LoadString(nIDCaption)) { SetCaption(strCaption); } } void CXTPControlAction::SetCaption(LPCTSTR lpszCaption) { CString strCaption(lpszCaption); int nShortCutPos = strCaption.Find ('\t'); if (nShortCutPos != -1) { strCaption.ReleaseBuffer(nShortCutPos); } if (m_strCaption != strCaption) { OnChanging(3); m_strCaption = strCaption; OnChanged(3); RepositionControls(); } } void CXTPControlAction::SetEditHint(LPCTSTR lpszEditHint) { CString strEditHint(lpszEditHint); if (m_strEditHint != strEditHint) { OnChanging(4); m_strEditHint = strEditHint; OnChanged(4); } } void CXTPControlAction::SetPrompt(LPCTSTR lpszPrompt) { if (lpszPrompt == NULL || lpszPrompt[0] == _T('\0')) return; if (_tcschr(lpszPrompt, _T('\n')) != NULL) { AfxExtractSubString(m_strTooltipText, lpszPrompt, 1); AfxExtractSubString(m_strDescriptionText, lpszPrompt, 0); } else { m_strDescriptionText = m_strTooltipText = lpszPrompt; } if (m_strCaption.IsEmpty()) { AfxExtractSubString(m_strCaption, lpszPrompt, 2); } if (m_strKeyboardTip.IsEmpty()) { AfxExtractSubString(m_strKeyboardTip, lpszPrompt, 3); } } BOOL CXTPControlAction::GetEnabled() const { if (GetCommandBars()->IsCustomizeMode()) return TRUE; return m_bEnabled; } CXTPCommandBars* CXTPControlAction::GetCommandBars() const { return m_pActions->m_pCommandBars; } CXTPControl* CXTPControlAction::GetControl(int nIndex) const { return m_arrControls[nIndex]; } int CXTPControlAction::GetCount() const { return (int)m_arrControls.GetSize(); } ////////////////////////////////////////////////////////////////////////// // CXTPControlActions CXTPControlActions::CXTPControlActions(CXTPCommandBars* pCommandBars) { m_pCommandBars = pCommandBars; } CXTPControlActions::~CXTPControlActions() { RemoveAll(); } CXTPControlAction* CXTPControlActions::GetAt(int nIndex) const { return m_arrActions.GetAt(nIndex); } int CXTPControlActions::GetCount() const { return (int)m_arrActions.GetSize(); } CXTPControlAction* CXTPControlActions::FindAction(int nId) const { if (nId <= 0 || nId >= 0xFFFFFFF) return NULL; int num = GetCount(); if (num == 0) return NULL; CXTPControlAction* const* lo = m_arrActions.GetData(); CXTPControlAction* const* hi = lo + (num - 1); CXTPControlAction* const* mid; while (lo <= hi) { int half = num / 2; if (half) { mid = lo + (num & 1 ? half : (half - 1)); if ((*mid)->GetID() == nId) return (*mid); if ((*mid)->GetID() > nId) { hi = mid - 1; num = num & 1 ? half : half - 1; } else { lo = mid + 1; num = half; } } else if (num) return (*lo)->GetID() == nId ? (*lo) : NULL; else break; } return NULL; } void CXTPControlActions::RemoveAll() { for (int i = 0; i < GetCount(); i++) { CXTPControlAction* pAction = GetAt(i); pAction->OnRemoved(); pAction->InternalRelease(); } m_arrActions.RemoveAll(); } void CXTPControlActions::Remove(int nId) { for (int i = 0; i < GetCount(); i++) { CXTPControlAction* pAction = GetAt(i); if (pAction->GetID() == nId) { m_arrActions.RemoveAt(i); pAction->OnRemoved(); pAction->InternalRelease(); return; } } } void CXTPControlActions::Insert(CXTPControlAction* pAction) { int nIndex = 0; for (; nIndex < GetCount(); nIndex++) { if (GetAt(nIndex)->GetID() > pAction->GetID()) break; } m_arrActions.InsertAt(nIndex, pAction); } void CXTPControlActions::SetActionId(CXTPControlAction* pAction, int nId) { ASSERT(FindAction(nId) == NULL); pAction->m_nId = nId; } CXTPControlAction* CXTPControlActions::Add(int nId, CXTPControlAction* pAction) { SetActionId(pAction, nId); CString strPrompt; if (XTPResourceManager()->LoadString(&strPrompt, nId)) { pAction->SetPrompt(strPrompt); } Insert(pAction); return pAction; } CXTPControlAction* CXTPControlActions::Add(int nId) { CXTPControlAction* pAction = FindAction(nId); if (pAction) return pAction; pAction = new CXTPControlAction(this); return Add(nId, pAction); } void CXTPControlActions::CreateFromMenu(CMenu* pMenu) { int nCount = ::GetMenuItemCount(pMenu->m_hMenu); for (int nIndex = 0; nIndex < nCount; nIndex++) { // Check to see if the item is a separator, we don't want // to use GetMenuItemID(i) because it may not equal zero. MENUITEMINFO info = { sizeof(MENUITEMINFO), MIIM_TYPE | MIIM_STATE}; ::GetMenuItemInfo(pMenu->m_hMenu, nIndex, TRUE, &info); int nID = (int)pMenu->GetMenuItemID(nIndex); BOOL bSeparator = ((info.fType & MFT_SEPARATOR) == MFT_SEPARATOR) || (nID == 0); if (!bSeparator) { CMenu* pPopupMenu = pMenu->GetSubMenu(nIndex); CString strCaption; XTPResourceManager()->GetMenuLocaleString(pMenu, nIndex, strCaption, MF_BYPOSITION); if (pPopupMenu) { nID = 0; } int iPos = strCaption.Find(_T('\t')); if (pPopupMenu && iPos > 0) { nID = _ttoi(strCaption.Mid(iPos + 1)); strCaption.ReleaseBuffer(iPos); } if (nID > 0) { CXTPControlAction* pAction = Add(nID); pAction->SetCaption(strCaption); CString strPrompt; if (XTPResourceManager()->LoadString(&strPrompt, nID)) { pAction->SetPrompt(strPrompt); } } if (pPopupMenu) { CreateFromMenu(pPopupMenu); } } } } ////////////////////////////////////////////////////////////////////////// // CXTPControl CXTPControl::CXTPControl() { EnableAutomation(); m_nId = 0; m_nIconId = 0; m_nHelpId = 0; m_nCustomIconId = 0; m_nTag = 0; m_nIndex = 0; m_dwFlags = 0; m_rcControl.SetRectEmpty(); m_rcRow.SetRectEmpty(); m_pParent = 0; m_pControls = 0; m_bExpanded = FALSE; m_bChecked = FALSE; m_bEnabled = TRUE; m_bBeginGroup = FALSE; m_bEnabled = TRUE; m_bTemporary = FALSE; m_bSelected = FALSE; m_bPressed = FALSE; m_bWrap = FALSE; m_dwHideFlags = xtpNoHide; m_controlType = xtpControlError; m_bDefaultItem = FALSE; m_buttonStyle = xtpButtonAutomatic; m_buttonCustomStyle = xtpButtonUndefined; m_buttonRibbonStyle = xtpButtonAutomatic; m_bCloseSubMenuOnClick = TRUE; m_pRibbonGroup = NULL; m_pAction = 0; m_nWidth = 0; m_nHeight = 0; m_szIcon = CSize(0, 0); m_nExecuteOnPressInterval = 0; } CXTPControl::~CXTPControl() { if (m_pAction) { m_pAction->RemoveControl(this); m_pAction = NULL; } } void CXTPControl::SetAction(CXTPControlAction* pAction) { if (m_pAction) { m_pAction->RemoveControl(this); m_pAction = NULL; } if (pAction) { m_pAction = pAction; m_pAction->AddControl(this); } } void CXTPControl::OnRemoved() { SetAction(NULL); } XTPButtonStyle CXTPControl::GetStyle() const { return m_buttonCustomStyle != xtpButtonUndefined ? m_buttonCustomStyle : m_buttonStyle != xtpButtonAutomatic ? m_buttonStyle : m_buttonRibbonStyle != xtpButtonAutomatic || !m_pParent ? m_buttonRibbonStyle : m_pParent->GetDefaultButtonStyle(); } CSize CXTPControl::GetSize(CDC* pDC) { return GetPaintManager()->DrawControl(pDC, this, FALSE); } void CXTPControl::Draw(CDC* pDC) { GetPaintManager()->DrawControl(pDC, this); } void CXTPControl::DelayRedrawParent() { if (m_pParent && IsWindow(m_pParent->GetSafeHwnd())) ((CXTPCommandBar*)m_pParent)->DelayRedraw(); } void CXTPControl::DelayLayoutParent() { if (m_pParent) m_pParent->DelayLayout(); } void CXTPControl::RedrawParent(BOOL bAnimate) { if (!IsVisible()) return; if (m_pParent) m_pParent->Redraw(GetRect(), bAnimate); } void CXTPControl::ScreenToClient(CPoint* point) { ASSERT(m_pParent); if (m_pParent) ((CWnd*)m_pParent)->ScreenToClient(point); } BOOL CXTPControl::OnSetSelected(int bSelected) { if (bSelected == m_bSelected) return FALSE; if (IsKeyboardSelected(bSelected) && m_pParent->m_nPopuped != GetIndex()) m_pParent->SetPopuped(-1); m_bSelected = bSelected; m_pParent->OnControlSelected(bSelected, this); if (GetEnabled() || IsKeyboardSelected(bSelected) || !bSelected) RedrawParent(!bSelected); return TRUE; } void CXTPControl::OnMouseHover() { if (m_pParent->SetPopuped(-1)) { if (m_pParent->IsTrackingMode() == TRUE_POPUP && m_pParent->GetPosition() != xtpBarPopup) m_pParent->SetTrackingMode(FALSE); } } void CXTPControl::SetPrompt(LPCTSTR lpszPrompt) { if (lpszPrompt == NULL || lpszPrompt[0] == _T('\0')) return; if (_tcschr(lpszPrompt, _T('\n')) != NULL) { AfxExtractSubString(m_strTooltipText, lpszPrompt, 1); AfxExtractSubString(m_strDescriptionText, lpszPrompt, 0); } else { m_strDescriptionText = m_strTooltipText = lpszPrompt; } if (m_strCaption.IsEmpty()) { if (!AfxExtractSubString(m_strCaption, lpszPrompt, 2) || m_strCaption.IsEmpty()) { m_strCaption = m_strTooltipText; OnCaptionChanged(); } } if (m_strKeyboardTip.IsEmpty()) { AfxExtractSubString(m_strKeyboardTip, lpszPrompt, 3); } } void CXTPControl::SetID(int nId) { if (m_nId == nId) return; CString strPrompt; if (XTPResourceManager()->LoadString(&strPrompt, nId)) { SetPrompt(strPrompt); } m_nId = nId; } void CXTPControl::OnActionChanged(int nProperty) { if (nProperty == 3) { OnCaptionChanged(); } if (nProperty == 0) { OnEnabledChanged(); } } void CXTPControl::SetCaption(UINT nIDCaption) { CString strCaption; if (strCaption.LoadString(nIDCaption)) { SetCaption(strCaption); } } void CXTPControl::SetCaption(LPCTSTR lpszCaption) { CString strCaption(lpszCaption); BOOL bDelayLayout = FALSE; int nShortCutPos = strCaption.Find ('\t'); if (nShortCutPos != -1) { CString strShortcutTextAuto = strCaption.Mid(nShortCutPos + 1); if (m_strShortcutTextAuto != strShortcutTextAuto) { m_strShortcutTextAuto = strShortcutTextAuto; bDelayLayout = TRUE; } strCaption.ReleaseBuffer(nShortCutPos); } if (m_strCaption != strCaption) { m_strCaption = strCaption; OnCaptionChanged(); bDelayLayout = TRUE; } if (bDelayLayout) { DelayLayoutParent(); } } AFX_INLINE void NotifyExecute(CXTPControl* pControl, CWnd* pOwner) { NMXTPCONTROL tagNMCONTROL; if (pControl->NotifySite(pOwner, CBN_XTP_EXECUTE, &tagNMCONTROL) == 0) { pOwner->SendMessage(WM_COMMAND, pControl->GetID()); } } //Click Helper void CXTPControl::ClickToolBarButton(CRect rcActiveRect) { #define XTP_TID_CLICKTICK 0x10AD if (rcActiveRect.IsRectEmpty()) rcActiveRect = m_rcControl; m_pParent->SetPopuped(-1); m_pParent->SetSelected(m_nIndex); m_bPressed = TRUE; RedrawParent(); InternalAddRef(); BOOL bExecuteOnTimer = m_nExecuteOnPressInterval > 0; CWnd* pOwner = m_pParent->GetOwnerSite(); m_pParent->SetCapture(); HWND hWndCapture = m_pParent->GetSafeHwnd(); CPoint pt(0, 0); BOOL bClick = FALSE; if (bExecuteOnTimer) { m_pParent->SetTimer(XTP_TID_CLICKTICK, m_nExecuteOnPressInterval, NULL); NotifyExecute(this, pOwner); } while (::GetCapture() == hWndCapture) { MSG msg; VERIFY(::GetMessage(&msg, NULL, 0, 0)); if (msg.message == WM_LBUTTONUP) { bClick = m_bSelected && ((!pt.x && !pt.y) || rcActiveRect.PtInRect(pt)); break; } if (m_pParent == NULL) break; if (msg.message == WM_TIMER && msg.wParam == XTP_TID_CLICKTICK) { if (m_bSelected) { NotifyExecute(this, pOwner); } } if (msg.message == WM_MOUSEMOVE) { pt = CPoint(LOWORD(msg.lParam), HIWORD(msg.lParam)); if (OnSetSelected(rcActiveRect.PtInRect(pt))) { RedrawParent(); } continue; } DispatchMessage (&msg); } if (bExecuteOnTimer && m_pParent->GetSafeHwnd()) { m_pParent->KillTimer(XTP_TID_CLICKTICK); } m_bPressed = bClick && !bExecuteOnTimer && NeedPressOnExecute() ? TRUE_KEYBOARD : FALSE; ReleaseCapture(); if (!bExecuteOnTimer && m_bSelected && m_pParent) { m_pParent->SetSelected(-1); m_bSelected = FALSE; m_pParent->m_nClickedControl = GetIndex(); } if (bClick && !bExecuteOnTimer) { OnExecute(); if (m_bPressed) { m_bPressed = FALSE; RedrawParent(); } } else if (bClick && m_pParent->GetType() == xtpBarTypePopup && m_bCloseSubMenuOnClick) { m_bPressed = FALSE; OnExecute(); } else { RedrawParent(); } InternalRelease(); } LRESULT CXTPControl::NotifySite(UINT code) { if (!m_pParent) return 0; NMXTPCONTROL tagNMCONTROL; return NotifySite(m_pParent->GetOwnerSite(), code, &tagNMCONTROL); } LRESULT CXTPControl::NotifySite(UINT code, NMXTPCONTROL* pNM) { if (!m_pParent) return 0; return NotifySite(m_pParent->GetOwnerSite(), code, pNM); } LRESULT CXTPControl::NotifySite(CWnd* pSite, UINT code, NMXTPCONTROL* pNM) { if (pSite == 0) { if (!m_pParent) return 0; pSite = m_pParent->GetOwnerSite(); } pNM->hdr.code = code ; pNM->hdr.idFrom = GetID(); pNM->hdr.hwndFrom = 0; pNM->pControl = this; LRESULT lResult = pSite->SendMessage(WM_XTP_COMMAND, GetID(), (LPARAM)pNM); if (lResult || !m_pParent) return lResult; AFX_NOTIFY notify; notify.pResult = &lResult; notify.pNMHDR = (NMHDR*)pNM; if (pSite->OnCmdMsg(GetID(), MAKELONG(code, WM_NOTIFY), ¬ify, NULL)) { return lResult; } return 0; } BOOL CXTPControl::NeedPressOnExecute() const { if (m_pParent && m_pParent->GetPosition() == xtpBarPopup) return FALSE; return TRUE; } void CXTPControl::OnExecute() { XTPSoundManager()->PlaySystemSound(xtpSoundMenuCommand); m_bPressed = NeedPressOnExecute() ? TRUE_KEYBOARD : FALSE; CXTPCommandBar* pCommandBar = m_pParent->GetRootParent(); BOOL bRecursePopup = pCommandBar->m_bRecursePopup; CWnd* pOwner = m_pParent->GetOwnerSite(); CXTPCommandBars* pCommandBars = m_pParent->GetCommandBars(); if (pCommandBars) { if (m_nId) pCommandBars->SetCommandUsed(m_nId); CXTPPopupBar* pPopupBar = DYNAMIC_DOWNCAST(CXTPPopupBar, m_pParent); if (pPopupBar && pPopupBar->GetControlPopup() && ((CXTPControl*)pPopupBar->GetControlPopup())->GetID()) { pCommandBars->SetCommandUsed(((CXTPControl*)pPopupBar->GetControlPopup())->GetID()); } } if (pCommandBar->m_pReturnCmd) { if (bRecursePopup) pCommandBar->OnTrackLost(); else if (pCommandBars) pCommandBars->ClosePopups(); else XTPMouseManager()->SendTrackLost(); *pCommandBar->m_pReturnCmd = m_nId; return; } InternalAddRef(); if (m_bCloseSubMenuOnClick) { if (bRecursePopup) pCommandBar->OnTrackLost(); else if (pCommandBars) pCommandBars->ClosePopups(); else XTPMouseManager()->SendTrackLost(); } if (m_nId == 0) { InternalRelease(); return; } NotifyExecute(this, pOwner); if ((!m_bCloseSubMenuOnClick || m_bPressed) && m_pParent) { m_bPressed = FALSE; m_pParent->OnIdleUpdateCmdUI(0, 0); RedrawParent(); } InternalRelease(); } BOOL CXTPControl::IsCursorOver() const { CPoint pt; GetCursorPos(&pt); m_pParent->ScreenToClient(&pt); return m_rcControl.PtInRect(pt); } void CXTPControl::Copy(CXTPControl* pControl, BOOL /*bRecursive*/) { m_nId = pControl->m_nId; SetAction(pControl->GetAction()); m_nTag = pControl->m_nTag; m_dwFlags = pControl->m_dwFlags; m_controlType = pControl->m_controlType; m_strCaption = pControl->m_strCaption; m_strShortcutText = pControl->m_strShortcutText; m_strShortcutTextAuto = pControl->m_strShortcutTextAuto; m_strTooltipText = pControl->m_strTooltipText; m_strDescriptionText = pControl->m_strDescriptionText; m_strParameter = pControl->m_strParameter; m_strKeyboardTip = pControl->m_strKeyboardTip; m_nCustomIconId = pControl->m_nCustomIconId; m_nIconId = pControl->m_nIconId; m_nHelpId = pControl->m_nHelpId; m_bTemporary = pControl->m_bTemporary; m_strCustomCaption = pControl->m_strCustomCaption; m_strCategory = pControl->m_strCategory; m_dwHideFlags = pControl->m_dwHideFlags & ~(xtpHideWrap | xtpHideScroll | xtpHideDockingPosition | xtpHideExpand); m_bDefaultItem = pControl->m_bDefaultItem; m_bEnabled = pControl->m_bEnabled; m_bChecked = pControl->m_bChecked; m_buttonCustomStyle = pControl->m_buttonCustomStyle; m_buttonStyle = pControl->m_buttonStyle; m_nWidth = max(GetCustomizeMinWidth(), pControl->m_nWidth); m_nHeight = pControl->m_nHeight; m_szIcon = pControl->m_szIcon; m_bBeginGroup = pControl->m_bBeginGroup; m_bCloseSubMenuOnClick = pControl->m_bCloseSubMenuOnClick; m_nExecuteOnPressInterval = pControl->m_nExecuteOnPressInterval; m_mapDocTemplatesAssigned.Copy(pControl->m_mapDocTemplatesAssigned); m_mapDocTemplatesExcluded.Copy(pControl->m_mapDocTemplatesExcluded); OnCaptionChanged(); } BOOL CXTPControl::Compare(CXTPControl* pOther) { if (GetStyle() != pOther->GetStyle()) return FALSE; if (GetType() != pOther->GetType()) return FALSE; if (GetID() != pOther->GetID()) return FALSE; if (GetFlags() != pOther->GetFlags()) return FALSE; if (GetBeginGroup() != pOther->GetBeginGroup()) return FALSE; if (GetIconId() != pOther->GetIconId()) return FALSE; if (m_strCaption != pOther->m_strCaption) return FALSE; if (m_strTooltipText != pOther->m_strTooltipText) return FALSE; if (m_strDescriptionText != pOther->m_strDescriptionText) return FALSE; if (m_strCustomCaption != pOther->m_strCustomCaption) return FALSE; if (m_buttonCustomStyle != pOther->m_buttonCustomStyle) return FALSE; if (m_strParameter != pOther->m_strParameter) return FALSE; if ((m_dwHideFlags & xtpHideCustomize) != (pOther->m_dwHideFlags & xtpHideCustomize)) return FALSE; if (m_nWidth != pOther->m_nWidth) return FALSE; return TRUE; } IMPLEMENT_XTP_CONTROL(CXTPControl, CCmdTarget) BOOL CXTPControl::IsCustomizeMode() const { return m_pParent ? m_pParent->IsCustomizeMode() : FALSE; } void CXTPControl::OnInvertTracker(CDC* pDC, CRect rect) { ASSERT(!rect.IsRectEmpty()); pDC->InvertRect(CRect(rect.left, rect.top, rect.right, rect.top + 2)); pDC->InvertRect(CRect(rect.left, rect.bottom - 2, rect.right, rect.bottom)); pDC->InvertRect(CRect(rect.left, rect.top + 2, rect.left + 2, rect.bottom - 2)); pDC->InvertRect(CRect(rect.right - 2, rect.top + 2, rect.right, rect.bottom - 2)); } void CXTPControl::OnCustomizeMouseMove(CPoint point) { if (IsCustomizeResizeAllow() && m_rcControl.PtInRect(point) && ((point.x - m_rcControl.left <= 2) || (m_rcControl.right - point.x <= 2))) { ::SetCursor(XTPResourceManager()->LoadCursor(XTP_IDC_VRESIZE)); } } BOOL CXTPControl::CustomizeStartResize(CPoint point) { if (m_rcControl.PtInRect(point) && ((point.x - m_rcControl.left <= 2) || (m_rcControl.right - point.x <= 2))) { CXTPCommandBars* pCommandBars = m_pParent->GetCommandBars(); ASSERT(pCommandBars); ASSERT(pCommandBars->m_pDragSelected == this); pCommandBars->m_pDragSelected = NULL; m_pParent->Redraw(); m_pParent->UpdateWindow(); CRect rectTracker = m_rcControl; m_pParent->ClientToScreen(rectTracker); m_pParent->SetCapture(); ::SetCursor(XTPResourceManager()->LoadCursor(XTP_IDC_VRESIZE)); CDC* pDC = 0; CWnd* pWnd = CWnd::GetDesktopWindow(); if (pWnd->LockWindowUpdate()) pDC = pWnd->GetDCEx(NULL, DCX_WINDOW | DCX_CACHE | DCX_LOCKWINDOWUPDATE); else pDC = pWnd->GetDCEx(NULL, DCX_WINDOW | DCX_CACHE); OnInvertTracker(pDC, rectTracker); int nMinWidth = GetCustomizeMinWidth(); BOOL bLeftAnchor = (point.x - m_rcControl.left <= 2); LONG& lTrackerAnchor = bLeftAnchor ? rectTracker.left : rectTracker.right; int nOffset = bLeftAnchor ? m_rcControl.left - point.x : m_rcControl.right - point.x; BOOL bAccept = FALSE; while (CWnd::GetCapture() == m_pParent) { MSG msg; if (!GetMessage(&msg, NULL, 0, 0)) break; if (msg.message == WM_MOUSEMOVE) { point = CPoint(msg.lParam); m_pParent->ClientToScreen(&point); point.x += nOffset; point.x = bLeftAnchor ? min(point.x, rectTracker.right - nMinWidth) : max(point.x, rectTracker.left + nMinWidth); if (lTrackerAnchor != point.x) { OnInvertTracker(pDC, rectTracker); lTrackerAnchor = point.x; OnInvertTracker(pDC, rectTracker); } } else if (msg.message == WM_KEYDOWN && msg.wParam == VK_ESCAPE) break; else if (msg.message == WM_LBUTTONUP) { bAccept = TRUE; break; } else ::DispatchMessage(&msg); } OnInvertTracker(pDC, rectTracker); if (CWnd::GetCapture() == m_pParent) ReleaseCapture(); pWnd->UnlockWindowUpdate(); if (pDC != NULL) { pWnd->ReleaseDC(pDC); pDC = NULL; } pCommandBars->m_pDragSelected = this; int nWidth = rectTracker.Width(); if (bAccept && rectTracker.Width() != m_rcControl.Width()) { if (GetParent()->GetType() == xtpBarTypePopup) nWidth -= GetPaintManager()->GetPopupBarGripperWidth(GetParent()); SetWidth(nWidth); m_pParent->OnRecalcLayout(); } m_pParent->Redraw(); return TRUE; } return FALSE; } void CXTPControl::CustomizeStartDrag(CPoint pt) { ASSERT(m_pParent); if (!m_pParent) return; if (m_pParent->m_nPopuped != m_nIndex) { m_pParent->SetPopuped(-1); m_pParent->SetSelected(-1); } CXTPCommandBars* pCommandBars = m_pParent->GetCommandBars(); ASSERT(pCommandBars); if (!pCommandBars) return; if ((pCommandBars->m_pDragSelected == this) && IsCustomizeResizeAllow() && CustomizeStartResize(pt)) { return; } pCommandBars->SetDragControl(this); if (GetFlags() & xtpFlagNoMovable) return; CXTPCustomizeDropSource* pDropSource = pCommandBars->GetDropSource(); DROPEFFECT dropEffect = pDropSource->DoDragDrop(this); if (dropEffect == DROPEFFECT_NONE || dropEffect == DROPEFFECT_MOVE) { CXTPCommandBar* pParent = m_pParent; pParent->SetPopuped(-1); pParent->SetSelected(-1); if (pCommandBars->GetDragControl() == this) pCommandBars->SetDragControl(NULL); if (GetBeginGroup() && m_nIndex < m_pControls->GetCount() - 1) m_pControls->GetAt(m_nIndex + 1)->SetBeginGroup(TRUE); if (m_nIndex == 0 && m_pControls->GetCount() > 1) m_pControls->GetAt(1)->SetBeginGroup(FALSE); m_pControls->Remove(this); pParent->OnRecalcLayout(); } pCommandBars->SetDragControl(pCommandBars->GetDragControl()); } void CXTPControl::OnCustomizeDragOver(CXTPControl* /*pDataObject*/, CPoint /*point*/, DROPEFFECT& /*dropEffect*/) { m_pParent->SetPopuped(-1); m_pParent->SetSelected(-1); } BOOL CXTPControl::IsCustomizeDragOverAvail(CXTPCommandBar* /*pCommandBar*/, CPoint /*point*/, DROPEFFECT& /*dropEffect*/) { return TRUE; } BOOL CXTPControl::IsCustomizeResizeAllow() const { return FALSE; } CXTPImageManager* CXTPControl::GetImageManager() const { if (m_pParent) return m_pParent->GetImageManager(); if (m_pControls) { CXTPCommandBars* pCommandBars = m_pControls->GetCommandBars(); if (pCommandBars) return pCommandBars->GetImageManager(); } return XTPImageManager(); } CXTPPaintManager* CXTPControl::GetPaintManager() const { if (m_pParent) return m_pParent->GetPaintManager(); if (m_pControls) { CXTPCommandBars* pCommandBars = m_pControls->GetCommandBars(); if (pCommandBars) return pCommandBars->GetPaintManager(); } return XTPPaintManager(); } CXTPImageManagerIcon* CXTPControl::GetImage(int nWidth) const { if (GetIconId() != 0) return GetImageManager()->GetImage(GetIconId(), nWidth); return NULL; } void CXTPControl::SetExpanded(BOOL bExpanded) { m_bExpanded = bExpanded; if (!bExpanded) SetHideFlags(GetHideFlags() & ~xtpHideExpand); } BOOL CXTPControl::IsItemDefault() const { return m_bDefaultItem; } void CXTPControl::SetItemDefault(BOOL bDefault) { if (bDefault != m_bDefaultItem) { m_bDefaultItem = bDefault; DelayLayoutParent(); } } void CXTPControl::SetFlags(DWORD dwFlags) { m_dwFlags = dwFlags; } DWORD CXTPControl::GetFlags() const { return m_dwFlags; } BOOL CXTPControl::IsCustomizeMovable() const { if (m_pParent && m_pParent->IsCustomizable() && ((GetFlags() & xtpFlagNoMovable) == 0)) return TRUE; if (!m_pParent) return FALSE; CXTPCommandBars* pCommandBars = m_pParent->GetCommandBars(); if (pCommandBars && pCommandBars->m_bDesignerMode) return TRUE; return FALSE; } void CXTPControl::CDocTemplateMap::Copy(CDocTemplateMap& map) { RemoveAll(); UINT nIDResource; BOOL bValue; POSITION pos = map.GetStartPosition(); while (pos) { map.GetNextAssoc(pos, nIDResource, bValue); SetAt(nIDResource, bValue); } } CXTPControl* CXTPControl::FromUI(CCmdUI* pCmdUI) { CXTPCommandBar* pCommandBar = DYNAMIC_DOWNCAST(CXTPCommandBar, pCmdUI->m_pOther); if (!pCommandBar) return NULL; CXTPControls* pControls = pCommandBar->GetControls(); if ((int)pCmdUI->m_nIndex < pControls->GetCount()) return pControls->GetAt(pCmdUI->m_nIndex); return NULL; } void CXTPControl::OnLButtonDown(CPoint point) { if (!m_pParent->IsCustomizeMode() || IsCustomizeMovable()) OnClick(FALSE, point); } BOOL CXTPControl::OnLButtonDblClk(CPoint point) { OnClick(FALSE, point); return TRUE; } void CXTPControl::Reset() { if (m_nCustomIconId != 0 || !m_strCustomCaption.IsEmpty() || m_buttonCustomStyle != xtpButtonUndefined) { m_nCustomIconId = 0; m_buttonCustomStyle = xtpButtonUndefined; if (!m_strCustomCaption.IsEmpty()) { m_strCustomCaption = _T(""); OnCaptionChanged(); } GetParent()->OnRecalcLayout(); } } void CXTPControl::SetCustomIcon(HICON hIcon) { CXTPImageManager* pImageManager = GetImageManager(); if (pImageManager) { m_nCustomIconId = pImageManager->AddCustomIcon(hIcon); } } CSize CXTPControl::GetButtonSize() const { return m_pParent->GetButtonSize(); } CSize CXTPControl::GetIconSize() const { if (m_szIcon != CSize(0, 0)) return m_szIcon; return m_pParent->GetIconSize(); } BOOL CXTPControl::GetEnabled() const { BOOL bEnabled = m_pParent ? m_pParent->IsControlEnabled(this) : -1; if (bEnabled != -1) return bEnabled; return m_bEnabled == -1 && m_pAction ? m_pAction->GetEnabled() : m_bEnabled; } #ifndef _XTP_INCLUDE_RIBBON BOOL CXTPControl::HasDwmCompositedRect() const { if (!GetParent()) return FALSE; if (GetParent()->IsDwmEnabled()) return TRUE; return FALSE; } #endif void CXTPControl::OnUnderlineActivate() { OnExecute(); } BOOL CXTPControl::IsCaptionVisible() const { if (GetParent()->GetType() == xtpBarTypePopup) return TRUE; if (GetCaption().IsEmpty()) return FALSE; XTPButtonStyle buttonStyle = GetStyle(); if ((buttonStyle == xtpButtonCaption) || (buttonStyle == xtpButtonIconAndCaption) || (buttonStyle == xtpButtonIconAndCaptionBelow)) return TRUE; if (buttonStyle == xtpButtonIcon) return FALSE; switch (GetType()) { case xtpControlPopup: case xtpControlLabel: case xtpControlCheckBox: case xtpControlRadioButton: return TRUE; case xtpControlButton: case xtpControlButtonPopup: case xtpControlSplitButtonPopup: CXTPImageManagerIcon* pImage = GetImage(0); return pImage == NULL; } return FALSE; } CCmdTarget* CXTPControl::GetAccessible() { return this; } HRESULT CXTPControl::GetAccessibleParent(IDispatch* FAR* ppdispParent) { SAFE_MANAGE_STATE(m_pModuleState); *ppdispParent = NULL; if (m_pParent) { *ppdispParent = m_pParent->GetIDispatch(TRUE); return S_OK; } return E_FAIL; } HRESULT CXTPControl::GetAccessibleChildCount(long FAR* pChildCount) { if (pChildCount == 0) return E_INVALIDARG; *pChildCount = GetCommandBar() ? 1 : 0; return S_OK; } HRESULT CXTPControl::GetAccessibleChild(VARIANT varChild, IDispatch* FAR* ppdispChild) { SAFE_MANAGE_STATE(m_pModuleState); *ppdispChild = NULL; if (GetChildIndex(&varChild) == 1) { CXTPCommandBar* pCommandBar = GetCommandBar(); if (pCommandBar) { *ppdispChild = pCommandBar->GetIDispatch(TRUE); } } return S_OK; } HRESULT CXTPControl::GetAccessibleName(VARIANT varChild, BSTR* pszName) { SAFE_MANAGE_STATE(m_pModuleState); if (GetChildIndex(&varChild) != CHILDID_SELF) return E_INVALIDARG; CString strCaption = GetCaption(); CXTPPaintManager::StripMnemonics(strCaption); if (!GetShortcutText().IsEmpty()) strCaption = strCaption + _T('\t') + GetShortcutText(); if (strCaption.IsEmpty()) { strCaption = GetTooltip(); } *pszName = strCaption.AllocSysString(); return S_OK; } HRESULT CXTPControl::GetAccessibleKeyboardShortcut(VARIANT varChild, BSTR* pszKeyboardShortcut) { SAFE_MANAGE_STATE(m_pModuleState); if (GetChildIndex(&varChild) != CHILDID_SELF) return E_INVALIDARG; CString strCaption = GetCaption(); if (strCaption.IsEmpty()) { *pszKeyboardShortcut = SysAllocString(L""); } else { int nIndex = CXTPShortcutManager::FindAccelPos(strCaption); CString strShortcut = CString(strCaption[nIndex + 1]); *pszKeyboardShortcut = strShortcut.AllocSysString(); } return S_OK; } HRESULT CXTPControl::GetAccessibleDescription(VARIANT varChild, BSTR* pszDescription) { if (GetChildIndex(&varChild) != CHILDID_SELF) return E_INVALIDARG; *pszDescription = GetDescription().AllocSysString(); return S_OK; } HRESULT CXTPControl::GetAccessibleRole(VARIANT varChild, VARIANT* pvarRole) { pvarRole->vt = VT_EMPTY; if (m_pParent && m_pParent->GetSafeHwnd() && GetChildIndex(&varChild) == CHILDID_SELF) { pvarRole->vt = VT_I4; pvarRole->lVal = m_pParent->GetType() == xtpBarTypeNormal || m_pParent->GetType() == xtpBarTypeRibbon ? GetCommandBar() ? ROLE_SYSTEM_BUTTONMENU: ROLE_SYSTEM_PUSHBUTTON : ROLE_SYSTEM_MENUITEM; return S_OK; } return E_INVALIDARG; } HRESULT CXTPControl::AccessibleSelect(long /*flagsSelect*/, VARIANT varChild) { SAFE_MANAGE_STATE(m_pModuleState); if (GetChildIndex(&varChild) != CHILDID_SELF) return E_INVALIDARG; if (m_pParent && m_pParent->GetSafeHwnd()) { m_pParent->SetTrackingMode(TRUE, FALSE); m_pParent->SetSelected(m_nIndex, TRUE); } return S_OK; } #ifndef STATE_SYSTEM_HASPOPUP #define STATE_SYSTEM_HASPOPUP (0x40000000) #endif //STATE_SYSTEM_HASPOPUP HRESULT CXTPControl::GetAccessibleState(VARIANT varChild, VARIANT* pvarState) { if (GetChildIndex(&varChild) != CHILDID_SELF) return E_INVALIDARG; pvarState->vt = VT_I4; pvarState->lVal = STATE_SYSTEM_FOCUSABLE | (m_bSelected ? STATE_SYSTEM_FOCUSED | STATE_SYSTEM_SELECTED | STATE_SYSTEM_HOTTRACKED : 0); if (!m_pParent->IsVisible() || !IsVisible()) pvarState->lVal |= STATE_SYSTEM_INVISIBLE; if (!GetEnabled()) pvarState->lVal |= STATE_SYSTEM_UNAVAILABLE; if (GetChecked()) pvarState->lVal |= STATE_SYSTEM_CHECKED; if (GetPressed()) pvarState->lVal |= STATE_SYSTEM_PRESSED; if (GetCommandBar()) pvarState->lVal |= STATE_SYSTEM_HASPOPUP; return S_OK; } HRESULT CXTPControl::GetAccessibleDefaultAction(VARIANT varChild, BSTR* pszDefaultAction) { if (GetChildIndex(&varChild) != CHILDID_SELF) return E_INVALIDARG; *pszDefaultAction = SysAllocString(L"Click"); return S_OK; } HRESULT CXTPControl::AccessibleDoDefaultAction(VARIANT varChild) { SAFE_MANAGE_STATE(m_pModuleState); if (GetChildIndex(&varChild) != CHILDID_SELF) return E_INVALIDARG; OnClick(TRUE); return S_OK; } HRESULT CXTPControl::AccessibleLocation(long* pxLeft, long* pyTop, long* pcxWidth, long* pcyHeight, VARIANT varChild) { *pxLeft = *pyTop = *pcxWidth = *pcyHeight = 0; if (GetChildIndex(&varChild) != CHILDID_SELF) return E_INVALIDARG; if (!m_pParent->GetSafeHwnd()) return S_OK; if (!IsVisible()) return S_OK; CRect rcControl = GetRect(); m_pParent->ClientToScreen(&rcControl); *pxLeft = rcControl.left; *pyTop = rcControl.top; *pcxWidth = rcControl.Width(); *pcyHeight = rcControl.Height(); return S_OK; } HRESULT CXTPControl::AccessibleHitTest(long xLeft, long yTop, VARIANT* pvarID) { if (pvarID == NULL) return E_INVALIDARG; pvarID->vt = VT_EMPTY; if (!m_pParent->GetSafeHwnd()) return S_FALSE; if (!CXTPWindowRect(m_pParent).PtInRect(CPoint(xLeft, yTop))) return S_FALSE; pvarID->vt = VT_I4; pvarID->lVal = 0; CPoint pt(xLeft, yTop); m_pParent->ScreenToClient(&pt); if (!GetRect().PtInRect(pt)) return S_FALSE; return S_OK; } void CXTPControl::SetVisible(BOOL bVisible) { DWORD dwHideFlags = m_dwHideFlags; if (!bVisible) SetHideFlags(m_dwHideFlags | xtpHideGeneric); else SetHideFlags(m_dwHideFlags & ~xtpHideGeneric); if (dwHideFlags != m_dwHideFlags) DelayLayoutParent(); } BOOL CXTPControl::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo) { if (nCode == CN_EVENT && nID == XTP_CN_REDRAWPARENT) { RedrawParent(FALSE); return TRUE; } return CCmdTarget::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo); } BEGIN_INTERFACE_MAP(CXTPControl, CCmdTarget) INTERFACE_PART(CXTPControl, IID_IAccessible, ExternalAccessible) END_INTERFACE_MAP()