/** * @file XTPDockingPaneKeyboardHook.cpp * * @copyright * (c) 1998-2025 Codejock Software, All Rights Reserved. * * This source file is the property of Codejock Software and must not be * redistributed by any means without the explicit written permission of * Codejock Software. * * The use of this source code is governed by the terms and conditions specified * in the Toolkit Pro license agreement. Codejock Software grants you, as a * single software developer, the limited right to use this software on one * computer only. * * Contact Information: * support@codejock.com * http://www.codejock.com * */ #include "stdafx.h" #include "Common/XTPVC80Helpers.h" #include "Common/XTPTypeId.h" #include "Common/XTPCasting.h" #include "Common/XTPFramework.h" #include "Common/XTPSystemHelpers.h" #include "Common/XTPSynchro.h" #include "Common/XTPApplication.h" #include "Common/XTPSingleton.h" #include "Common/XTPGdiObjects.h" #include "Common/XTPResourceManager.h" #include "Common/XTPImageManager.h" #include "Common/XTPDrawHelpers.h" #include "Common/XTPColorManager.h" #include "Common/XTPHookManager.h" #include "Common/ScrollBar/XTPScrollBase.h" #include "Common/ScrollBar/XTPScrollBarCtrl.h" #include "Common/ScrollBar/XTPScrollable.h" #include "Common/ScrollBar/XTPScrollInfo.h" #include "Common/Hook/XTPWinEventHook.h" #include "Common/FrameShadow/XTPFrameShadowManager.h" #include "Common/XTPMaskEditT.h" #include "Common/Resource.h" #include "TabManager/Includes.h" #include "DockingPane/Resource.h" #include "DockingPane/XTPDockingPaneDefines.h" #include "DockingPane/XTPDockingPaneBase.h" #include "DockingPane/XTPDockingPaneKeyboardHook.h" #include "DockingPane/XTPDockingPane.h" #include "DockingPane/XTPDockingPanePaintManager.h" #include "DockingPane/XTPDockingPaneManager.h" #include "DockingPane/XTPDockingPaneMiniWnd.h" #ifdef _XTP_INCLUDE_CONTROLS # include "Controls/Util/XTPControlTheme.h" # include "Controls/Edit/XTPEdit.h" #endif #ifdef _XTP_INCLUDE_COMMANDBARS # include "CommandBars/XTPCommandBarsDefines.h" # include "CommandBars/XTPPaintManager.h" # include "CommandBars/XTPCommandBars.h" # include "CommandBars/XTPCommandBar.h" # include "CommandBars/XTPPopupBar.h" # include "CommandBars/XTPToolBar.h" # include "CommandBars/XTPMenuBar.h" # include "CommandBars/XTPMenuTitleBar.h" # include "CommandBars/XTPControls.h" # include "CommandBars/XTPControl.h" # include "CommandBars/XTPControlButton.h" # include "CommandBars/XTPControlEdit.h" # include "CommandBars/XTPControlExt.h" # include "CommandBars/XTPMouseManager.h" # include "CommandBars/XTPShortcutManager.h" # include "CommandBars/XTPFrameWnd.h" # include "CommandBars/XTPCommandBarsIIDs.h" # include "CommandBars/XTPTabClientWnd.h" # include "CommandBars/Frame/XTPFrameHook.h" # include "CommandBars/TabClient/XTPTearOffFrame.h" #endif #include "Common/Base/Diagnostic/XTPDisableNoisyWarnings.h" #ifdef _DEBUG # define new DEBUG_NEW # undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CXTPDockingPaneWindowSelect IMPLEMENT_DYNCREATE(CXTPDockingPaneWindowSelect, CMiniFrameWnd) CXTPDockingPaneWindowSelect::CXTPDockingPaneWindowSelect() { LOGFONT lfIcon; VERIFY(CXTPDrawHelpers::GetIconLogFont(&lfIcon)); lfIcon.lfWeight = FW_NORMAL; m_fnt.CreateFontIndirect(&lfIcon); lfIcon.lfWeight = FW_BOLD; m_fntBold.CreateFontIndirect(&lfIcon); XTPResourceManager()->LoadString(&m_strActiveTools, XTP_IDS_DOCKINGPANE_SELECTWINDOW_ACTIVETOOLS); XTPResourceManager()->LoadString(&m_strActiveFiles, XTP_IDS_DOCKINGPANE_SELECTWINDOW_ACTIVEFILES); m_pSelected = NULL; m_pManager = NULL; m_bActivatePanes = FALSE; m_nPaneCount = 0; m_nFirstFile = 0; m_hHandCursor = AfxGetApp()->LoadStandardCursor(MAKEINTRESOURCE(32649)); if (m_hHandCursor == 0) m_hHandCursor = XTPResourceManager()->LoadCursor(XTP_IDC_HAND); m_hArrowCursor = AfxGetApp()->LoadStandardCursor(IDC_ARROW); } CXTPDockingPaneWindowSelect::~CXTPDockingPaneWindowSelect() { for (int i = 0; i < (int)m_arrItems.GetSize(); i++) { delete m_arrItems[i]; } m_arrItems.RemoveAll(); } int CXTPDockingPaneWindowSelect::CalcItemHeight(CDC* pDC) { CXTPFontDC font(pDC, &m_fnt); CSize szFont = pDC->GetTextExtent(_T(" "), 1); CSize szIcon = m_pManager->GetPaintManager()->GetTabPaintManager()->m_szIcon; return max(szIcon.cy + XTP_DPI_X(4), szFont.cy + XTP_DPI_Y(4)); } CXTPDockingPaneWindowSelect::CItem* CXTPDockingPaneWindowSelect::HitTest(CPoint point) const { for (int i = 0; i < (int)m_arrItems.GetSize(); i++) { CItem* pItem = m_arrItems[i]; if (pItem->rc.PtInRect(point)) { return pItem; } } return 0; } CString CXTPDockingPaneWindowSelect::GetItemCaption(CItem* pItem) const { if (pItem->type == itemPane) { return pItem->pPane->GetTitle(); } else { CString strCaption; CFrameWnd* pChild = DYNAMIC_DOWNCAST(CFrameWnd, CWnd::FromHandle(pItem->hWndFrame)); if (pChild && pChild->GetActiveDocument()) { strCaption = pChild->GetActiveDocument()->GetTitle(); } else { CXTPDrawHelpers::GetWindowCaption(pItem->hWndFrame, strCaption); } return strCaption; } } CString CXTPDockingPaneWindowSelect::GetItemDescription(CItem* pItem) const { if (pItem->type == itemPane) return _T(""); CFrameWnd* pChild = DYNAMIC_DOWNCAST(CFrameWnd, CWnd::FromHandle(pItem->hWndFrame)); if (!pChild) return _T(""); CDocument* pDocument = pChild->GetActiveDocument(); if (!pDocument) return _T(""); CString strTypeName; if (pDocument->GetDocTemplate() != NULL) pDocument->GetDocTemplate()->GetDocString(strTypeName, CDocTemplate::regFileTypeName); return strTypeName; } CString CXTPDockingPaneWindowSelect::GetItemPath(CItem* pItem) const { if (pItem->type == itemPane) return _T(""); CFrameWnd* pChild = DYNAMIC_DOWNCAST(CFrameWnd, CWnd::FromHandle(pItem->hWndFrame)); if (!pChild) return _T(""); CDocument* pDocument = pChild->GetActiveDocument(); if (!pDocument) return _T(""); return pDocument->GetPathName(); } HWND CXTPDockingPaneWindowSelect::GetMDIClient() const { #ifdef _XTP_ACTIVEX HWND hWndClient = OleFindMDIClient(m_pManager->GetSite()); #else CMDIFrameWnd* pFrame = DYNAMIC_DOWNCAST(CMDIFrameWnd, m_pManager->GetSite()); HWND hWndClient = pFrame ? pFrame->m_hWndMDIClient : NULL; #endif return hWndClient; } void CXTPDockingPaneWindowSelect::FillItems(HWND hWndClient, int& nItemHeight, int& nItemWidth, int& x, int& y, int& nRow, int& nColumn, int& nTotalRow, int& nFirstColumn) { HWND hWndActive = hWndClient ? (HWND)::SendMessage(hWndClient, WM_MDIGETACTIVE, 0, 0) : 0; if (hWndActive) { HWND hWndFrame = hWndActive; while (hWndFrame) { DWORD dwStyle = XTPToDWORD(GetWindowLong(hWndFrame, GWL_STYLE)); if (((dwStyle & WS_VISIBLE) != 0) && ((dwStyle & WS_DISABLED) == 0)) { if (nRow > 14) { CColumn colNext; colNext.nFirst = nFirstColumn; colNext.nLast = (int)m_arrItems.GetSize() - 1; m_arrColumns.Add(colNext); nTotalRow = max(nRow, nTotalRow); nFirstColumn = (int)m_arrItems.GetSize(); nRow = 0; nColumn++; y = nItemHeight + XTP_DPI_Y(13); x += nItemWidth + XTP_DPI_X(12); } CItem* pItem = new CItem; pItem->hWndFrame = hWndFrame; pItem->type = itemMDIFrame; pItem->rc = CRect(x, y, x + nItemWidth, y + nItemHeight); y += nItemHeight + XTP_DPI_Y(1); pItem->nIndex = (int)m_arrItems.Add(pItem); pItem->nColumn = nColumn; pItem->nRow = nRow; if (hWndActive == hWndFrame && !m_bActivatePanes) m_pSelected = pItem; nRow++; } hWndFrame = ::GetWindow(hWndFrame, GW_HWNDNEXT); } } } BOOL CXTPDockingPaneWindowSelect::Reposition() { CClientDC dc(this); int nItemHeight = CalcItemHeight(&dc); int nItemWidth = XTP_DPI_X(163); int y = nItemHeight + XTP_DPI_Y(13); int x = XTP_DPI_X(9); int nRow = 0; int nColumn = 0; m_pSelected = 0; int nTotalRow = 0; int nFirstColumn = 0; CXTPDockingPaneInfoList& paneList = m_pManager->GetPaneList(); POSITION pos = paneList.GetHeadPosition(); while (pos) { CXTPDockingPane* pPane = paneList.GetNext(pos); if ((pPane->GetEnabled() & xtpPaneEnableClient) == 0) continue; if (nColumn == 0 && m_pManager->IsClientHidden() && nRow > paneList.GetCount() / 2) { CColumn colNext; colNext.nFirst = 0; colNext.nLast = (int)m_arrItems.GetSize() - 1; m_arrColumns.Add(colNext); nTotalRow = max(nRow, nTotalRow); nFirstColumn = (int)m_arrItems.GetSize(); nRow = 0; nColumn++; y = nItemHeight + XTP_DPI_Y(13); x += nItemWidth + XTP_DPI_X(12); } CItem* pItem = new CItem; pItem->pPane = pPane; pItem->type = itemPane; pItem->rc = CRect(x, y, x + nItemWidth, y + nItemHeight); y += nItemHeight + XTP_DPI_Y(1); pItem->nIndex = (int)m_arrItems.Add(pItem); pItem->nColumn = nColumn; pItem->nRow = nRow; if (m_pManager->GetActivePane() == pPane) m_pSelected = pItem; nRow++; } m_nPaneCount = (int)m_arrItems.GetSize(); if (m_bActivatePanes && m_nPaneCount > 0) { if (m_pSelected == 0) { m_pSelected = m_arrItems[GetKeyState(VK_SHIFT) >= 0 ? 0 : nRow - 1]; } else { if (GetKeyState(VK_SHIFT) >= 0) { m_pSelected = m_arrItems[m_pSelected->nIndex >= nRow - 1 ? 0 : m_pSelected->nIndex + 1]; } else { m_pSelected = m_arrItems[m_pSelected->nIndex > 0 ? m_pSelected->nIndex - 1 : nRow - 1]; } } } nTotalRow = max(nRow, nTotalRow); if (m_nPaneCount > 0) { CColumn col; col.nFirst = nFirstColumn; col.nLast = (int)m_arrItems.GetSize() - 1; m_arrColumns.Add(col); } else { m_bActivatePanes = FALSE; } m_nFirstFile = (int)m_arrItems.GetSize(); nFirstColumn = m_nFirstFile; nRow = 0; if (m_nPaneCount > 0 && !m_pManager->IsClientHidden()) { nColumn++; x += nItemWidth + XTP_DPI_X(12); y = nItemHeight + XTP_DPI_Y(13); } HWND hWndClient = GetMDIClient(); if (m_pManager->IsClientHidden()) { } else if (hWndClient) { FillItems(hWndClient, nItemHeight, nItemWidth, x, y, nRow, nColumn, nTotalRow, nFirstColumn); #ifdef _XTP_INCLUDE_COMMANDBARS CXTPTabClientWnd* pTabClient = DYNAMIC_DOWNCAST(CXTPTabClientWnd, CWnd::FromHandle(hWndClient)); if (pTabClient && pTabClient->IsTearOffEnabled()) { CArray tabClients; pTabClient->GetTabClients(tabClients); for (int i = 0; i < tabClients.GetSize(); i++) { if (pTabClient == tabClients.GetAt(i)) continue; FillItems(tabClients.GetAt(i)->m_hWnd, nItemHeight, nItemWidth, x, y, nRow, nColumn, nTotalRow, nFirstColumn); } } #endif } else if (!hWndClient) { CItem* pItem = new CItem; pItem->hWndFrame = m_pManager->GetSite()->GetSafeHwnd(); pItem->type = itemSDIFrame; pItem->rc = CRect(x, y, x + nItemWidth, y + nItemHeight); pItem->nIndex = (int)m_arrItems.Add(pItem); pItem->nColumn = nColumn; pItem->nRow = nRow; if (m_pSelected == NULL) m_pSelected = pItem; m_nFirstFile++; } if (nFirstColumn < m_arrItems.GetSize()) { CColumn colNext; colNext.nFirst = nFirstColumn; colNext.nLast = (int)m_arrItems.GetSize() - 1; m_arrColumns.Add(colNext); } if (m_nFirstFile < m_arrItems.GetSize() - 1 && !m_bActivatePanes) { if (GetKeyState(VK_SHIFT) >= 0) m_pSelected = m_arrItems[m_nFirstFile + 1]; else m_pSelected = m_arrItems[m_arrItems.GetSize() - 1]; } nTotalRow = max(nRow, nTotalRow); int nTotalColumns = max(2, (int)m_arrColumns.GetSize()); CSize sz(XTP_DPI_X(4) + (nItemWidth + XTP_DPI_X(12)) * nTotalColumns, nItemHeight + XTP_DPI_Y(13) + nTotalRow * (nItemHeight + XTP_DPI_Y(1)) + XTP_DPI_Y(110)); CXTPWindowRect rcWindow(m_pManager->GetSite()); CPoint ptCenter = rcWindow.CenterPoint(); CRect rect(CPoint(ptCenter.x - sz.cx / 2, ptCenter.y - sz.cy / 2), sz); SetWindowPos(&CWnd::wndTopMost, rect.left, rect.top, rect.Width(), rect.Height(), SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_NOOWNERZORDER); return TRUE; } #include "Common/Base/Diagnostic/XTPBeginAfxMap.h" BEGIN_MESSAGE_MAP(CXTPDockingPaneWindowSelect, CMiniFrameWnd) //{{AFX_MSG_MAP(CXTPDockingPaneWindowSelect) ON_WM_KILLFOCUS() ON_WM_CAPTURECHANGED() ON_WM_PAINT() ON_WM_KEYDOWN() ON_WM_SYSKEYDOWN() ON_WM_KEYUP() ON_WM_LBUTTONDOWN() ON_WM_LBUTTONUP() ON_WM_MOUSEMOVE() ON_WM_CHAR() //}}AFX_MSG_MAP END_MESSAGE_MAP() #include "Common/Base/Diagnostic/XTPEndAfxMap.h" #define CS_DROPSHADOW 0x00020000 ///////////////////////////////////////////////////////////////////////////// // CXTPDockingPaneWindowSelect message handlers BOOL CXTPDockingPaneWindowSelect::DoModal() { CWnd* pSite = m_pManager->GetSite(); HWND hWndParent = pSite->GetSafeHwnd(); HWND hwndFocus = ::GetFocus(); BOOL bLayoutRTL = m_pManager->IsLayoutRTL(); UINT nClassStyle = UINT(bLayoutRTL ? 0 : CS_SAVEBITS | CS_OWNDC); if (XTPSystemVersion()->IsWinXPOrGreater()) // Windows XP only { nClassStyle |= CS_DROPSHADOW; } if (!CreateEx(DWORD(WS_EX_TOOLWINDOW | (bLayoutRTL ? WS_EX_LAYOUTRTL : 0)), AfxRegisterWndClass(nClassStyle, m_hArrowCursor), 0, WS_POPUP | MFS_SYNCACTIVE, CRect(0, 0, 0, 0), pSite, 0)) return FALSE; if (!Reposition()) { DestroyWindow(); return FALSE; } SetFocus(); SetCapture(); BOOL bEnableParent = FALSE; if (hWndParent != NULL && ::IsWindowEnabled(hWndParent)) { CWnd::ModifyStyle(hWndParent, 0, WS_DISABLED, 0); bEnableParent = TRUE; } m_nFlags |= WF_CONTINUEMODAL; if (m_nFlags & WF_CONTINUEMODAL) { // enter modal loop DWORD dwFlags = MLF_SHOWONIDLE; VERIFY(RunModalLoop(dwFlags) == m_nModalResult); } // hide the window before enabling the parent, etc. if (m_hWnd != NULL) SetWindowPos(NULL, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER); if (bEnableParent) CWnd::ModifyStyle(hWndParent, WS_DISABLED, 0, 0); if (hWndParent != NULL && ::GetActiveWindow() == m_hWnd) ::SetActiveWindow(hWndParent); if (m_nModalResult == IDOK && m_pSelected) { if (m_pSelected->type == itemPane) { m_pManager->ShowPane(m_pSelected->pPane); } else if (m_pSelected->type == itemMDIFrame) { HWND hWndClient = GetMDIClient(); ::SendMessage(hWndClient, WM_MDIACTIVATE, (WPARAM)m_pSelected->hWndFrame, 0); CWnd* pWnd = CWnd::FromHandle(m_pSelected->hWndFrame); CWnd* pFocus = GetFocus(); BOOL bHasFocus = pFocus->GetSafeHwnd() && (pFocus == pWnd || pWnd->IsChild(pFocus) || (pFocus->GetOwner()->GetSafeHwnd() && pWnd->IsChild(pFocus->GetOwner()))); if (!bHasFocus) pWnd->SetFocus(); } } else { ::SetFocus(hwndFocus); } DestroyWindow(); return TRUE; } void CXTPDockingPaneWindowSelect::OnKillFocus(CWnd* pNewWnd) { CWnd::OnKillFocus(pNewWnd); if (m_nFlags & WF_CONTINUEMODAL) EndModalLoop(IDCANCEL); } void CXTPDockingPaneWindowSelect::OnCaptureChanged(CWnd* pWnd) { if (m_nFlags & WF_CONTINUEMODAL) EndModalLoop(IDCANCEL); CWnd::OnCaptureChanged(pWnd); } void CXTPDockingPaneWindowSelect::OnPaint() { CPaintDC dcPaint(this); // device context for painting CXTPClientRect rc(this); CXTPBufferDC dc(dcPaint); dc.FillSolidRect(rc, GetSysColor(COLOR_3DFACE)); dc.Draw3dRect(rc, GetXtremeColor(XPCOLOR_HIGHLIGHT_BORDER), GetXtremeColor(XPCOLOR_HIGHLIGHT_BORDER)); int nItemHeight = CalcItemHeight(&dc); CXTPFontDC font(&dc, &m_fntBold); dc.SetBkMode(TRANSPARENT); dc.SetTextColor(GetXtremeColor(COLOR_BTNTEXT)); if (m_nPaneCount > 0) { CRect rcActiveTools(XTP_DPI_X(9), 0, XTP_DPI_X(9) + XTP_DPI_X(163), nItemHeight + XTP_DPI_Y(12)); dc.DrawText(m_strActiveTools, rcActiveTools, DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX); if (!m_pManager->IsClientHidden()) { CRect rcActiveFiles(XTP_DPI_X(9) + XTP_DPI_X(13) + XTP_DPI_X(163), 0, XTP_DPI_X(9) + XTP_DPI_X(13) + 2 * XTP_DPI_X(163), nItemHeight + XTP_DPI_Y(12)); dc.DrawText(m_strActiveFiles, rcActiveFiles, DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX); } } else { CRect rcActiveFiles(XTP_DPI_X(9), 0, XTP_DPI_X(9) + 2 * XTP_DPI_X(163), nItemHeight + XTP_DPI_Y(12)); dc.DrawText(m_strActiveFiles, rcActiveFiles, DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX); } font.SetFont(&m_fnt); CSize szIcon = m_pManager->GetPaintManager()->GetTabPaintManager()->m_szIcon; for (int i = 0; i < (int)m_arrItems.GetSize(); i++) { CItem* pItem = m_arrItems[i]; if (m_pSelected == pItem) { dc.FillSolidRect(pItem->rc, GetXtremeColor(XPCOLOR_HIGHLIGHT)); dc.Draw3dRect(pItem->rc, GetXtremeColor(XPCOLOR_HIGHLIGHT_BORDER), GetXtremeColor(XPCOLOR_HIGHLIGHT_BORDER)); } if (pItem->type == itemPane) { CPoint ptIcon(pItem->rc.left + 2, pItem->rc.CenterPoint().y - szIcon.cy / 2); CXTPImageManagerIcon* pImage = pItem->pPane->GetIcon(szIcon.cx); if (pImage) pImage->Draw(&dc, ptIcon, szIcon); } else { CPoint ptIcon(pItem->rc.left + XTP_DPI_X(2), pItem->rc.CenterPoint().y - szIcon.cy / 2); HICON hIcon = (HICON)::SendMessage(pItem->hWndFrame, WM_GETICON, ICON_SMALL, 0); if (hIcon == NULL) hIcon = (HICON)::SendMessage(pItem->hWndFrame, WM_GETICON, ICON_BIG, 0); if (hIcon == NULL) hIcon = (HICON)(ULONG_PTR)::GetClassLongPtr(pItem->hWndFrame, GCLP_HICONSM); if (hIcon) { if (GetExStyle() & WS_EX_LAYOUTRTL) ::DrawIconEx(dc, ptIcon.x + szIcon.cx, ptIcon.y, hIcon, -szIcon.cx, szIcon.cy, 0, 0, DI_NORMAL); else ::DrawIconEx(dc, ptIcon.x, ptIcon.y, hIcon, szIcon.cx, szIcon.cy, 0, 0, DI_NORMAL); } } CRect rcText(pItem->rc); rcText.left += XTP_DPI_X(5) + szIcon.cx; dc.DrawText(GetItemCaption(pItem), rcText, DT_SINGLELINE | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX); } CRect rcInfoPane(XTP_DPI_X(11), rc.bottom - XTP_DPI_Y(100), rc.right - XTP_DPI_X(11), rc.bottom - XTP_DPI_Y(10)); dc.Draw3dRect(rcInfoPane, GetXtremeColor(XPCOLOR_HIGHLIGHT_BORDER), GetXtremeColor(XPCOLOR_HIGHLIGHT_BORDER)); if (!m_pSelected) return; rcInfoPane.DeflateRect(XTP_DPI_X(15), XTP_DPI_Y(13), XTP_DPI_X(15), XTP_DPI_Y(13)); font.SetFont(&m_fntBold); CRect rcCaption(rcInfoPane.left, rcInfoPane.top, rcInfoPane.right, rcInfoPane.top + rcInfoPane.Height() / 3); dc.DrawText(GetItemCaption(m_pSelected), rcCaption, DT_SINGLELINE | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX); font.SetFont(&m_fnt); CRect rcTypeName(rcInfoPane.left, rcCaption.bottom, rcInfoPane.right, rcCaption.bottom + rcInfoPane.Height() / 3); dc.DrawText(GetItemDescription(m_pSelected), rcTypeName, DT_SINGLELINE | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX); CRect rcPathName(rcInfoPane.left, rcTypeName.bottom, rcInfoPane.right, rcInfoPane.bottom); dc.DrawText(GetItemPath(m_pSelected), rcPathName, DT_SINGLELINE | DT_VCENTER | DT_PATH_ELLIPSIS | DT_NOPREFIX); } void CXTPDockingPaneWindowSelect::Select(int nItem) { Select(nItem >= 0 && nItem < m_arrItems.GetSize() ? m_arrItems[nItem] : NULL); } void CXTPDockingPaneWindowSelect::Select(CItem* pItem) { if (m_pSelected != pItem) { m_pSelected = pItem; Invalidate(FALSE); } } void CXTPDockingPaneWindowSelect::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) { CMiniFrameWnd::OnChar(nChar, nRepCnt, nFlags); } void CXTPDockingPaneWindowSelect::OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { OnKeyDown(nChar, nRepCnt, nFlags); } void CXTPDockingPaneWindowSelect::OnKeyDown(UINT nChar, UINT /*nRepCnt*/, UINT /*nFlags*/) { XTPDrawHelpers()->KeyToLayout(this, nChar); if (nChar == VK_TAB) { if (GetKeyState(VK_SHIFT) >= 0) { int nSelected = m_pSelected ? m_pSelected->nIndex + 1 : 0; if (nSelected >= m_arrItems.GetSize()) nSelected = m_nFirstFile == m_arrItems.GetSize() ? 0 : m_nFirstFile; else if (nSelected == m_nFirstFile) nSelected = 0; Select(nSelected); } else { int nSelected = m_pSelected ? m_pSelected->nIndex - 1 : (int)m_arrItems.GetSize() - 1; if (nSelected < 0) nSelected = m_nFirstFile == 0 ? (int)m_arrItems.GetSize() - 1 : m_nFirstFile - 1; else if (nSelected == m_nFirstFile - 1) nSelected = (int)m_arrItems.GetSize() - 1; Select(nSelected); } } else if (nChar == VK_LEFT) { if (m_arrColumns.GetSize() > 1 && m_pSelected) { int nColumn = m_pSelected->nColumn; int nRow = m_pSelected->nRow; CColumn& col = m_arrColumns[nColumn > 0 ? nColumn - 1 : m_arrColumns.GetSize() - 1]; int nItem = col.nFirst + nRow > col.nLast ? col.nLast : col.nFirst + nRow; Select(nItem); } } else if (nChar == VK_RIGHT) { if (m_arrColumns.GetSize() > 1 && m_pSelected) { int nColumn = m_pSelected->nColumn; int nRow = m_pSelected->nRow; CColumn& col = m_arrColumns[nColumn < m_arrColumns.GetSize() - 1 ? nColumn + 1 : 0]; int nItem = col.nFirst + nRow > col.nLast ? col.nLast : col.nFirst + nRow; Select(nItem); } } else if (nChar == VK_DOWN) { int nSelected = m_pSelected ? m_pSelected->nIndex + 1 : 0; Select(nSelected < m_arrItems.GetSize() ? nSelected : 0); } else if (nChar == VK_UP) { int nSelected = m_pSelected ? m_pSelected->nIndex - 1 : -1; Select(nSelected >= 0 ? nSelected : (int)m_arrItems.GetSize() - 1); } else if (nChar == VK_SHIFT) { } else { EndModalLoop(IDOK); } } void CXTPDockingPaneWindowSelect::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) { if (::GetKeyState(VK_CONTROL) >= 0) { EndModalLoop(IDOK); } CWnd::OnKeyUp(nChar, nRepCnt, nFlags); } void CXTPDockingPaneWindowSelect::OnLButtonDown(UINT nFlags, CPoint point) { CXTPClientRect rc(this); if (!rc.PtInRect(point)) EndModalLoop(IDCANCEL); CItem* pItem = HitTest(point); if (pItem) { Select(pItem); } CWnd::OnLButtonDown(nFlags, point); } void CXTPDockingPaneWindowSelect::OnLButtonUp(UINT nFlags, CPoint point) { CItem* pItem = HitTest(point); if (pItem) { m_pSelected = pItem; EndModalLoop(IDOK); } CWnd::OnLButtonUp(nFlags, point); } void CXTPDockingPaneWindowSelect::OnMouseMove(UINT /*nFlags*/, CPoint point) { CItem* pItem = HitTest(point); ::SetCursor(pItem ? m_hHandCursor : m_hArrowCursor); } void CXTPDockingPaneWindowSelect::PostNcDestroy() { } ////////////////////////////////////////////////////////////////////////// // CXTPDockingPaneKeyboardHook CThreadLocal CXTPDockingPaneKeyboardHook::_xtpKeyboardThreadState; CXTPDockingPaneKeyboardHook::CXTPDockingPaneKeyboardHook() { m_pWindowSelect = 0; m_hHookKeyboard = 0; #ifdef _AFXDLL m_pModuleState = 0; #endif } CXTPDockingPaneKeyboardHook::~CXTPDockingPaneKeyboardHook() { _ASSERTE(m_mapSites.IsEmpty()); _ASSERTE(m_hHookKeyboard == 0); } CXTPDockingPaneManager* CXTPDockingPaneKeyboardHook::FindFocusedManager() { HWND hWnd = GetFocus(); while (hWnd) { CXTPDockingPaneManager* pManager = Lookup(hWnd); if (pManager) { if (!pManager->GetSite()->IsWindowEnabled()) return FALSE; return pManager; } LONG dwStyle = ::GetWindowLong(hWnd, GWL_STYLE); if (dwStyle & WS_CHILD) { hWnd = ::GetParent(hWnd); } else if (::GetWindowLong(hWnd, GWL_EXSTYLE) & WS_EX_TOOLWINDOW) { CXTPDockingPaneMiniWnd* pMinWnd = DYNAMIC_DOWNCAST(CXTPDockingPaneMiniWnd, CWnd::FromHandle(hWnd)); if (pMinWnd != NULL) return pMinWnd->GetDockingPaneManager(); return NULL; } else return NULL; } return NULL; } LRESULT CALLBACK CXTPDockingPaneKeyboardHook::KeyboardProc(int code, WPARAM wParam, LPARAM lParam) { CXTPDockingPaneKeyboardHook* pKeyboardManager = GetThreadState(); if (code != HC_ACTION) return CallNextHookEx(pKeyboardManager->m_hHookKeyboard, code, wParam, lParam); if ((!(HIWORD(lParam) & KF_UP))) { if (wParam == VK_TAB && GetKeyState(VK_CONTROL) < 0 && !(HIWORD(lParam) & KF_ALTDOWN)) { SAFE_MANAGE_STATE(pKeyboardManager->m_pModuleState); CXTPDockingPaneWindowSelect*& pWindowSelect = pKeyboardManager->m_pWindowSelect; if (pWindowSelect) { pWindowSelect->OnKeyDown(VK_TAB, 0, 0); return TRUE; } CXTPDockingPaneManager* pManager = pKeyboardManager->FindFocusedManager(); if (pManager && (pManager->IsKeyboardNavigateEnabled() & xtpPaneKeyboardUseCtrlTab)) { pWindowSelect = (CXTPDockingPaneWindowSelect*)pManager ->GetKeyboardWindowSelectClass() ->CreateObject(); pWindowSelect->m_pManager = pManager; pWindowSelect->m_bActivatePanes = FALSE; BOOL bResult = pWindowSelect->DoModal(); delete pWindowSelect; pWindowSelect = 0; if (bResult) return TRUE; } } if ((HIWORD(lParam) & KF_ALTDOWN) && (wParam == VK_F7) && GetKeyState(VK_CONTROL) >= 0) { SAFE_MANAGE_STATE(pKeyboardManager->m_pModuleState); CXTPDockingPaneWindowSelect*& pWindowSelect = pKeyboardManager->m_pWindowSelect; if (pWindowSelect) { pWindowSelect->OnKeyDown(VK_TAB, 0, 0); return TRUE; } CXTPDockingPaneManager* pManager = pKeyboardManager->FindFocusedManager(); if (pManager && (pManager->IsKeyboardNavigateEnabled() & xtpPaneKeyboardUseAltF7)) { pWindowSelect = (CXTPDockingPaneWindowSelect*)pManager ->GetKeyboardWindowSelectClass() ->CreateObject(); pWindowSelect->m_pManager = pManager; pWindowSelect->m_bActivatePanes = TRUE; BOOL bResult = pWindowSelect->DoModal(); delete pWindowSelect; pWindowSelect = 0; if (bResult) return TRUE; } } if ((HIWORD(lParam) & KF_ALTDOWN) && (wParam == VK_F6) && GetKeyState(VK_CONTROL) >= 0) // Alt + F6 { SAFE_MANAGE_STATE(pKeyboardManager->m_pModuleState); CXTPDockingPaneManager* pManager = pKeyboardManager->FindFocusedManager(); if (pManager && (pManager->IsKeyboardNavigateEnabled() & xtpPaneKeyboardUseAltF6)) { pManager->PostMessage(WM_SYSCOMMAND, (UINT)(GetKeyState(VK_SHIFT) >= 0 ? SC_NEXTWINDOW : SC_PREVWINDOW), 0); return TRUE; } } if ((HIWORD(lParam) & KF_ALTDOWN) && ((wParam == 0xBD || wParam == VK_SUBTRACT)) && GetKeyState(VK_CONTROL) >= 0 && GetKeyState(VK_SHIFT) >= 0) // Alt + '-' { SAFE_MANAGE_STATE(pKeyboardManager->m_pModuleState); CXTPDockingPaneManager* pManager = pKeyboardManager->FindFocusedManager(); if (pManager && (pManager->IsKeyboardNavigateEnabled() & xtpPaneKeyboardUseAltMinus)) { CXTPDockingPane* pPane = pManager->GetActivePane(); if (pPane) { if (!pPane->IsClosed() && !pPane->IsHidden()) pManager->PostMessage(WM_SYSCOMMAND, SC_KEYMENU, MAKELONG(TEXT('-'), 0)); return TRUE; } } } } return CallNextHookEx(pKeyboardManager->m_hHookKeyboard, code, wParam, lParam); } CXTPDockingPaneManager* CXTPDockingPaneKeyboardHook::Lookup(HWND hSite) const { CXTPDockingPaneManager* pManager = NULL; if (m_mapSites.Lookup(hSite, pManager)) return pManager; return NULL; } void CXTPDockingPaneKeyboardHook::SetupKeyboardHook(CXTPDockingPaneManager* pManager, BOOL bSetup) { if (!pManager->GetSite()) return; if (bSetup) { if (Lookup(pManager->GetSite()->GetSafeHwnd())) return; if (m_hHookKeyboard == 0) { m_hHookKeyboard = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, XTPGetInstanceHandle(), GetCurrentThreadId()); } #ifdef _AFXDLL m_pModuleState = AfxGetModuleState(); #endif m_mapSites.SetAt(pManager->GetSite()->GetSafeHwnd(), pManager); } else { if (Lookup(pManager->GetSite()->GetSafeHwnd())) { m_mapSites.RemoveKey(pManager->GetSite()->GetSafeHwnd()); } if (m_hHookKeyboard && m_mapSites.IsEmpty()) { UnhookWindowsHookEx(m_hHookKeyboard); m_hHookKeyboard = 0; } } }