// XTPTaskPanel.cpp : implementation of the CXTPTaskPanel class. // // This file is a part of the XTREME TASKPANEL 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/Resource.h" #include "Common/XTPDrawHelpers.h" #include "Common/XTPImageManager.h" #include "Common/XTPToolTipContext.h" #include "Common/XTPResourceManager.h" #include "Common/XTPMarkupRender.h" #include "Common/XTPSystemHelpers.h" #include "Common/XTPColorManager.h" #if !defined(_XTP_ACTIVEX) && defined(_XTP_INCLUDE_COMMANDBARS) #include "CommandBars/XTPMouseManager.h" #endif #include "XTPTaskPanelDefines.h" #include "XTPTaskPanelItem.h" #include "XTPTaskPanelItems.h" #include "XTPTaskPanelGroup.h" #include "XTPTaskPanel.h" #include "XTPTaskPanelPaintManager.h" #include "XTPTaskPanelGroupItem.h" #include "XTPTaskPanelAnimation.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #ifndef SPI_GETMOUSEHOVERTIME #define SPI_GETMOUSEHOVERTIME 102 #endif #define TID_REPOSITION 200 #define TID_SCROLLBARS 201 #define TID_SCROLLGROUP 202 #define TID_GROUPHOVER 203 #define IsItemLink(pItem) (pItem && pItem->GetType() == xtpTaskItemTypeLink) #define IsItemGroup(pItem) (pItem && pItem->GetType() == xtpTaskItemTypeGroup) CLIPFORMAT CXTPTaskPanel::m_cfItem = (CLIPFORMAT)::RegisterClipboardFormat(_T("TaskPanelGroupItem")); BOOL CXTPTaskPanel::GetMessageExt(MSG& msg) { if (!::GetMessage(&msg, NULL, 0, 0)) { AfxPostQuitMessage((int)msg.wParam); return FALSE; } return TRUE; } ////////////////////////////////////////////////////////////////////////// // CPanelDropTarget class CXTPTaskPanel::CPanelDropTarget : public COleDropTarget { public: virtual DROPEFFECT OnDragOver(CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point) { CXTPTaskPanel* pPanel = DYNAMIC_DOWNCAST(CXTPTaskPanel, pWnd); if (!pPanel) return DROPEFFECT_NONE; return pPanel->OnDragOver(pDataObject, dwKeyState, point); } virtual void OnDragLeave(CWnd* pWnd) { CXTPTaskPanel* pPanel = DYNAMIC_DOWNCAST(CXTPTaskPanel, pWnd); if (pPanel) { pPanel->OnDragOver(NULL, 0, CPoint(-1, -1)); } } virtual BOOL OnDrop(CWnd* pWnd, COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point) { CXTPTaskPanel* pPanel = DYNAMIC_DOWNCAST(CXTPTaskPanel, pWnd); if (pPanel) { return pPanel->OnDrop(pDataObject, dropEffect, point); } return FALSE; } }; ////////////////////////////////////////////////////////////////////////// // CXTPTaskPanelScrollButton CXTPTaskPanelScrollButton::CXTPTaskPanelScrollButton(BOOL bScrollUp) { this->bScrollUp = bScrollUp; bEnabled = FALSE; bPressed = FALSE; bHot = FALSE; rcButton.SetRectEmpty(); pGroupScroll = pGroupCaption = NULL; } BOOL CXTPTaskPanelScrollButton::IsVisible() const { if (rcButton.IsRectEmpty()) return FALSE; if (pGroupScroll == NULL) return FALSE; if (!bEnabled && !pGroupScroll->GetTaskPanel()->GetPaintManager()->m_bCaptionScrollButton) return FALSE; return TRUE; } ////////////////////////////////////////////////////////////////////////// // CXTPTaskPanelEditItem class CXTPTaskPanelEditItem : public CEdit { public: CXTPTaskPanelEditItem(); public: BOOL Create(CXTPTaskPanelItem* pItem); protected: virtual void PostNcDestroy(); protected: afx_msg void OnKillFocus(CWnd* pNewWnd); afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags); afx_msg UINT OnGetDlgCode(); protected: BOOL m_bEscapeKey; CXTPTaskPanelItem* m_pItem; private: BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL); BOOL Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID); protected: DECLARE_MESSAGE_MAP() DECLARE_DYNAMIC(CXTPTaskPanelEditItem) }; AFX_INLINE BOOL CXTPTaskPanelEditItem::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext) { return CWnd::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext); } AFX_INLINE BOOL CXTPTaskPanelEditItem::Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID) { return CEdit::Create(dwStyle, rect, pParentWnd, nID); } IMPLEMENT_DYNAMIC(CXTPTaskPanelEditItem, CEdit) CXTPTaskPanelEditItem::CXTPTaskPanelEditItem() { m_bEscapeKey = FALSE; m_pItem = NULL; } BEGIN_MESSAGE_MAP(CXTPTaskPanelEditItem, CEdit) //{{AFX_MSG_MAP(CXTPTaskPanelEditItem) ON_WM_KILLFOCUS() ON_WM_CHAR() ON_WM_GETDLGCODE() //}}AFX_MSG_MAP END_MESSAGE_MAP() UINT CXTPTaskPanelEditItem::OnGetDlgCode() { return DLGC_WANTALLKEYS; } void CXTPTaskPanelEditItem::OnKillFocus(CWnd* /*pNewWnd*/) { PostMessage(WM_CLOSE); if (!m_pItem) return; if (!m_bEscapeKey) { CString str; GetWindowText(str); m_pItem->GetTaskPanel()->OnEndLabelEdit(m_pItem, str); } else { m_pItem->GetTaskPanel()->OnEndLabelEdit(m_pItem, m_pItem->GetCaption()); } m_pItem = NULL; } void CXTPTaskPanelEditItem::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) { if (nChar == VK_ESCAPE || nChar == VK_RETURN) { m_bEscapeKey = (nChar == VK_ESCAPE); OnKillFocus(NULL); return; } CEdit::OnChar(nChar, nRepCnt, nFlags); } void CXTPTaskPanelEditItem::PostNcDestroy() { delete this; } BOOL CXTPTaskPanelEditItem::Create(CXTPTaskPanelItem* pItem) { m_pItem = pItem; CXTPTaskPanel* pPanel = pItem->GetTaskPanel(); CFont* pFont = m_pItem->GetItemFont(); UINT nFormat = 0; CRect rc = pItem->GetTextRect(&nFormat); rc.OffsetRect(0, -pPanel->GetScrollOffset()); CString strText = pItem->GetCaption(); UINT nCenter = nFormat & DT_CENTER ? ES_CENTER : 0; if (!CEdit::Create(WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | nCenter, rc, pPanel, 0)) return FALSE; SetFont(pFont); SetMargins(0, 0); SetWindowText(strText); SetFocus(); SetSel(0, -1); return TRUE; } void CXTPTaskPanel::EnableMarkup(BOOL bEnable) { XTPMarkupReleaseContext(m_pMarkupContext); if (bEnable) { m_pMarkupContext = XTPMarkupCreateContext(); } } void CXTPTaskPanel::RenameItem(CXTPTaskPanelItem* pItem) { Reposition(FALSE); EnsureVisible(pItem); UpdateWindow(); CXTPTaskPanelEditItem* pEditItem = new CXTPTaskPanelEditItem; pEditItem->Create(pItem); } void CXTPTaskPanel::OnEndLabelEdit(CXTPTaskPanelItem* pItem, LPCTSTR str) { XTP_TPNENDLABELEDIT ele; ele.pItem = pItem; ele.strNewString = str; if (NotifyOwner(XTP_TPN_ENDLABELEDIT, (LPARAM)&ele) == XTP_ACTION_CANCEL) return; pItem->SetCaption(ele.strNewString); } ///////////////////////////////////////////////////////////////////////////// // CXTPTaskPanel IMPLEMENT_DYNAMIC(CXTPTaskPanel, CWnd) CXTPTaskPanel::CXTPTaskPanel() { RegisterWindowClass(); m_pPaintManager = NULL; SetTheme(xtpTaskPanelThemeNativeWinXP); m_pGroups = new CXTPTaskPanelGroups(this); m_pGroups->m_pOwner = this; m_nClientHeight = m_nOldClientHeight = 0; m_rcMargins = CXTPTaskPanelPaintManager::rectDefault; m_nGroupSpacing = CW_USEDEFAULT; m_szItemIcon = CSize(16, 16); m_szGroupIcon = CSize(32, 32); m_bGrabbingFocus = FALSE; m_pItemHot = 0; m_pItemFocused = 0; m_pItemPressed = 0; m_nAnimateTimer = 0; m_bScrollVisible = FALSE; m_bPreSubclassWindow = TRUE; m_hHandCursor = AfxGetApp()->LoadStandardCursor(MAKEINTRESOURCE(32649)); if (m_hHandCursor == 0) m_hHandCursor = XTPResourceManager()->LoadCursor(XTP_IDC_HAND); m_bExpandable = TRUE; SetAnimation(xtpTaskPanelAnimationYes); m_nLockRedraw = 0; m_nOLEDropMode = 0; m_bAcceptFocus = TRUE; m_bDrawFocusRect = FALSE; m_pImageManager = new CXTPImageManager(); m_itemLayout = xtpTaskItemLayoutDefault; m_hotTrackStyle = xtpTaskPanelHighlightDefault; m_panelBehaviour = xtpTaskPanelBehaviourExplorer; m_pActiveGroup = NULL; m_bSelectItemOnFocus = FALSE; m_bSingleSelection = FALSE; m_nAllowDrag = xtpTaskItemAllowDragNone; m_bAllowDrop = TRUE; m_ptPressed = CPoint(0, 0); m_pItemDragging = m_pItemDragOver = NULL; OleInitialize(NULL); m_pDropTarget = new CPanelDropTarget(); m_pScrollButton[TRUE] = new CXTPTaskPanelScrollButton(TRUE); m_pScrollButton[FALSE] = new CXTPTaskPanelScrollButton(FALSE); m_bTimerGroupHover = FALSE; m_pToolTipContext = new CXTPToolTipContext; m_bMultiColumn = FALSE; m_nColumnWidth = 100; m_nGroupMinClientHeight = 0; m_bInUpdateScrollBar = FALSE; m_bTabItems = FALSE; m_pAnimation = new CXTPTaskPanelAnimation(this); m_pMarkupContext = NULL; EnableAutomation(); } BOOL CXTPTaskPanel::RegisterWindowClass(HINSTANCE hInstance /*= NULL*/) { return XTPDrawHelpers()->RegisterWndClass(hInstance, _T("XTPTaskPanel"), CS_DBLCLKS); } CXTPTaskPanel::~CXTPTaskPanel() { CMDTARGET_RELEASE(m_pItemHot); CMDTARGET_RELEASE(m_pItemFocused); CMDTARGET_RELEASE(m_pActiveGroup); if (m_pGroups) { m_pGroups->Clear(FALSE); CMDTARGET_RELEASE(m_pGroups); } CMDTARGET_RELEASE(m_pImageManager); CMDTARGET_RELEASE(m_pToolTipContext); delete m_pPaintManager; delete m_pDropTarget; delete m_pScrollButton[TRUE]; delete m_pScrollButton[FALSE]; delete m_pAnimation; XTPMarkupReleaseContext(m_pMarkupContext); OleUninitialize(); } void CXTPTaskPanel::EnableAnimation(BOOL bEnable) { m_pAnimation->m_bAnimation = bEnable; Redraw(); } void CXTPTaskPanel::AllowDrag(long nAllowDrag /* = xtpTaskItemAllowDragDefault */) { m_nAllowDrag = nAllowDrag; } void CXTPTaskPanel::SetImageList(CImageList* pImageList, CSize szItemIcon) { if (pImageList) { m_pImageManager->SetIcons(*pImageList, 0, 0, 0, xtpImageNormal); } m_szItemIcon = szItemIcon; } void CXTPTaskPanel::SetGroupImageList(CImageList* pImageList, CSize szGroupIcon /* = CSize */) { if (pImageList) { m_pImageManager->SetIcons(*pImageList, 0, 0, 0, xtpImageNormal); } m_szGroupIcon = szGroupIcon; } CXTPImageManager* CXTPTaskPanel::GetImageManager() const { return m_pImageManager ? m_pImageManager : XTPImageManager(); } void CXTPTaskPanel::SetImageManager(CXTPImageManager* pImageManager) { if (m_pImageManager) m_pImageManager->InternalRelease(); m_pImageManager = pImageManager; Reposition(); } void CXTPTaskPanel::SetHotItem(CXTPTaskPanelItem* pItem) { if (m_pItemHot == pItem) return; CXTPTaskPanelItem* pItemHot = m_pItemHot; m_pItemHot = pItem; if (pItemHot) { pItemHot->RedrawPanel(TRUE); pItemHot->InternalRelease(); } if (m_pItemHot) { m_pItemHot->RedrawPanel(FALSE); m_pItemHot->InternalAddRef(); } if (m_pItemHot) { TRACKMOUSEEVENT tme = { sizeof(TRACKMOUSEEVENT), TME_LEAVE, m_hWnd }; _TrackMouseEvent(&tme); } NotifyOwner(XTP_TPN_HOTITEMCHANGED, 0); } void CXTPTaskPanel::EnsureVisibleRect(const CRect& rc) { CXTPClientRect rcClient(this); if (rc.bottom > rcClient.bottom + GetScrollOffset()) { OnScrollChanged(min(rc.top, rc.bottom - rcClient.Height())); } else if (rc.top < GetScrollOffset()) { OnScrollChanged(rc.top); } } void CXTPTaskPanel::EnsureVisible(CXTPTaskPanelItem* pItem) { if (!pItem || !pItem->IsVisible()) return; CXTPTaskPanelGroup* pGroup = pItem->GetItemGroup(); if (!pGroup) return; if (pItem->IsGroup()) { CRect rc = pGroup->GetCaptionRect(); EnsureVisibleRect(rc); } else { if (!pGroup->IsExpanded()) pGroup->SetExpanded(TRUE); CRect rc = pGroup->GetTargetClientRect(); if (IsExplorerBehaviour()) { CRect rcItem(((CXTPTaskPanelGroupItem*)pItem)->GetItemRect()); rcItem.OffsetRect(0, rc.top); EnsureVisibleRect(rcItem); } else { rc.top -= pGroup->GetTargetCaptionRect().Height(); EnsureVisibleRect(rc); pGroup->EnsureVisible((CXTPTaskPanelGroupItem*)pItem); } } } void CXTPTaskPanel::GrabFocus() { if (m_bAcceptFocus && ::GetFocus() != m_hWnd && m_hWnd) { m_bGrabbingFocus = TRUE; SetFocus(); m_bGrabbingFocus = FALSE; } } void CXTPTaskPanel::SetFocusedItem(CXTPTaskPanelItem* pItem, BOOL bDrawFocusRect, BOOL bSetFocus) { if (bDrawFocusRect) m_bDrawFocusRect = m_bAcceptFocus; if (bSetFocus) GrabFocus(); if (m_pItemFocused == pItem) return; if (m_hWnd) EnsureVisible(pItem); CXTPTaskPanelItem* pItemFocused = m_pItemFocused; m_pItemFocused = pItem; if (pItemFocused) { pItemFocused->RedrawPanel(FALSE); pItemFocused->InternalRelease(); } if (m_pItemFocused) { m_pItemFocused->RedrawPanel(FALSE); m_pItemFocused->InternalAddRef(); } if (m_bSelectItemOnFocus && IsItemLink(pItem) && !m_bSingleSelection) { pItem->GetItemGroup()->SetSelectedItem(((CXTPTaskPanelGroupItem*)pItem)); } if (!GetSafeHwnd()) return; NotifyOwner(XTP_TPN_FOCUSEDITEMCHANGED, 0); if (m_pItemFocused) { AccessibleNotifyWinEvent(EVENT_OBJECT_FOCUS, m_hWnd, OBJID_CLIENT, GetAccessibleIndex(m_pItemFocused)); } if (bSetFocus && m_pItemFocused && m_pItemFocused->GetType() == xtpTaskItemTypeControl) { ::SetFocus(((CXTPTaskPanelGroupItem*)m_pItemFocused)->GetControlHandle()); } } int CXTPTaskPanel::GetGroupCount() const { return m_pGroups->GetCount(); } BOOL CXTPTaskPanel::IsDirty() const { for (int i = 0; i < GetGroupCount(); i++) { if (GetAt(i)->IsDirty()) return TRUE; } return FALSE; } void CXTPTaskPanel::SetMargins(long nLeft, long nTop, long nRight, long nBottom, long nMiddle) { m_rcMargins.SetRect(nLeft, nTop, nRight, nBottom); m_nGroupSpacing = nMiddle; Reposition(); } BOOL CXTPTaskPanel::Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID) { if (!CreateEx(0, _T("XTPTaskPanel"), NULL, dwStyle, rect, pParentWnd, nID)) { return FALSE; } m_pDropTarget->Register(this); m_nAnimateTimer = 0; return TRUE; } CXTPTaskPanelGroup* CXTPTaskPanel::AddGroup(UINT nID, int nImage) { CXTPTaskPanelGroup* pGroup = (CXTPTaskPanelGroup*)m_pGroups->Add(new CXTPTaskPanelGroup(this), nID); pGroup->SetIconIndex(nImage); return pGroup; } CXTPTaskPanelGroup* CXTPTaskPanel::FindGroup(UINT nID) const { return (CXTPTaskPanelGroup*)m_pGroups->Find(nID); } CXTPTaskPanelGroupItem* CXTPTaskPanel::FindItem(UINT nID) const { for (int i = 0; i < GetGroupCount(); i++) { CXTPTaskPanelGroupItem* pItem = GetAt(i)->FindItem(nID); if (pItem) { return pItem; } } return NULL; } CXTPTaskPanelGroup* CXTPTaskPanel::GetAt(int nIndex) const { return (CXTPTaskPanelGroup*)m_pGroups->GetAt(nIndex); } void CXTPTaskPanel::SetTheme(XTPTaskPanelPaintTheme paintTheme) { if (m_pPaintManager) { delete m_pPaintManager; } if (paintTheme == xtpTaskPanelThemeOfficeXPPlain) m_pPaintManager = new CXTPTaskPanelOfficeXPThemePlain(); else if (paintTheme == xtpTaskPanelThemeToolbox) m_pPaintManager = new CXTPTaskPanelToolboxTheme(); else if (paintTheme == xtpTaskPanelThemeToolboxWhidbey) m_pPaintManager = new CXTPTaskPanelToolboxWhidbeyTheme(); else if (paintTheme == xtpTaskPanelThemeListView) m_pPaintManager = new CXTPTaskPanelListViewTheme(); else if (paintTheme == xtpTaskPanelThemeListViewOfficeXP) m_pPaintManager = new CXTPTaskPanelListViewOfficeXPTheme(); else if (paintTheme == xtpTaskPanelThemeListViewOffice2003) m_pPaintManager = new CXTPTaskPanelListViewOffice2003Theme(); else if (paintTheme == xtpTaskPanelThemeOffice2000Plain) m_pPaintManager = new CXTPTaskPanelPaintManagerPlain(); else if (paintTheme == xtpTaskPanelThemeOffice2003Plain) m_pPaintManager = new CXTPTaskPanelOffice2003ThemePlain(); else if (paintTheme == xtpTaskPanelThemeNativeWinXPPlain) m_pPaintManager = new CXTPTaskPanelExplorerThemePlain(); else if (paintTheme == xtpTaskPanelThemeOffice2000) m_pPaintManager = new CXTPTaskPanelPaintManager(); else if (paintTheme == xtpTaskPanelThemeOffice2003) m_pPaintManager = new CXTPTaskPanelOffice2003Theme(); else if (paintTheme == xtpTaskPanelThemeShortcutBarOffice2003) m_pPaintManager = new CXTPTaskPanelShortcutBarOffice2003Theme(); else if (paintTheme == xtpTaskPanelThemeShortcutBarOffice2007) m_pPaintManager = new CXTPTaskPanelShortcutBarOffice2007Theme(); else if (paintTheme == xtpTaskPanelThemeVisualStudio2010) m_pPaintManager = new CXTPTaskPanelVisualStudio2010Theme(); else m_pPaintManager = new CXTPTaskPanelExplorerTheme(); m_paintTheme = paintTheme; m_pPaintManager->RefreshMetrics(); Reposition(); } void CXTPTaskPanel::SetCustomTheme(CXTPTaskPanelPaintManager* pPaintManager) { delete m_pPaintManager; m_pPaintManager = pPaintManager; if (m_pPaintManager) { m_pPaintManager->RefreshMetrics(); } m_paintTheme = xtpTaskPanelThemeCustom; Reposition(); } BEGIN_MESSAGE_MAP(CXTPTaskPanel, CWnd) //{{AFX_MSG_MAP(CXTPTaskPanel) ON_WM_ERASEBKGND() ON_WM_PAINT() ON_WM_SIZE() ON_WM_VSCROLL() ON_WM_MOUSEMOVE() ON_WM_SETCURSOR() ON_WM_LBUTTONUP() ON_WM_DESTROY() ON_WM_TIMER() ON_WM_SYSCOLORCHANGE() ON_WM_SETTINGCHANGE() ON_WM_RBUTTONDOWN() ON_WM_RBUTTONUP() ON_WM_SETFOCUS() ON_WM_KILLFOCUS() ON_WM_KEYDOWN() ON_WM_KEYUP() ON_WM_SYSKEYDOWN() ON_WM_SYSKEYUP() ON_WM_LBUTTONDOWN() ON_WM_LBUTTONDBLCLK() ON_WM_MOUSEWHEEL() ON_WM_GETDLGCODE() ON_WM_CAPTURECHANGED() //}}AFX_MSG_MAP ON_MESSAGE_VOID(WM_MOUSELEAVE, OnMouseLeave) ON_MESSAGE(WM_PRINTCLIENT, OnPrintClient) ON_MESSAGE(WM_GETOBJECT, OnGetObject) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CXTPTaskPanel message handlers BOOL CXTPTaskPanel::OnEraseBkgnd(CDC* /*pDC*/) { return TRUE; } void CXTPTaskPanel::OnPaint() { CPaintDC paintDC(this); m_pAnimation->OnPaint(paintDC); } LRESULT CXTPTaskPanel::OnPrintClient(WPARAM wParam, LPARAM /*lParam*/) { CDC* pDC = CDC::FromHandle((HDC)wParam); if (pDC) { OnDraw(pDC, CXTPClientRect(this)); } return TRUE; } void CXTPTaskPanel::Redraw(LPCRECT lpRect, BOOL bAnimate) { if (m_nLockRedraw > 0) { return; } if (m_hWnd && IsWindowVisible()) { m_pAnimation->RedrawRect(lpRect, bAnimate); } } void CXTPTaskPanel::OnDraw(CDC* pDC, CRect rcClipBox) { CPoint pt = pDC->GetViewportOrg(); pDC->SetViewportOrg(pt.x, pt.y - GetScrollOffset()); m_pPaintManager->FillTaskPanel(pDC, this); for (int i = 0; i < GetGroupCount(); i++) { CXTPTaskPanelGroup* pGroup = GetAt(i); if (!pGroup->IsVisible()) continue; if (CRect().IntersectRect(pGroup->GetInvalidateRect(), rcClipBox)) { pGroup->OnPaint(pDC); } } m_pPaintManager->DrawScrollButton(pDC, m_pScrollButton[TRUE]); m_pPaintManager->DrawScrollButton(pDC, m_pScrollButton[FALSE]); pDC->SetViewportOrg(pt); } void CXTPTaskPanel::SetLockRedraw(BOOL bLockRedraw) { m_nLockRedraw += bLockRedraw ? +1 : -1; ASSERT(m_nLockRedraw >= 0); if (m_nLockRedraw == 0) Reposition(); } void CXTPTaskPanel::UpdateScrollButtons() { m_pScrollButton[TRUE]->bEnabled = m_pScrollButton[TRUE]->pGroupScroll ? m_pScrollButton[TRUE]->pGroupScroll->IsScrollButtonEnabled(TRUE) : FALSE; m_pScrollButton[FALSE]->bEnabled = m_pScrollButton[FALSE]->pGroupScroll ? m_pScrollButton[FALSE]->pGroupScroll->IsScrollButtonEnabled(FALSE) : FALSE; } void CXTPTaskPanel::OnClickScrollButton(CXTPTaskPanelScrollButton* pScrollButton) { if (!pScrollButton->bEnabled) return; pScrollButton->bPressed = TRUE; SetCapture(); CXTPTaskPanelGroup* pActiveGroup = m_pActiveGroup; int nScrollOffset = (pScrollButton->bScrollUp ? -1 : +1) * pActiveGroup->GetItemsInRow(); pActiveGroup->Scroll(nScrollOffset); Redraw(); SetTimer(TID_SCROLLGROUP, 500, NULL); BOOL bQuick = FALSE; while (CWnd::GetCapture() == this && pScrollButton->bEnabled) { MSG msg; if (!GetMessageExt(msg)) break; if (msg.message == WM_TIMER && msg.wParam == TID_SCROLLGROUP) { pActiveGroup->Scroll(nScrollOffset); Redraw(); if (!bQuick) { KillTimer(TID_SCROLLGROUP); SetTimer(TID_SCROLLGROUP, 50, NULL); bQuick = TRUE; } } else if (msg.message == WM_LBUTTONUP) break; else if (msg.message == WM_MOUSEMOVE) { } else if (msg.message == WM_KEYDOWN) { if (msg.wParam == VK_ESCAPE) break; } else DispatchMessage(&msg); } pScrollButton->bPressed = FALSE; ReleaseCapture(); Redraw(); } void CXTPTaskPanel::RepositionScrollButtons() { m_pScrollButton[FALSE]->rcButton.SetRectEmpty(); m_pScrollButton[TRUE]->rcButton.SetRectEmpty(); m_pScrollButton[TRUE]->pGroupCaption = m_pScrollButton[FALSE]->pGroupCaption = NULL; if (IsExplorerBehaviour() || !m_pActiveGroup || !m_pActiveGroup->IsVisible()) return; m_pScrollButton[TRUE]->pGroupScroll = m_pScrollButton[FALSE]->pGroupScroll = m_pActiveGroup; if (GetPaintManager()->m_bCaptionScrollButton) { CXTPClientRect rc(this); rc.bottom = max(rc.bottom, m_nClientHeight); CRect rcMargins = GetPaintManager()->GetControlMargins(this); m_pScrollButton[TRUE]->pGroupCaption = m_pActiveGroup; CRect rcCaption = m_pActiveGroup->GetCaptionRect(); int nRight = rc.right - rcMargins.right - GetPaintManager()->GetGroupOuterMargins(m_pActiveGroup).right; int nHeight = rcCaption.Height(); m_pScrollButton[TRUE]->rcButton.SetRect(nRight - nHeight, rcCaption.top, nRight, rcCaption.bottom); CXTPTaskPanelGroup* pGroupNext = GetNextVisibleGroup(m_pActiveGroup->GetIndex()); if (pGroupNext == 0) { m_pScrollButton[FALSE]->rcButton.SetRect(nRight - nHeight, rc.bottom - rcMargins.bottom - nHeight, nRight, rc.bottom - rcMargins.bottom); } else { m_pScrollButton[FALSE]->pGroupCaption = pGroupNext; CRect rcNextCaption = pGroupNext->GetCaptionRect(); int nButtonRight = rc.right - rcMargins.right - GetPaintManager()->GetGroupOuterMargins(pGroupNext).right; m_pScrollButton[FALSE]->rcButton.SetRect(nButtonRight - rcNextCaption.Height(), rcNextCaption.top, nButtonRight, rcNextCaption.bottom); } } else { CRect rc = m_pActiveGroup->GetClientRect(); rc.DeflateRect(4, 4); int nHeight = 16; m_pScrollButton[TRUE]->rcButton.SetRect(rc.right - nHeight, rc.top, rc.right, rc.top + nHeight); m_pScrollButton[FALSE]->rcButton.SetRect(rc.right - nHeight, rc.bottom - nHeight, rc.right, rc.bottom); } UpdateScrollButtons(); } void CXTPTaskPanel::Reposition(BOOL bRecalcOnly) { if (!GetSafeHwnd()) return; if (m_nLockRedraw > 0) return; CXTPClientRect rc(this); CRect rcMargins = GetPaintManager()->GetControlMargins(this); int nGroupSpacing = GetPaintManager()->GetGroupSpacing(this); int nCurPos = rcMargins.top, nGroupCount = GetGroupCount(), i; rc.DeflateRect(rcMargins.left, 0, rcMargins.right, 0); BOOL bFirstVisbleGroup = TRUE; for (i = 0; i < nGroupCount; i++) { CXTPTaskPanelGroup* pGroup = GetAt(i); if (!pGroup->IsVisible()) { pGroup->OnAnimate(0); continue; } if (!bFirstVisbleGroup) { nCurPos += nGroupSpacing; } else bFirstVisbleGroup = FALSE; CRect rcGroup = pGroup->OnReposition(CRect(rc.left, nCurPos, rc.right, nCurPos), bRecalcOnly); CRect rcOuter = GetPaintManager()->GetGroupOuterMargins(pGroup); nCurPos = rcGroup.bottom + rcOuter.bottom; } { CClientDC dc(this); for (i = 0; i < nGroupCount; i++) { CXTPTaskPanelGroup* pGroup = GetAt(i); if (!pGroup->IsVisible()) continue; pGroup->OnCalcClientHeight(&dc, rc); } } nCurPos += rcMargins.bottom; m_nClientHeight = nCurPos; RepositionScrollButtons(); m_nAnimationStep = 10; BOOL bDirty = IsDirty(); if (m_nAnimateTimer == 0 && bDirty) { m_nAnimateTimer = SetTimer(TID_REPOSITION, 30, NULL); } else if (m_nAnimateTimer != 0 && !bDirty) { KillTimer(m_nAnimateTimer); m_nAnimateTimer = 0; } UpdateScrollBar(); if (!m_bAnimation) AnimateGroups(FALSE); Redraw(); } void CXTPTaskPanel::OnClientHeightChanged() { } void CXTPTaskPanel::UpdateScrollBar() { if (m_bInUpdateScrollBar) return; m_bInUpdateScrollBar = TRUE; if (m_nClientHeight != m_nOldClientHeight) { m_nOldClientHeight = m_nClientHeight; OnClientHeightChanged(); } CXTPClientRect rc(this); m_bScrollVisible = rc.Height() < m_nClientHeight; if (m_bScrollVisible) { ShowScrollBar(SB_VERT, TRUE); SCROLLINFO si ; si.cbSize = sizeof(SCROLLINFO) ; si.fMask = SIF_PAGE | SIF_RANGE ; GetScrollInfo(SB_VERT, &si, si.fMask); UINT nControlHeight = (UINT)rc.Height(); if (si.nPage != nControlHeight || si.nMax != m_nClientHeight - 1 || si.nMin != 0) { si.nPage = nControlHeight ; si.nMax = m_nClientHeight - 1; si.nMin = 0 ; si.fMask = SIF_PAGE | SIF_RANGE ; SetScrollInfo(SB_VERT, &si) ; AnimateGroups(FALSE); } EnableScrollBarCtrl(SB_VERT, TRUE); } else { SetScrollPos(SB_VERT, 0); ShowScrollBar(SB_VERT, FALSE); } m_bInUpdateScrollBar = FALSE; if (::GetWindow(m_hWnd, GW_CHILD)) { RedrawWindow(0, 0, RDW_INVALIDATE | RDW_ALLCHILDREN); } } void CXTPTaskPanel::OnSize(UINT nType, int cx, int cy) { Reposition(IsExplorerBehaviour()); CWnd::OnSize(nType, cx, cy); } int CXTPTaskPanel::GetScrollOffset() const { if (!m_bScrollVisible) return 0; return GetScrollPos(SB_VERT); } int CXTPTaskPanel::GetClientHeight() const { return m_nClientHeight; } void CXTPTaskPanel::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) { if (pScrollBar != NULL) { CWnd::OnVScroll(nSBCode, nPos, pScrollBar); return; } // its horizontal scroll bar int nCurPos = GetScrollPos(SB_VERT); // decide what to do for each diffrent scroll event switch (nSBCode) { case SB_LEFT: nCurPos = 0; break; case SB_RIGHT: nCurPos = GetScrollLimit(SB_VERT); break; case SB_LINELEFT: nCurPos = max(nCurPos - 6, 0); break; case SB_LINERIGHT: nCurPos = min(nCurPos + 6, GetScrollLimit(SB_VERT)); break; case SB_PAGELEFT: nCurPos = max(nCurPos - CXTPClientRect(this).Height(), 0); break; case SB_PAGERIGHT: nCurPos = min(nCurPos + CXTPClientRect(this).Height(), GetScrollLimit(SB_VERT)); break; case SB_THUMBTRACK: case SB_THUMBPOSITION: { SCROLLINFO si; ZeroMemory(&si, sizeof(SCROLLINFO)); si.cbSize = sizeof(SCROLLINFO); si.fMask = SIF_TRACKPOS; if (!GetScrollInfo(SB_VERT, &si)) return; nCurPos = si.nTrackPos; } break; } OnScrollChanged(nCurPos); } void CXTPTaskPanel::OnScrollChanged(int nCurPos) { SetScrollPos(SB_VERT, nCurPos); AnimateGroups(FALSE); Redraw(); if (::GetWindow(m_hWnd, GW_CHILD)) { RedrawWindow(0, 0, RDW_INVALIDATE | RDW_ALLCHILDREN); } } CXTPTaskPanelScrollButton* CXTPTaskPanel::HitTestScrollButton(CPoint point) const { point.y += GetScrollOffset(); for (int i = 0; i < 2; i++) { if (m_pScrollButton[i]->IsVisible() && m_pScrollButton[i]->rcButton.PtInRect(point)) return m_pScrollButton[i]; } return 0; } CXTPTaskPanelGroup* CXTPTaskPanel::HitTestGroup(CPoint point, BOOL* pbCaption) const { if (HitTestScrollButton(point)) return 0; point.y += GetScrollOffset(); int nGroupCount = GetGroupCount(); for (int i = 0; i < nGroupCount; i++) { CXTPTaskPanelGroup* pGroup = GetAt(i); if (!pGroup->IsVisible()) continue; if (pGroup->GetClientRect().PtInRect(point)) { if (pbCaption) *pbCaption = FALSE; return pGroup; } if (pGroup->IsCaptionVisible() && pGroup->GetCaptionRect().PtInRect(point)) { if (pbCaption) *pbCaption = TRUE; return pGroup; } } return NULL; } CXTPTaskPanelItem* CXTPTaskPanel::HitTestItem(CPoint point, BOOL bClientAvail) const { BOOL bCaption; CXTPTaskPanelGroup* pGroup = HitTestGroup(point, &bCaption); if (!pGroup) return NULL; if (bCaption) return pGroup; CXTPTaskPanelGroupItem* pItem = pGroup->HitTest(point); if (pItem) return pItem; if (bClientAvail) return pGroup; return NULL; } void CXTPTaskPanel::OnClick(CXTPTaskPanelGroupItem* pItem) { ASSERT(pItem); NotifyOwner(XTP_TPN_CLICK, (LPARAM)pItem); } void CXTPTaskPanel::OnRButtonDown(UINT nFlags, CPoint point) { CXTPTaskPanelItem* pItem = HitTestItem(point); if (pItem && pItem->IsAcceptFocus()) { SetFocusedItem(pItem); } if (pItem) { NotifyOwner(XTP_TPN_RCLICK, (LPARAM)pItem); } CWnd::OnRButtonDown(nFlags, point); } void CXTPTaskPanel::OnRButtonUp(UINT nFlags, CPoint point) { CWnd::OnRButtonUp(nFlags, point); } void CXTPTaskPanel::OnLButtonDown(UINT nFlags, CPoint point) { CXTPTaskPanelItem* pItem = HitTestItem(point); if (pItem && pItem->IsAcceptFocus()) { SetFocusedItem(pItem); } else { GrabFocus(); } if (pItem && pItem->IsAcceptFocus()) { SetCapture(); m_pItemPressed = pItem; m_ptPressed = point; m_pItemPressed->RedrawPanel(); } CXTPTaskPanelScrollButton* pScrollButton = HitTestScrollButton(point); if (pScrollButton) { OnClickScrollButton(pScrollButton); } CWnd::OnLButtonDown(nFlags, point); } void CXTPTaskPanel::OnLButtonDblClk(UINT nFlags, CPoint point) { OnLButtonDown(nFlags, point); if (m_pItemHot && m_pItemPressed == m_pItemHot && !m_pItemHot->IsGroup()) { NotifyOwner(XTP_TPN_DBLCLICK, (LPARAM)(CXTPTaskPanelGroupItem*)m_pItemPressed); } } void CXTPTaskPanel::OnLButtonUp(UINT /*nFlags*/, CPoint point) { UNREFERENCED_PARAMETER(point); if (m_pItemPressed == NULL) { return; } CXTPTaskPanelItem* pItemPressed = m_pItemPressed; m_pItemPressed = NULL; ReleaseCapture(); pItemPressed->RedrawPanel(); if (pItemPressed == m_pItemHot) { if (IsItemGroup(pItemPressed)) { CXTPTaskPanelGroup* pGroup = (CXTPTaskPanelGroup*)pItemPressed; pGroup->SetExpanded(!pGroup->IsExpanded()); } else { OnClick((CXTPTaskPanelGroupItem*)pItemPressed); } } } void CXTPTaskPanel::OnCaptureChanged(CWnd* pWnd) { if (m_pItemPressed) { m_pItemPressed = NULL; Redraw(); } CWnd::OnCaptureChanged(pWnd); } void CXTPTaskPanel::OnStartItemDrag(CXTPTaskPanelGroupItem* pItem) { BOOL bAllowDrag = pItem->IsAllowDrag(); if (bAllowDrag == xtpTaskItemAllowDragNone) return; ASSERT(pItem); ReleaseCapture(); BOOL bAllowDragOutsideControl = (bAllowDrag & xtpTaskItemAllowDragMoveOutsideControl) || (bAllowDrag & xtpTaskItemAllowDragCopyOutsideControl); if (NotifyOwner(XTP_TPN_STARTDRAG, (LPARAM)pItem) == XTP_ACTION_CANCEL) return; COleDataSource ds; if (!pItem->PrepareDrag(ds, bAllowDragOutsideControl)) return; m_pItemDragging = pItem; DROPEFFECT dropEffectMask = ((bAllowDrag & xtpTaskItemAllowDragCopyWithinGroup) || (bAllowDrag & xtpTaskItemAllowDragCopy) ? DROPEFFECT_COPY : 0) + ((bAllowDrag & xtpTaskItemAllowDragMoveWithinGroup) || (bAllowDrag & xtpTaskItemAllowDragMove) ? DROPEFFECT_MOVE : 0); DROPEFFECT dropEffect = ds.DoDragDrop(dropEffectMask); if ((dropEffect == DROPEFFECT_MOVE) && (dropEffectMask & DROPEFFECT_MOVE)) { m_pItemDragging->Remove(); } m_pItemDragOver = m_pItemDragging = NULL; } DROPEFFECT CXTPTaskPanel::OnDragOver(COleDataObject* pDataObject, DWORD dwKeyState, CPoint point) { DROPEFFECT dropEffectMask = DROPEFFECT_COPY + DROPEFFECT_MOVE; BOOL bCaption; CXTPTaskPanelGroup* pGroup = HitTestGroup(point, &bCaption); CXTPTaskPanelItem* pItemDragOverOld = m_pItemDragOver; if (pGroup && pGroup->IsAllowDrop()) { m_pItemDragOver = pGroup; if (!bCaption) { CRect rcItem; CXTPTaskPanelItem* pItem = pGroup->HitTest(point, &rcItem); if (pItem && pItem->IsAllowDrop()) { if (!GetPaintManager()->m_bInvertDragRect) { pItem = rcItem.CenterPoint().y > point.y ? pItem : pGroup->GetNextVisibleItem(pItem->GetIndex()); } if (pItem) { m_pItemDragOver = pItem; } } } } else { m_pItemDragOver = NULL; } DROPEFFECT dropEffect = DROPEFFECT_NONE; if (m_pItemDragOver && m_nOLEDropMode) { dropEffect = DROPEFFECT_MOVE; if (dropEffect == DROPEFFECT_NONE) m_pItemDragOver = 0; } else { if (!pDataObject || !pDataObject->IsDataAvailable(GetClipboardFormat())) m_pItemDragOver = NULL; if (pDataObject && !pDataObject->IsDataAvailable(CF_TEXT) && (m_pItemDragging == 0)) m_pItemDragOver = NULL; if (m_pItemDragging) { BOOL bAllowDrag = m_pItemDragging->IsAllowDrag(); if (((bAllowDrag & xtpTaskItemAllowDragMoveWithinGroup) == 0) && ((bAllowDrag & xtpTaskItemAllowDragMoveWithinControl) == 0)) dropEffectMask &= ~DROPEFFECT_MOVE; if (((bAllowDrag & xtpTaskItemAllowDragCopyWithinGroup) == 0) && ((bAllowDrag & xtpTaskItemAllowDragCopyWithinControl) == 0)) dropEffectMask &= ~DROPEFFECT_COPY; if (m_pItemDragOver && m_pItemDragging->GetItemGroup() != pGroup) { if (bAllowDrag & xtpTaskItemAllowDragMoveWithinGroup) dropEffectMask &= ~DROPEFFECT_MOVE; if (bAllowDrag & xtpTaskItemAllowDragCopyWithinGroup) dropEffectMask &= ~DROPEFFECT_COPY; } if (m_pItemDragOver) { if (((bAllowDrag & xtpTaskItemAllowDragMoveWithinControl) == 0) && ((bAllowDrag & xtpTaskItemAllowDragMoveWithinGroup) == 0)) dropEffectMask &= ~DROPEFFECT_MOVE; if (((bAllowDrag & xtpTaskItemAllowDragCopyWithinControl) == 0) && ((bAllowDrag & xtpTaskItemAllowDragCopyWithinGroup) == 0)) dropEffectMask &= ~DROPEFFECT_COPY; } if (dropEffectMask == 0) m_pItemDragOver = 0; } } if (pItemDragOverOld != m_pItemDragOver) { Redraw(); } BOOL bGroupHover = IsItemGroup(m_pItemDragOver) && !((CXTPTaskPanelGroup*)m_pItemDragOver)->IsExpanded(); if (bGroupHover && !m_bTimerGroupHover) { UINT nHoverTime = 500; SystemParametersInfo(SPI_GETMOUSEHOVERTIME, 0, &nHoverTime, 0); SetTimer(TID_GROUPHOVER, nHoverTime, NULL); m_bTimerGroupHover = TRUE; } if (!bGroupHover && m_bTimerGroupHover) { KillTimer(TID_GROUPHOVER); m_bTimerGroupHover = FALSE; } if (!m_pItemDragOver) return DROPEFFECT_NONE; if (dropEffect != DROPEFFECT_NONE) return dropEffect; if (dropEffectMask & DROPEFFECT_COPY) { if (((dwKeyState & MK_CONTROL) == MK_CONTROL) || ((dropEffectMask & DROPEFFECT_MOVE) == 0)) return DROPEFFECT_COPY; } return dropEffectMask & DROPEFFECT_MOVE ? DROPEFFECT_MOVE : DROPEFFECT_NONE; } BOOL CXTPTaskPanel::OnDrop(COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point) { point; if (!m_pItemDragOver) return FALSE; CXTPTaskPanelItem* pItemDragOver = m_pItemDragOver; m_pItemDragOver = NULL; Redraw(); if (dropEffect != DROPEFFECT_COPY && dropEffect != DROPEFFECT_MOVE) return FALSE; if (m_nOLEDropMode && pDataObject) { return dropEffect != DROPEFFECT_NONE; } if (!pDataObject || !pDataObject->IsDataAvailable(GetClipboardFormat())) return FALSE; CXTPTaskPanelItem* pItemDrop = CXTPTaskPanelItem::CreateFromOleData(pDataObject); if (!pItemDrop) return FALSE; if (IsItemGroup(pItemDragOver)) { CXTPTaskPanelItems* pItems = ((CXTPTaskPanelGroup*)pItemDragOver)->GetItems(); pItems->InsertAt(pItems->GetCount(), pItemDrop); } else { CXTPTaskPanelItems* pItems = pItemDragOver->GetParentItems(); int nIndex = pItemDragOver->GetIndex(); if (GetPaintManager()->m_bInvertDragRect) { nIndex++; if (m_pItemDragging && m_pItemDragging->GetParentItems() == pItems) { if (m_pItemDragging->GetIndex() >= nIndex) nIndex--; } } pItems->InsertAt(nIndex, pItemDrop); } if (pItemDrop->IsAcceptFocus()) { SetFocusedItem(pItemDrop); } NotifyOwner(XTP_TPN_ITEMDROP, (LPARAM)pItemDrop); return TRUE; } void CXTPTaskPanel::OnStartGroupDrag(CXTPTaskPanelItem* pItem) { if (!pItem->IsAllowDrag()) return; SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZENS)); m_pItemDragging = pItem; Redraw(); while (CWnd::GetCapture() == this) { MSG msg; if (!GetMessageExt(msg)) break; if (msg.message == WM_LBUTTONUP) break; else if (msg.message == WM_MOUSEMOVE) { CPoint pt(msg.pt); ScreenToClient(&pt); BOOL bCaption; CXTPTaskPanelGroup* pHTGroup = HitTestGroup(pt, &bCaption); if (pHTGroup && bCaption && pHTGroup != pItem) { m_pGroups->Move(pItem, pHTGroup->GetIndex()); NotifyOwner(XTP_TPN_GROUPMOVE, (LPARAM)(CXTPTaskPanelGroup*)pItem); } } else if (msg.message == WM_KEYDOWN) { if (msg.wParam == VK_ESCAPE) { break; } } else DispatchMessage(&msg); } SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW)); m_pItemDragging = NULL; ReleaseCapture(); } void CXTPTaskPanel::CheckScrollButtonMouseOver(CPoint point) { CXTPTaskPanelScrollButton* pButtonHot = HitTestScrollButton(point); for (int i = 0; i < 2; i++) { BOOL bHot = (pButtonHot == m_pScrollButton[i]); if ((m_pScrollButton[i]->bHot && !bHot) || (!m_pScrollButton[i]->bHot && bHot)) { m_pScrollButton[i]->bHot = bHot; Redraw(); if (bHot) { TRACKMOUSEEVENT tme = { sizeof(TRACKMOUSEEVENT), TME_LEAVE, m_hWnd }; _TrackMouseEvent(&tme); } } } } void CXTPTaskPanel::OnMouseMove(UINT nFlags, CPoint point) { CWnd::OnMouseMove(nFlags, point); #if !defined(_XTP_ACTIVEX) && defined(_XTP_INCLUDE_COMMANDBARS) if (XTPMouseManager()->IsTrackedLock(NULL) || XTPMouseManager()->IsMouseLocked()) return; #endif CXTPTaskPanelItem* pItem = HitTestItem(point); BOOL bAccept = pItem && pItem->IsAcceptFocus() && CXTPDrawHelpers::IsTopParentActive(m_hWnd) && ((m_pItemPressed == NULL) || (m_pItemPressed == pItem)); SetHotItem(bAccept ? pItem : NULL); if (m_pItemPressed && (abs(m_ptPressed.x - point.x) + abs(m_ptPressed.y - point.y) > 4)) { if (IsItemGroup(m_pItemPressed)) OnStartGroupDrag(m_pItemPressed); else OnStartItemDrag((CXTPTaskPanelGroupItem*)m_pItemPressed); } CheckScrollButtonMouseOver(point); } void CXTPTaskPanel::OnMouseLeave() { SetHotItem(NULL); CheckScrollButtonMouseOver(CPoint(-1, -1)); } BOOL CXTPTaskPanel::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) { if (m_pItemHot) { ::SetCursor(m_hHandCursor); return TRUE; } return CWnd::OnSetCursor(pWnd, nHitTest, message); } void CXTPTaskPanel::OnDestroy() { m_pAnimation->OnDestroy(); CWnd::OnDestroy(); } BOOL CXTPTaskPanel::AnimateGroups(BOOL bCheckDirty) { BOOL bDirty = FALSE; for (int i = 0; i < GetGroupCount(); i++) { CXTPTaskPanelGroup* pGroup = GetAt(i); if (!bCheckDirty || pGroup->IsDirty()) { bDirty = TRUE; pGroup->OnAnimate(m_nAnimationStep); } } RepositionScrollButtons(); if (DYNAMIC_DOWNCAST(CXTPTaskPanelEditItem, GetFocus()) != 0) GrabFocus(); return bDirty; } void CXTPTaskPanel::OnTimer(UINT_PTR nIDEvent) { switch (nIDEvent) { case TID_REPOSITION: { BOOL bDirty = AnimateGroups(); Redraw(); m_nAnimationStep--; if (!bDirty) { KillTimer(m_nAnimateTimer); m_nAnimateTimer = 0; } } break; case TID_GROUPHOVER: if (IsItemGroup(m_pItemDragOver) && m_bTimerGroupHover) { ((CXTPTaskPanelGroup*)m_pItemDragOver)->SetExpanded(TRUE); } m_bTimerGroupHover = FALSE; KillTimer(TID_GROUPHOVER); break; case XTP_TID_ANIMATION: m_pAnimation->OnAnimate(); return; } CWnd::OnTimer(nIDEvent); } void CXTPTaskPanel::OnSysColorChange() { m_pPaintManager->RefreshMetrics(); Reposition(); CWnd::OnSysColorChange(); } #ifndef SPI_GETMENUANIMATION #define SPI_GETMENUANIMATION 0x1002 #endif void CXTPTaskPanel::SetAnimation(XTPTaskPanelAnimation panelAnimation) { m_eAnimation = panelAnimation; if (m_eAnimation == xtpTaskPanelAnimationYes) m_bAnimation = TRUE; else if (m_eAnimation == xtpTaskPanelAnimationNo) m_bAnimation = FALSE; else { m_bAnimation = FALSE; ::SystemParametersInfo(SPI_GETMENUANIMATION, 0, &m_bAnimation, 0); } } void CXTPTaskPanel::OnSettingChange(UINT uFlags, LPCTSTR lpszSection) { CWnd::OnSettingChange(uFlags, lpszSection); if (m_eAnimation == xtpTaskPanelAnimationSystem) SetAnimation(xtpTaskPanelAnimationSystem); m_pPaintManager->RefreshMetrics(); Reposition(); } CXTPTaskPanelItem* CXTPTaskPanel::GetFocusedItem() const { return m_pItemFocused; } BOOL CXTPTaskPanel::IsDrawFocusRect() const { return m_bDrawFocusRect && (::GetFocus() == m_hWnd); } HWND CXTPTaskPanel::GetNextControl(BOOL bForward) const { HWND hWnd = m_hWnd; HWND hWndParent = ::GetParent(hWnd); if (!hWnd || !hWndParent) { ASSERT(FALSE); return 0; } if ((GetWindowLong(hWndParent, GWL_EXSTYLE) & WS_EX_CONTROLPARENT) && (GetWindowLong(hWndParent, GWL_STYLE) & WS_CHILD)) { hWndParent = ::GetParent(hWndParent); } HWND hwndNextItem = ::GetNextDlgTabItem(hWndParent, hWnd, bForward); if (hwndNextItem == hWnd) return 0; return hwndNextItem; } void CXTPTaskPanel::CheckOldFocus(CWnd* pOldWnd) { if (!m_bGrabbingFocus && pOldWnd) { BOOL bShiftPressed = GetKeyState(VK_SHIFT) < 0; if (pOldWnd->m_hWnd == GetNextControl(!bShiftPressed)) { CXTPTaskPanelItem* pItem = GetNextItem(0, bShiftPressed ? -1 : 1, !m_bTabItems); if (pItem) { SetFocusedItem(pItem, TRUE); } } } } void CXTPTaskPanel::OnSetFocus(CWnd* pOldWnd) { CWnd::OnSetFocus(pOldWnd); CheckOldFocus(pOldWnd); Redraw(); } void CXTPTaskPanel::OnKillFocus(CWnd* pNewWnd) { CWnd::OnKillFocus(pNewWnd); m_bDrawFocusRect = FALSE; Redraw(); } CXTPTaskPanelGroup* CXTPTaskPanel::GetNextVisibleGroup(int nIndex, int nDirection) const { return GetAt(m_pGroups->GetNextVisibleIndex(nIndex, nDirection)); } CXTPTaskPanelItem* CXTPTaskPanel::GetNextItem(CXTPTaskPanelItem* pItem, int nDirection, BOOL bTab, BOOL bSkipRowItems) const { if (GetGroupCount() == 0) return NULL; CXTPTaskPanelGroup* pGroupCheck = NULL; do { if (nDirection > 0) { if (pItem) { pGroupCheck = pItem->GetItemGroup(); if (IsItemGroup(pItem)) pItem = pGroupCheck->GetItems()->GetFirstVisibleItem(); else { if (bTab) pItem = NULL; else pItem = pGroupCheck->GetNextVisibleItem(pItem->GetIndex(), bSkipRowItems ? pGroupCheck->GetItemsInRow() : 1); } } if (!pItem) { pItem = GetNextVisibleGroup(pGroupCheck ? pGroupCheck->GetIndex() : -1); } } else { if (!pItem && !pGroupCheck) { pGroupCheck = GetNextVisibleGroup(GetGroupCount(), - 1); pItem = pGroupCheck ? pGroupCheck->GetItems()->GetLastVisibleItem() : 0; } else if (IsItemGroup(pItem)) { pGroupCheck = GetNextVisibleGroup(pItem->GetIndex(), - 1); pItem = pGroupCheck ? pGroupCheck->GetItems()->GetLastVisibleItem() : NULL; } else if (pItem) { pGroupCheck = pItem->GetItemGroup(); if (bTab) pItem = NULL; else pItem = pGroupCheck->GetNextVisibleItem(pItem->GetIndex(), -(bSkipRowItems ? pGroupCheck->GetItemsInRow() : 1)); } if (!pItem) pItem = pGroupCheck; } if (!(IsItemLink(pItem) && pGroupCheck && !pGroupCheck->IsExpanded())) if (pItem && pItem->IsAcceptFocus()) return pItem; } while (pItem); return NULL; } void CXTPTaskPanel::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { CWnd::OnKeyDown(nChar, nRepCnt, nFlags); CXTPDrawHelpers::KeyToLayout(this, nChar); switch (nChar) { case VK_HOME: case VK_END: if (m_pItemFocused) { CXTPTaskPanelItems* pItems = m_pItemFocused->GetParentItems(); CXTPTaskPanelItem* pItem = nChar == VK_HOME ? pItems->GetFirstVisibleItem() : pItems->GetLastVisibleItem(); if (pItem && pItem->IsAcceptFocus()) SetFocusedItem(pItem, TRUE); } break; case VK_DOWN: case VK_UP: case VK_RIGHT: case VK_LEFT: { BOOL bSkipRowItems = (nChar == VK_DOWN || nChar == VK_UP); int nDirection = (nChar == VK_DOWN || nChar == VK_RIGHT ? +1 : -1); if (!IsExplorerBehaviour() && GetKeyState(VK_CONTROL) < 0 && m_pActiveGroup) { CXTPTaskPanelGroup* pActiveGroup = GetNextVisibleGroup(m_pActiveGroup->GetIndex(), nDirection); if (pActiveGroup && pActiveGroup->IsAcceptFocus()) { pActiveGroup->SetExpanded(TRUE); SetFocusedItem(pActiveGroup); } return; } CXTPTaskPanelItem* pItem = GetNextItem(m_pItemFocused, nDirection, FALSE, bSkipRowItems); if (pItem) SetFocusedItem(pItem, TRUE); } break; case VK_TAB: { BOOL bShiftPressed = GetKeyState(VK_SHIFT) < 0; CXTPTaskPanelItem* pItem = GetNextItem(m_pItemFocused, bShiftPressed ? -1 : +1, !m_bTabItems); if (pItem) { SetFocusedItem(pItem, TRUE); } else { HWND hWnd = GetNextControl(bShiftPressed); if (hWnd) { ::SetFocus(hWnd); } } } break; case VK_RETURN: case VK_SPACE: if (m_pItemFocused && m_pItemFocused->IsAcceptFocus()) { if (IsItemGroup(m_pItemFocused)) { ((CXTPTaskPanelGroup*)m_pItemFocused)->SetExpanded(!((CXTPTaskPanelGroup*)m_pItemFocused)->IsExpanded()); } else if (IsItemLink(m_pItemFocused)) { OnClick((CXTPTaskPanelGroupItem*)m_pItemFocused); } } break; } } void CXTPTaskPanel::OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { CWnd::OnKeyUp(nChar, nRepCnt, nFlags); } void CXTPTaskPanel::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) { CWnd::OnSysKeyUp(nChar, nRepCnt, nFlags); } void CXTPTaskPanel::OnSysKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) { CWnd::OnSysKeyUp(nChar, nRepCnt, nFlags); } BOOL CXTPTaskPanel::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) { if (m_bScrollVisible) { // its horizontal scroll bar int nCurPos = GetScrollPos(SB_VERT); if (zDelta > 0) nCurPos = max(nCurPos - 10, 0); else nCurPos = min(nCurPos + 10, GetScrollLimit(SB_VERT)); OnScrollChanged(nCurPos); Redraw(); } else if (GetBehaviour() != xtpTaskPanelBehaviourExplorer && m_pActiveGroup) { BOOL bScrollButtonUp = zDelta > 0; for (int i = 0; i < 3; i++) { if (!m_pActiveGroup->IsScrollButtonEnabled(bScrollButtonUp)) break; int nScrollOffset = (bScrollButtonUp ? -1 : +1) * m_pActiveGroup->GetItemsInRow(); m_pActiveGroup->Scroll(nScrollOffset); } Redraw(); } return CWnd::OnMouseWheel(nFlags, zDelta, pt); } BOOL CXTPTaskPanel::PreCreateWindow(CREATESTRUCT& cs) { if (!CWnd::PreCreateWindow(cs)) return FALSE; // // PreCreateWindow is called when a control is dynamically // created. We want to set m_bPreSubclassWindow to FALSE // here so the control is initialized from CWnd::Create and // not CWnd::PreSubclassWindow. // m_bPreSubclassWindow = FALSE; return TRUE; } void CXTPTaskPanel::PreSubclassWindow() { if (m_bPreSubclassWindow) { m_pDropTarget->Register(this); } } INT_PTR CXTPTaskPanel::OnToolHitTest(CPoint point, TOOLINFO* pTI) const { ASSERT_VALID(this); ASSERT(::IsWindow(m_hWnd)); // check child windows first by calling CControlBar INT_PTR nHit = CWnd::OnToolHitTest(point, pTI); if (nHit != -1) return nHit; #if !defined(_XTP_ACTIVEX) && defined(_XTP_INCLUDE_COMMANDBARS) if (XTPMouseManager()->IsTrackedLock(NULL) || XTPMouseManager()->IsMouseLocked()) return -1; #endif CXTPTaskPanelItem* pItem = HitTestItem(point); if (pItem) { nHit = pItem->GetID(); CString strTip = pItem->GetTooltip(); if (strTip.GetLength() == 0) return -1; CXTPToolTipContext::FillInToolInfo(pTI, m_hWnd, pItem->GetHitTestRect(), nHit, strTip, pItem->GetCaption(), strTip, GetImageManager()); return nHit; } return -1; } UINT CXTPTaskPanel::OnGetDlgCode() { return DLGC_WANTARROWS | DLGC_WANTTAB | DLGC_WANTCHARS; } LRESULT CXTPTaskPanel::NotifyOwner(WPARAM wParam, LPARAM lParam) { if (!m_hWnd) return 0; return GetOwner()->SendMessage(XTPWM_TASKPANEL_NOTIFY, wParam, lParam); } void CXTPTaskPanel::ExpandGroup(CXTPTaskPanelGroup* pGroup, BOOL bExpanded) { ASSERT(pGroup); if (!pGroup) return; if (IsExplorerBehaviour()) { XTP_TPNGROUPEXPANDING NMGROUPEXPANDING; NMGROUPEXPANDING.bExpanding = bExpanded; NMGROUPEXPANDING.pGroup = pGroup; if (NotifyOwner(XTP_TPN_GROUPEXPANDING, (LPARAM)&NMGROUPEXPANDING) == XTP_ACTION_CANCEL) return; pGroup->m_bExpanded = bExpanded; pGroup->m_bExpanding = TRUE; } else if (bExpanded) { XTP_TPNGROUPEXPANDING NMGROUPEXPANDING; NMGROUPEXPANDING.bExpanding = TRUE; NMGROUPEXPANDING.pGroup = pGroup; if (NotifyOwner(XTP_TPN_GROUPEXPANDING, (LPARAM)&NMGROUPEXPANDING) == XTP_ACTION_CANCEL) return; if (m_pActiveGroup) { if (m_pActiveGroup->IsExpandable()) { m_pActiveGroup->m_bExpanded = FALSE; m_pActiveGroup->m_bExpanding = TRUE; } m_pActiveGroup->InternalRelease(); } m_pActiveGroup = pGroup; m_pActiveGroup->InternalAddRef(); m_pActiveGroup->m_bExpanding = TRUE; m_pActiveGroup->m_bExpanded = TRUE; } Reposition(); } BOOL CXTPTaskPanel::IsGroupExpanded(const CXTPTaskPanelGroup* pGroup) const { return IsExplorerBehaviour() ? pGroup->m_bExpanded : (m_pActiveGroup == pGroup) || (pGroup->m_bExpanded && !pGroup->m_bExpandable); } XTPTaskPanelHotTrackStyle CXTPTaskPanel::GetHotTrackStyle() const { if (m_hotTrackStyle != xtpTaskPanelHighlightDefault) return m_hotTrackStyle; if (m_panelBehaviour == xtpTaskPanelBehaviourExplorer) return xtpTaskPanelHighlightText; if (m_panelBehaviour == xtpTaskPanelBehaviourToolbox) return xtpTaskPanelHighlightItem; return xtpTaskPanelHighlightImage; } void CXTPTaskPanel::SetHotTrackStyle(XTPTaskPanelHotTrackStyle hotTrackStyle) { m_hotTrackStyle = hotTrackStyle; Reposition(); } XTPTaskPanelItemLayout CXTPTaskPanel::GetItemLayout() const { if (m_itemLayout != xtpTaskItemLayoutDefault) return m_itemLayout; if (m_panelBehaviour == xtpTaskPanelBehaviourList) return xtpTaskItemLayoutImagesWithTextBelow; return xtpTaskItemLayoutImagesWithText; } void CXTPTaskPanel::SetItemLayout(XTPTaskPanelItemLayout itemLayout) { m_itemLayout = itemLayout; Reposition(); } void CXTPTaskPanel::SetBehaviour(XTPTaskPanelBehaviour panelBehaviour) { m_panelBehaviour = panelBehaviour; Reposition(); } XTPTaskPanelBehaviour CXTPTaskPanel::GetBehaviour() const { return m_panelBehaviour; } void CXTPTaskPanel::OnItemRemoved(CXTPTaskPanelItem* pItem) { ASSERT(pItem); if (!pItem) return; if (m_pActiveGroup == pItem) { m_pActiveGroup->InternalRelease(); m_pActiveGroup = NULL; } if (m_pItemHot == pItem) { m_pItemHot->InternalRelease(); m_pItemHot = NULL; } if (m_pItemFocused == pItem) { m_pItemFocused->InternalRelease(); m_pItemFocused = NULL; } if (m_pScrollButton[TRUE]->pGroupCaption == pItem) m_pScrollButton[TRUE]->pGroupCaption = NULL; if (m_pScrollButton[TRUE]->pGroupScroll == pItem) m_pScrollButton[TRUE]->pGroupScroll = NULL; if (m_pScrollButton[FALSE]->pGroupCaption == pItem) m_pScrollButton[FALSE]->pGroupCaption = NULL; if (m_pScrollButton[FALSE]->pGroupScroll == pItem) m_pScrollButton[FALSE]->pGroupScroll = NULL; NotifyOwner(XTP_TPN_ITEMREMOVED, (LPARAM)pItem); } BOOL CXTPTaskPanel::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult) { if (m_pToolTipContext) { m_pToolTipContext->FilterToolTipMessage(this, message, wParam, lParam); } return CWnd::OnWndMsg(message, wParam, lParam, pResult); } HWND CXTPTaskPanel::GetRootChild(HWND hWndTaskPanel, HWND hWnd) { HWND hwndParent = ::GetParent(hWnd); while (hwndParent != hWndTaskPanel) { hWnd = hwndParent; hwndParent = ::GetParent(hWnd); if (hwndParent == NULL) return NULL; } return hWnd; } CXTPTaskPanelGroupItem* CXTPTaskPanel::FindControlItem(HWND hWnd) { for (int i = 0; i < GetGroupCount(); i++) { CXTPTaskPanelGroup* pGroup = GetAt(i); for (int j = 0; j < pGroup->GetItemCount(); j++) { if (pGroup->GetAt(j)->GetControlHandle() == hWnd) return pGroup->GetAt(j); } } return NULL; } BOOL CXTPTaskPanel::PreTranslateMessage(MSG* pMsg) { if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_TAB && m_bTabItems) { HWND hWnd = ::GetFocus(); if (hWnd && hWnd != m_hWnd && ::IsChild(m_hWnd, hWnd)) { HWND hWndDlg = GetRootChild(m_hWnd, hWnd); if (!hWndDlg) return CWnd::PreTranslateMessage(pMsg); BOOL bShiftPressed = GetKeyState(VK_SHIFT) < 0; HWND hWndFirst = ::GetNextDlgTabItem(hWndDlg, NULL, FALSE); if (bShiftPressed) hWndFirst = ::GetNextDlgTabItem(hWndDlg, hWndFirst, TRUE); HWND hWndNext = ::GetNextDlgTabItem(hWndDlg, hWnd, bShiftPressed); if (hWndNext && hWndNext != hWnd && hWndNext != hWndDlg && hWndNext != hWndFirst) { ::SetFocus(hWndNext); return TRUE; } CXTPTaskPanelGroupItem* pItemFocused = FindControlItem(hWndDlg); if (pItemFocused) { CXTPTaskPanelItem* pItem = GetNextItem(pItemFocused, bShiftPressed ? -1 : +1, !m_bTabItems); if (!pItem) { hWndNext = GetNextControl(bShiftPressed); if (hWndNext) { ::SetFocus(hWndNext); return TRUE; } pItem = GetNextItem(NULL, bShiftPressed ? -1 : +1, !m_bTabItems); } if (pItem) { if (pItem == m_pItemFocused) { CMDTARGET_RELEASE(m_pItemFocused); } SetFocusedItem(pItem, TRUE); if (pItem->GetType() == xtpTaskItemTypeControl && bShiftPressed && pItemFocused != pItem) { hWndDlg = ((CXTPTaskPanelGroupItem*)m_pItemFocused)->GetControlHandle(); if (hWndDlg) hWndFirst = ::GetNextDlgTabItem(hWndDlg, NULL, FALSE); if (hWndFirst) hWndFirst = ::GetNextDlgTabItem(hWndDlg, hWndFirst, TRUE); if (hWndFirst) ::SetFocus(hWndFirst); } } return TRUE; } } } return CWnd::PreTranslateMessage(pMsg); } CXTPToolTipContext* CXTPTaskPanel::GetToolTipContext() const { return m_pToolTipContext; } void CXTPTaskPanel::SetLayoutRTL(BOOL bRightToLeft) { if (!XTPSystemVersion()->IsLayoutRTLSupported()) return; if (!m_hWnd) return; ModifyStyleEx(bRightToLeft ? 0 : WS_EX_LAYOUTRTL, !bRightToLeft ? 0 : WS_EX_LAYOUTRTL); GetImageManager()->DrawReverted(bRightToLeft); Reposition(); } LRESULT CXTPTaskPanel::OnGetObject(WPARAM wParam, LPARAM lParam) { if (((LONG)lParam) != OBJID_CLIENT) return (LRESULT)Default(); LPUNKNOWN lpUnknown = GetInterface(&IID_IAccessible); if (!lpUnknown) return E_FAIL; return LresultFromObject(IID_IAccessible, wParam, lpUnknown); } BEGIN_INTERFACE_MAP(CXTPTaskPanel, CCmdTarget) INTERFACE_PART(CXTPTaskPanel, IID_IAccessible, ExternalAccessible) END_INTERFACE_MAP() CCmdTarget* CXTPTaskPanel::GetAccessible() { return this; } HRESULT CXTPTaskPanel::GetAccessibleParent(IDispatch* FAR* ppdispParent) { *ppdispParent = NULL; if (GetSafeHwnd()) { return AccessibleObjectFromWindow(GetSafeHwnd(), OBJID_WINDOW, IID_IDispatch, (void**)ppdispParent); } return E_FAIL; } int CXTPTaskPanel::GetAccessibleIndex(CXTPTaskPanelItem* pItem) { int nCount = 0; for (int i = 0; i < GetGroupCount(); i++) { CXTPTaskPanelGroup* pGroup = GetAt(i); nCount++; if (pItem) { if (pGroup == pItem) return nCount; if (pItem->GetItemGroup() == pGroup) return nCount + pItem->GetIndex() + 1; } nCount += pGroup->GetItemCount(); } return nCount; } CXTPTaskPanelItem* CXTPTaskPanel::GetAccessibleItem(int nIndex) { for (int i = 0; i < GetGroupCount(); i++) { CXTPTaskPanelGroup* pGroup = GetAt(i); nIndex--; if (nIndex == 0) return pGroup; if (nIndex <= pGroup->GetItemCount()) return pGroup->GetAt(nIndex - 1); nIndex -= pGroup->GetItemCount(); } return NULL; } HRESULT CXTPTaskPanel::GetAccessibleChildCount(long FAR* pChildCount) { if (pChildCount == 0) { return E_INVALIDARG; } *pChildCount = GetAccessibleIndex(NULL); return S_OK; } HRESULT CXTPTaskPanel::GetAccessibleChild(VARIANT varChild, IDispatch* FAR* ppdispChild) { *ppdispChild = NULL; int nChild = GetChildIndex(&varChild); if (nChild <= 0) { return E_INVALIDARG; } CXTPTaskPanelItem* pItem = GetAccessibleItem(nChild); if (!pItem) { return E_INVALIDARG; } *ppdispChild = pItem->GetIDispatch(TRUE); return S_OK; } HRESULT CXTPTaskPanel::GetAccessibleName(VARIANT varChild, BSTR* pszName) { int nChild = GetChildIndex(&varChild); if (nChild == CHILDID_SELF || nChild == -1) { CString strCaption; GetWindowText(strCaption); *pszName = strCaption.AllocSysString(); return S_OK; } return E_INVALIDARG; } HRESULT CXTPTaskPanel::GetAccessibleRole(VARIANT varChild, VARIANT* pvarRole) { pvarRole->vt = VT_EMPTY; int nChild = GetChildIndex(&varChild); if (nChild == CHILDID_SELF) { pvarRole->vt = VT_I4; pvarRole->lVal = ROLE_SYSTEM_OUTLINE; return S_OK; } return E_INVALIDARG; } HRESULT CXTPTaskPanel::GetAccessibleState(VARIANT varChild, VARIANT* pvarState) { pvarState->vt = VT_I4; pvarState->lVal = 0; int nChild = GetChildIndex(&varChild); if (nChild == CHILDID_SELF) { pvarState->lVal = STATE_SYSTEM_FOCUSABLE; } return S_OK; } HRESULT CXTPTaskPanel::AccessibleLocation(long* pxLeft, long* pyTop, long* pcxWidth, long* pcyHeight, VARIANT varChild) { *pxLeft = *pyTop = *pcxWidth = *pcyHeight = 0; if (!GetSafeHwnd()) return S_OK; CRect rc; GetWindowRect(&rc); int nChild = GetChildIndex(&varChild); if (nChild > 0) { CXTPTaskPanelItem* pItem = GetAccessibleItem(nChild); if (pItem) { CRect rcItem = pItem->GetHitTestRect(); rc = CRect(CPoint(rc.left + rcItem.left, rc.top + rcItem.top), rcItem.Size()); } } *pxLeft = rc.left; *pyTop = rc.top; *pcxWidth = rc.Width(); *pcyHeight = rc.Height(); return S_OK; } HRESULT CXTPTaskPanel::AccessibleHitTest(long xLeft, long yTop, VARIANT* pvarID) { if (pvarID == NULL) return E_INVALIDARG; pvarID->vt = VT_EMPTY; if (!GetSafeHwnd()) return S_FALSE; if (!CXTPWindowRect(this).PtInRect(CPoint(xLeft, yTop))) return S_FALSE; pvarID->vt = VT_I4; pvarID->lVal = 0; CPoint pt(xLeft, yTop); ScreenToClient(&pt); CXTPTaskPanelItem* pItem = HitTestItem(pt); if (pItem) { pvarID->vt = VT_DISPATCH; pvarID->pdispVal = pItem->GetIDispatch(TRUE); } return S_OK; }