// XTPDockingPaneContext.cpp : implementation of the CXTPDockingPaneContext class. // // This file is a part of the XTREME DOCKINGPANE 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/XTPColorManager.h" #include "Common/XTPDrawHelpers.h" #include "Common/XTPResourceManager.h" #include "Common/XTPSystemHelpers.h" #include "Common/XTPImageManager.h" #include "TabManager/XTPTabManager.h" #include "TabManager/XTPTabPaintManager.h" #include "XTPDockingPaneDefines.h" #include "XTPDockingPaneBase.h" #include "XTPDockingPaneBaseContainer.h" #include "XTPDockingPaneContext.h" #include "XTPDockingPane.h" #include "XTPDockingPaneManager.h" #include "XTPDockingPaneTabbedContainer.h" #include "XTPDockingPaneSplitterContainer.h" #include "XTPDockingPaneMiniWnd.h" #include "XTPDockingPaneSidePanel.h" #include "XTPDockingPanePaintManager.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif void AFX_CDECL CXTPDockingPaneContext::AdjustRectangle(CRect& rect, CPoint pt) { int nXOffset = (pt.x < rect.left) ? (pt.x - rect.left - 6) : (pt.x > rect.right) ? (pt.x - rect.right + 6) : 0; int nYOffset = (pt.y < rect.top) ? (pt.y - rect.top - 6) : (pt.y > rect.bottom) ? (pt.y - rect.bottom + 6) : 0; rect.OffsetRect(nXOffset, nYOffset); } void AFX_CDECL CXTPDockingPaneContext::AdjustCursor(CPoint& pt) { CRect rc = XTPMultiMonitor()->GetWorkArea(pt); if (pt.x < rc.left) pt.x = rc.left; if (pt.x > rc.right) pt.x = rc.right; if (pt.y < rc.top) pt.y = rc.top; if (pt.y > rc.bottom) pt.y = rc.bottom; } typedef BOOL (WINAPI *PFNSETLAYEREDWINDOWATTRIBUTES) (HWND hwnd, COLORREF crKey, BYTE bAlpha, DWORD dwFlags); #ifndef LWA_ALPHA #define LWA_ALPHA 0x00000002 #endif #ifndef WS_EX_LAYERED #define WS_EX_LAYERED 0x00080000 #endif ///////////////////////////////////////////////////////////////////////////// // CXTPDockingPaneContextAlphaWnd CXTPDockingPaneContextAlphaWnd::CXTPDockingPaneContextAlphaWnd() { } CXTPDockingPaneContextAlphaWnd::~CXTPDockingPaneContextAlphaWnd() { } BEGIN_MESSAGE_MAP(CXTPDockingPaneContextAlphaWnd, CWnd) //{{AFX_MSG_MAP(CXTPDockingPaneContextAlphaWnd) ON_WM_ERASEBKGND() ON_WM_PAINT() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CXTPDockingPaneContextAlphaWnd message handlers BOOL CXTPDockingPaneContextAlphaWnd::OnEraseBkgnd(CDC* /*pDC*/) { return TRUE; } void CXTPDockingPaneContextAlphaWnd::OnPaint() { CPaintDC dc(this); // device context for painting CRect rc; GetClientRect(&rc); dc.FillSolidRect(rc, GetSysColor(COLOR_HIGHLIGHT)); } ////////////////////////////////////////////////////////////////////////// // CXTPDockingPaneContextStickerWnd CXTPDockingPaneContextStickerWnd::CXTPDockingPaneContextStickerWnd(CXTPDockingPaneContext* pContext) : m_pContext(pContext) { m_typeSticker = m_selectedSticker = xtpPaneStickerNone; } CXTPDockingPaneContextStickerWnd::~CXTPDockingPaneContextStickerWnd() { } BEGIN_MESSAGE_MAP(CXTPDockingPaneContextStickerWnd, CWnd) //{{AFX_MSG_MAP(CXTPDockingPaneContextStickerWnd) ON_WM_ERASEBKGND() ON_WM_PAINT() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CXTPDockingPaneContextAlphaWnd message handlers BOOL CXTPDockingPaneContextStickerWnd::OnEraseBkgnd(CDC* /*pDC*/) { return TRUE; } struct CXTPDockingPaneContextStickerWnd::SPRITEINFO { SPRITEINFO(int x, int y, int left, int top, int cx, int cy) { ptDest = CPoint(x, y); rcSrc.SetRect(left, top, left + cx, top + cy); } CPoint ptDest; CRect rcSrc; }; #define SPRITE_STICKER_TOP 0 #define SPRITE_STICKER_LEFT 1 #define SPRITE_STICKER_BOTTOM 2 #define SPRITE_STICKER_RIGHT 3 #define SPRITE_STICKER_TOP_SELECTED 4 #define SPRITE_STICKER_LEFT_SELECTED 5 #define SPRITE_STICKER_BOTTOM_SELECTED 6 #define SPRITE_STICKER_RIGHT_SELECTED 7 #define SPRITE_STICKER_CENTER 8 #define SPRITE_STICKER_CENTER_SELECTED 9 #define SPRITE_STICKER_CLIENT 10 static CXTPDockingPaneContextStickerWnd::SPRITEINFO arrSpritesStyckerWidbey[] = { CXTPDockingPaneContextStickerWnd::SPRITEINFO(25, 0, 0, 0, 43, 30), CXTPDockingPaneContextStickerWnd::SPRITEINFO(0, 25, 30, 33, 30, 43), CXTPDockingPaneContextStickerWnd::SPRITEINFO(25, 63, 43, 0, 43, 30), CXTPDockingPaneContextStickerWnd::SPRITEINFO(63, 25, 0, 33, 30, 43), CXTPDockingPaneContextStickerWnd::SPRITEINFO(25, 0, 0, 76, 43, 30), CXTPDockingPaneContextStickerWnd::SPRITEINFO(0, 25, 90, 33, 30, 43), CXTPDockingPaneContextStickerWnd::SPRITEINFO(25, 63, 43, 76, 43, 30), CXTPDockingPaneContextStickerWnd::SPRITEINFO(63, 25, 60, 33, 30, 43), CXTPDockingPaneContextStickerWnd::SPRITEINFO(30, 30, 86, 0, 33, 33), CXTPDockingPaneContextStickerWnd::SPRITEINFO(30, 30, 86, 76, 33, 33), CXTPDockingPaneContextStickerWnd::SPRITEINFO(25, 25, 0, 0, 43, 43), }; static CXTPDockingPaneContextStickerWnd::SPRITEINFO arrSpritesStyckerVisualStudio2005[] = { CXTPDockingPaneContextStickerWnd::SPRITEINFO(30, 0, 61, 29, 29, 30), CXTPDockingPaneContextStickerWnd::SPRITEINFO(0, 30, 90, 30, 30, 29), CXTPDockingPaneContextStickerWnd::SPRITEINFO(30, 59, 91, 0, 29, 30), CXTPDockingPaneContextStickerWnd::SPRITEINFO(60, 30, 62, 0, 30, 29), CXTPDockingPaneContextStickerWnd::SPRITEINFO(30, 0, 61, 29 + 61, 29, 30), CXTPDockingPaneContextStickerWnd::SPRITEINFO(0, 30, 90, 30 + 61, 30, 29), CXTPDockingPaneContextStickerWnd::SPRITEINFO(30, 59, 91, 0 + 61, 29, 30), CXTPDockingPaneContextStickerWnd::SPRITEINFO(60, 30, 62, 0 + 61, 30, 29), CXTPDockingPaneContextStickerWnd::SPRITEINFO(30, 30, 120, 82, 28, 29), CXTPDockingPaneContextStickerWnd::SPRITEINFO(24, 24, 120, 41, 41, 41), CXTPDockingPaneContextStickerWnd::SPRITEINFO(24, 24, 120, 0, 41, 41), CXTPDockingPaneContextStickerWnd::SPRITEINFO(0, 0, 0, 29, 29, 32), CXTPDockingPaneContextStickerWnd::SPRITEINFO(0, 0, 29, 32, 32, 29), CXTPDockingPaneContextStickerWnd::SPRITEINFO(0, 0, 32, 0, 29, 32), CXTPDockingPaneContextStickerWnd::SPRITEINFO(0, 0, 0, 0, 32, 29), CXTPDockingPaneContextStickerWnd::SPRITEINFO(0, 0, 0, 29 + 61, 29, 32), CXTPDockingPaneContextStickerWnd::SPRITEINFO(0, 0, 29, 32 + 61, 32, 29), CXTPDockingPaneContextStickerWnd::SPRITEINFO(0, 0, 32, 0 + 61, 29, 32), CXTPDockingPaneContextStickerWnd::SPRITEINFO(0, 0, 0, 0 + 61, 32, 29), }; static CXTPDockingPaneContextStickerWnd::SPRITEINFO arrSpritesStyckerVisualStudio2008[] = { CXTPDockingPaneContextStickerWnd::SPRITEINFO(36, 0, 142, 35, 35, 35), CXTPDockingPaneContextStickerWnd::SPRITEINFO(0, 35, 142 + 35, 35, 35, 35), CXTPDockingPaneContextStickerWnd::SPRITEINFO(36, 70, 142 + 35, 0, 35, 35), CXTPDockingPaneContextStickerWnd::SPRITEINFO(72, 35, 142, 0, 35, 35), CXTPDockingPaneContextStickerWnd::SPRITEINFO(36, 0, 212, 35, 35, 35), CXTPDockingPaneContextStickerWnd::SPRITEINFO(0, 35, 212 + 35, 35, 35, 35), CXTPDockingPaneContextStickerWnd::SPRITEINFO(36, 70, 212 + 35, 0, 35, 35), CXTPDockingPaneContextStickerWnd::SPRITEINFO(72, 35, 212, 0, 35, 35), CXTPDockingPaneContextStickerWnd::SPRITEINFO(37, 38, 359, 0, 32, 31), CXTPDockingPaneContextStickerWnd::SPRITEINFO(37, 38, 359, 31, 32, 31), CXTPDockingPaneContextStickerWnd::SPRITEINFO(15, 15, 282, 0, 77, 75), // Client CXTPDockingPaneContextStickerWnd::SPRITEINFO(0, 0, 0, 35, 35, 36), CXTPDockingPaneContextStickerWnd::SPRITEINFO(0, 0, 35, 36, 36, 35), CXTPDockingPaneContextStickerWnd::SPRITEINFO(0, 0, 36, 0, 35, 36), CXTPDockingPaneContextStickerWnd::SPRITEINFO(0, 0, 0, 0, 36, 35), CXTPDockingPaneContextStickerWnd::SPRITEINFO(0, 0, 0 + 71, 35, 35, 36), CXTPDockingPaneContextStickerWnd::SPRITEINFO(0, 0, 35 + 71, 36, 36, 35), CXTPDockingPaneContextStickerWnd::SPRITEINFO(0, 0, 36 + 71, 0, 35, 36), CXTPDockingPaneContextStickerWnd::SPRITEINFO(0, 0, 0 + 71, 0, 36, 35), }; static CXTPDockingPaneContextStickerWnd::SPRITEINFO arrSpritesStyckerVisualStudio2010[] = { CXTPDockingPaneContextStickerWnd::SPRITEINFO(36, 0, 80, 40, 40, 40), CXTPDockingPaneContextStickerWnd::SPRITEINFO(0, 36, 80 + 40, 40, 40, 40), CXTPDockingPaneContextStickerWnd::SPRITEINFO(36, 72, 80 + 40, 0, 40, 40), CXTPDockingPaneContextStickerWnd::SPRITEINFO(72, 36, 80, 0, 40, 40), CXTPDockingPaneContextStickerWnd::SPRITEINFO(36, 0, 80, 40 + 80, 40, 40), CXTPDockingPaneContextStickerWnd::SPRITEINFO(0, 36, 80 + 40, 40 + 80, 40, 40), CXTPDockingPaneContextStickerWnd::SPRITEINFO(36, 72, 80 + 40, 0 + 80, 40, 40), CXTPDockingPaneContextStickerWnd::SPRITEINFO(72, 36, 80, 0 + 80, 40, 40), CXTPDockingPaneContextStickerWnd::SPRITEINFO(40, 40, 160, 120, 32, 32), CXTPDockingPaneContextStickerWnd::SPRITEINFO(40, 40, 192, 120, 32, 32), CXTPDockingPaneContextStickerWnd::SPRITEINFO(0, 0, 160, 0, 112, 112), // Client CXTPDockingPaneContextStickerWnd::SPRITEINFO(0, 0, 0, 40, 40, 40), CXTPDockingPaneContextStickerWnd::SPRITEINFO(0, 0, 40, 40, 40, 40), CXTPDockingPaneContextStickerWnd::SPRITEINFO(0, 0, 40, 0, 40, 40), CXTPDockingPaneContextStickerWnd::SPRITEINFO(0, 0, 0, 0, 40, 40), CXTPDockingPaneContextStickerWnd::SPRITEINFO(0, 0, 0, 40 + 80, 40, 40), CXTPDockingPaneContextStickerWnd::SPRITEINFO(0, 0, 40, 40 + 80, 40, 40), CXTPDockingPaneContextStickerWnd::SPRITEINFO(0, 0, 40, 0 + 80, 40, 40), CXTPDockingPaneContextStickerWnd::SPRITEINFO(0, 0, 0, 0 + 80, 40, 40), }; void CXTPDockingPaneContextStickerWnd::DrawTransparent(CDC* pDC , const CPoint& ptDest, const CSize& sz, CBitmap* pBitmap) { CImageList il; il.Create(sz.cx, sz.cy, ILC_COLOR24 | ILC_MASK, 0, 1); il.Add(pBitmap, RGB(0, 0xFF, 0)); il.Draw(pDC, 0, ptDest, ILD_NORMAL); } void CXTPDockingPaneContextStickerWnd::DrawSprite(CDC* pDC, UINT nID, SPRITEINFO* pSpriteInfo, BOOL bClientBitmap) { CBitmap bmp; { CXTPResourceManager::CManageState state; bmp.Attach(CXTPImageManagerIcon::LoadBitmapFromResource(MAKEINTRESOURCE(nID), NULL)); } CSize sz(pSpriteInfo->rcSrc.Width(), pSpriteInfo->rcSrc.Height()); CBitmap bmpSprite; bmpSprite.CreateCompatibleBitmap(pDC, sz.cx, sz.cy); if (bmpSprite.GetSafeHandle()) { CXTPCompatibleDC dcSprite(pDC, &bmpSprite); CXTPCompatibleDC dc(pDC, &bmp); dcSprite.BitBlt(0, 0, sz.cx, sz.cy, &dc, pSpriteInfo->rcSrc.left, pSpriteInfo->rcSrc.top, SRCCOPY); } CPoint ptDest = bClientBitmap ? pSpriteInfo->ptDest : CPoint(0, 0); DrawTransparent(pDC, ptDest, sz, &bmpSprite); } void CXTPDockingPaneContextStickerWnd::OnDraw(CDC* pDC) { BOOL bClient = (m_typeSticker & xtpPaneStickerClient) == xtpPaneStickerClient; XTPDockingContextStickerStyle style = m_pContext->GetStickerStyle(); if (style == xtpPaneStickerStyleVisualStudio2005Beta) { XTPCurrentSystemTheme theme = XTPColorManager()->GetCurrentSystemTheme(); UINT nIDBitmap = theme == xtpSystemThemeOlive ? XTP_IDB_DOCKINGPANE_STICKERS_OLIVE : theme == xtpSystemThemeSilver ? XTP_IDB_DOCKINGPANE_STICKERS_SILVER : XTP_IDB_DOCKINGPANE_STICKERS_BLUE; SPRITEINFO* sprites = arrSpritesStyckerWidbey; if (bClient) DrawSprite(pDC, XTP_IDB_DOCKINGPANE_STICKER_CLIENT, &sprites[SPRITE_STICKER_CLIENT]); if (m_typeSticker & xtpPaneStickerTop) DrawSprite(pDC, nIDBitmap, &sprites[m_selectedSticker == xtpPaneStickerTop ? SPRITE_STICKER_TOP_SELECTED : SPRITE_STICKER_TOP], bClient); if (m_typeSticker & xtpPaneStickerLeft) DrawSprite(pDC, nIDBitmap, &sprites[m_selectedSticker == xtpPaneStickerLeft ? SPRITE_STICKER_LEFT_SELECTED : SPRITE_STICKER_LEFT], bClient); if (m_typeSticker & xtpPaneStickerBottom) DrawSprite(pDC, nIDBitmap, &sprites[m_selectedSticker == xtpPaneStickerBottom ? SPRITE_STICKER_BOTTOM_SELECTED : SPRITE_STICKER_BOTTOM], bClient); if (m_typeSticker & xtpPaneStickerRight) DrawSprite(pDC, nIDBitmap, &sprites[m_selectedSticker == xtpPaneStickerRight ? SPRITE_STICKER_RIGHT_SELECTED : SPRITE_STICKER_RIGHT], bClient); if (m_typeSticker & xtpPaneStickerCenter) DrawSprite(pDC, nIDBitmap, &sprites[m_selectedSticker == xtpPaneStickerCenter ? SPRITE_STICKER_CENTER_SELECTED : SPRITE_STICKER_CENTER]); } else if (style == xtpPaneStickerStyleVisualStudio2008 || style == xtpPaneStickerStyleVisualStudio2010) { UINT nIDBitmap = style == xtpPaneStickerStyleVisualStudio2008 ? XTP_IDB_DOCKINGPANE_STICKERS_2008 : XTP_IDB_DOCKINGPANE_STICKERS_2010; SPRITEINFO* sprites = style == xtpPaneStickerStyleVisualStudio2008 ? arrSpritesStyckerVisualStudio2008 : arrSpritesStyckerVisualStudio2010; int nClientSprite = bClient ? 0 : 11; if (bClient) { DrawSprite(pDC, nIDBitmap, &sprites[SPRITE_STICKER_CLIENT]); if (m_typeSticker & xtpPaneStickerCenter) DrawSprite(pDC, nIDBitmap, &sprites[m_selectedSticker == xtpPaneStickerCenter ? SPRITE_STICKER_CENTER_SELECTED : SPRITE_STICKER_CENTER]); } if (m_typeSticker & xtpPaneStickerTop) DrawSprite(pDC, nIDBitmap, &sprites[nClientSprite + (m_selectedSticker == xtpPaneStickerTop ? SPRITE_STICKER_TOP_SELECTED : SPRITE_STICKER_TOP)], bClient); if (m_typeSticker & xtpPaneStickerLeft) DrawSprite(pDC, nIDBitmap, &sprites[nClientSprite + (m_selectedSticker == xtpPaneStickerLeft ? SPRITE_STICKER_LEFT_SELECTED : SPRITE_STICKER_LEFT)], bClient); if (m_typeSticker & xtpPaneStickerBottom) DrawSprite(pDC, nIDBitmap, &sprites[nClientSprite + (m_selectedSticker == xtpPaneStickerBottom ? SPRITE_STICKER_BOTTOM_SELECTED : SPRITE_STICKER_BOTTOM)], bClient); if (m_typeSticker & xtpPaneStickerRight) DrawSprite(pDC, nIDBitmap, &sprites[nClientSprite + (m_selectedSticker == xtpPaneStickerRight ? SPRITE_STICKER_RIGHT_SELECTED : SPRITE_STICKER_RIGHT)], bClient); } else { SPRITEINFO* sprites = arrSpritesStyckerVisualStudio2005; int nClientSprite = bClient ? 0 : 11; if (bClient) DrawSprite(pDC, XTP_IDB_DOCKINGPANE_STICKERS_2005, &sprites[m_selectedSticker == xtpPaneStickerCenter ? SPRITE_STICKER_CENTER_SELECTED : SPRITE_STICKER_CLIENT]); if (m_typeSticker & xtpPaneStickerTop) DrawSprite(pDC, XTP_IDB_DOCKINGPANE_STICKERS_2005, &sprites[nClientSprite + (m_selectedSticker == xtpPaneStickerTop ? SPRITE_STICKER_TOP_SELECTED : SPRITE_STICKER_TOP)], bClient); if (m_typeSticker & xtpPaneStickerLeft) DrawSprite(pDC, XTP_IDB_DOCKINGPANE_STICKERS_2005, &sprites[nClientSprite + (m_selectedSticker == xtpPaneStickerLeft ? SPRITE_STICKER_LEFT_SELECTED : SPRITE_STICKER_LEFT)], bClient); if (m_typeSticker & xtpPaneStickerBottom) DrawSprite(pDC, XTP_IDB_DOCKINGPANE_STICKERS_2005, &sprites[nClientSprite + (m_selectedSticker == xtpPaneStickerBottom ? SPRITE_STICKER_BOTTOM_SELECTED : SPRITE_STICKER_BOTTOM)], bClient); if (m_typeSticker & xtpPaneStickerRight) DrawSprite(pDC, XTP_IDB_DOCKINGPANE_STICKERS_2005, &sprites[nClientSprite + (m_selectedSticker == xtpPaneStickerRight ? SPRITE_STICKER_RIGHT_SELECTED : SPRITE_STICKER_RIGHT)], bClient); if (m_typeSticker & xtpPaneStickerCenter) DrawSprite(pDC, XTP_IDB_DOCKINGPANE_STICKERS_2005, &sprites[SPRITE_STICKER_CENTER]); } } void CXTPDockingPaneContextStickerWnd::OnPaint() { CPaintDC dcPaint(this); // device context for painting CXTPBufferDC dc(dcPaint, CXTPClientRect(this)); OnDraw(&dc); } XTPDockingPaneStickerType CXTPDockingPaneContextStickerWnd::HitTest(CPoint pt) { CXTPClientRect rc(this); ScreenToClient(&pt); if (!rc.PtInRect(pt)) return xtpPaneStickerNone; CClientDC dcClient(this); CBitmap bmp; bmp.CreateCompatibleBitmap(&dcClient, rc.Width(), rc.Height()); CXTPCompatibleDC dc(&dcClient, &bmp); dc.FillSolidRect(rc, 0); XTPDockingContextStickerStyle style = m_pContext->GetStickerStyle(); UINT nIDBitmap = style == xtpPaneStickerStyleVisualStudio2005 ? XTP_IDB_DOCKINGPANE_STICKERS_2005 : style == xtpPaneStickerStyleVisualStudio2008 ? XTP_IDB_DOCKINGPANE_STICKERS_2008 : style == xtpPaneStickerStyleVisualStudio2010 ? XTP_IDB_DOCKINGPANE_STICKERS_2010 : XTP_IDB_DOCKINGPANE_STICKERS_BLUE; UINT nIDBitmapClient = style == xtpPaneStickerStyleVisualStudio2005Beta ? XTP_IDB_DOCKINGPANE_STICKER_CLIENT : nIDBitmap; BOOL bClient = (m_typeSticker & xtpPaneStickerClient) == xtpPaneStickerClient; SPRITEINFO* sprites = style == xtpPaneStickerStyleVisualStudio2005Beta ? arrSpritesStyckerWidbey : style == xtpPaneStickerStyleVisualStudio2008 ? arrSpritesStyckerVisualStudio2008 : style == xtpPaneStickerStyleVisualStudio2010 ? arrSpritesStyckerVisualStudio2010 : arrSpritesStyckerVisualStudio2005; if (m_typeSticker & xtpPaneStickerTop) { DrawSprite(&dc, nIDBitmap, &sprites[SPRITE_STICKER_TOP], bClient); if (dc.GetPixel(pt) != 0) return xtpPaneStickerTop; } if (m_typeSticker & xtpPaneStickerLeft) { DrawSprite(&dc, nIDBitmap, &sprites[SPRITE_STICKER_LEFT], bClient); if (dc.GetPixel(pt) != 0) return xtpPaneStickerLeft; } if (m_typeSticker & xtpPaneStickerBottom) { DrawSprite(&dc, nIDBitmap, &sprites[SPRITE_STICKER_BOTTOM], bClient); if (dc.GetPixel(pt) != 0) return xtpPaneStickerBottom; } if (m_typeSticker & xtpPaneStickerRight) { DrawSprite(&dc, nIDBitmap, &sprites[SPRITE_STICKER_RIGHT], bClient); if (dc.GetPixel(pt) != 0) return xtpPaneStickerRight; } if (m_typeSticker & xtpPaneStickerCenter) { DrawSprite(&dc, nIDBitmapClient, &sprites[SPRITE_STICKER_CLIENT]); if (dc.GetPixel(pt) != 0) return xtpPaneStickerCenter; } return xtpPaneStickerNone; } ////////////////////////////////////////////////////////////////////////// // CXTPDockingPaneContext CXTPDockingPaneContext::CXTPDockingPaneContext() { m_bUseAlphaContext = FALSE; m_bUseDockingStickers = FALSE; m_bDragKeyboard = FALSE; m_pStickerPane = NULL; m_pLastStickerPane = NULL; m_pManager = NULL; m_pPane = NULL; m_pContainer = NULL; m_bAttachLast = FALSE; m_bSideDock = FALSE; m_bAttach = FALSE; m_bFloatable = TRUE; m_bDockable = TRUE; m_bDitherLast = FALSE; m_containDirection = (XTPDockingPaneDirection)-1; m_pDC = NULL; m_pfnSetLayeredWindowAttributes = NULL; HMODULE hLib = GetModuleHandle(_T("USER32")); if (hLib) { m_pfnSetLayeredWindowAttributes = (PVOID) ::GetProcAddress(hLib, "SetLayeredWindowAttributes"); } m_bResetDC = FALSE; } CXTPDockingPaneContext::~CXTPDockingPaneContext() { } void CXTPDockingPaneContext::Drag(CXTPDockingPaneBase* pPane, CPoint point) { CRect rcPane = pPane->GetPaneWindowRect(); CWnd* pSite = pPane->GetDockingSite(); if (pSite && (pPane->GetType() == xtpPaneTypeDockingPane || pPane->GetType() == xtpPaneTypeTabbedContainer) && !pSite->IsKindOf(RUNTIME_CLASS(CXTPDockingPaneMiniWnd))) { CXTPDockingPane* pActivePane = pPane->GetType() == xtpPaneTypeTabbedContainer ? ((CXTPDockingPaneTabbedContainer*)pPane)->GetSelected() : (CXTPDockingPane*)pPane; if (pActivePane) { CXTPDockingPaneTabbedContainer* pHolder = (CXTPDockingPaneTabbedContainer*)m_pManager->_GetHolder(pActivePane, TRUE); pSite = pHolder ? pHolder->GetDockingSite() : NULL; if (pSite && pSite->IsKindOf(RUNTIME_CLASS(CXTPDockingPaneMiniWnd))) { CRect rcFloating = ((CXTPDockingPaneMiniWnd*)pSite)->GetPaneWindowRect(); rcPane.right = rcPane.left + rcFloating.Width(); rcPane.bottom = rcPane.top + rcFloating.Height(); } else if (!pHolder) { rcPane.right = rcPane.left + pActivePane->m_szDocking.cx; rcPane.bottom = rcPane.top + pActivePane->m_szDocking.cy; } } } Drag(pPane, point, rcPane); } void CXTPDockingPaneContext::Drag(CXTPDockingPaneBase* pPane, CPoint pt, CRect rect) { m_bDragKeyboard = (pt == CPoint(-1, -1)); if (m_bDragKeyboard) { pt.x = rect.CenterPoint().x; pt.y = rect.top + 15; SetCursorPos(pt.x, pt.y); } m_ptSticky = m_ptLast = pt; AdjustRectangle(rect, pt); m_pPane = pPane; m_rectDragFrameScreen = m_rectDragFrame = rect; m_pDC = 0; m_pContainer = 0; m_bAttach = m_bAttachLast = FALSE; m_bFloatable = TRUE; m_bDockable = TRUE; m_bSideDock = FALSE; m_bUseAlphaContext = m_pManager->IsAlphaDockingContext() && (m_pfnSetLayeredWindowAttributes != NULL); m_bUseDockingStickers = m_pManager->IsShowDockingContextStickers() && m_bUseAlphaContext; CXTPDockingPaneBaseList lst; pPane->FindPane(xtpPaneTypeDockingPane, &lst); POSITION pos = lst.GetHeadPosition(); while (pos) { CXTPDockingPane* pListPane = (CXTPDockingPane*)lst.GetNext(pos); if (m_pManager->NotifyAction(xtpPaneActionFloating, pListPane)) m_bFloatable = FALSE; if (pListPane->GetOptions() & xtpPaneNoFloatable) m_bFloatable = FALSE; if (pListPane->GetOptions() & xtpPaneNoDockable) m_bDockable = FALSE; } if (m_pManager->m_bShowSizeCursorWhileDragging) { SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZEALL)); } InitLoop(); Track(); } void CXTPDockingPaneContext::InitLoop() { m_rectLast.SetRectEmpty(); m_sizeLast.cx = m_sizeLast.cy = 0; m_bDitherLast = FALSE; m_rectStickerPane.SetRectEmpty(); m_pStickerPane = NULL; m_pLastStickerPane = NULL; m_bResetDC = FALSE; if (!m_bUseAlphaContext) { // handle pending WM_PAINT messages MSG msg; while (::PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_NOREMOVE)) { if (!GetMessage(&msg, NULL, WM_PAINT, WM_PAINT)) return; DispatchMessage(&msg); } // lock window update while dragging ASSERT(m_pDC == NULL); CWnd* pWnd = CWnd::GetDesktopWindow(); if (pWnd->LockWindowUpdate()) m_pDC = pWnd->GetDCEx(NULL, DCX_WINDOW | DCX_CACHE | DCX_LOCKWINDOWUPDATE); else m_pDC = pWnd->GetDCEx(NULL, DCX_WINDOW | DCX_CACHE); ASSERT(m_pDC != NULL); } } void CXTPDockingPaneContext::CancelLoop() { ReleaseCapture(); if (m_bUseAlphaContext) { m_wndContext.DestroyWindow(); m_wndAttachedTab.DestroyWindow(); DestroyDockingStickers(); POSITION pos = m_rgnStickers.GetStartPosition(); while (pos) { UINT nKey; CRgn* pRgn; m_rgnStickers.GetNextAssoc(pos, nKey, pRgn); delete pRgn; } m_rgnStickers.RemoveAll(); } else { DrawFocusRect(TRUE); // gets rid of focus rect CWnd* pWnd = CWnd::GetDesktopWindow(); pWnd->UnlockWindowUpdate(); if (m_pDC != NULL) { pWnd->ReleaseDC(m_pDC); m_pDC = NULL; } } } void CXTPDockingPaneContext::_CreateRectangleRgn(CRgn& rgnResult, CRect rc) { CRgn rgnOutside, rgnInside; rgnOutside.CreateRectRgnIndirect(&rc); CRect rect = rc; rect.DeflateRect(4, 4); rect.IntersectRect(rect, rc); rgnInside.CreateRectRgnIndirect(rect); rgnResult.CreateRectRgn(0, 0, 0, 0); rgnResult.CombineRgn(&rgnOutside, &rgnInside, RGN_XOR); } void CXTPDockingPaneContext::_CreateRgn(CRgn& rgnResult, CRect rc, BOOL bTabbedRgn, BOOL bRemove) { if (bRemove) { rgnResult.CreateRectRgn(0, 0, 0, 0); return; } if (bTabbedRgn) { CSize szTab(min(50, rc.Width() - 5), min(20, rc.Height() / 2)); CRect rcIntersect, rcTop(rc.left, rc.top, rc.right, rc.bottom - szTab.cy), rcBottom(rc.left + 5, rc.bottom - szTab.cy - 4, rc.left + 5 + szTab.cx, rc.bottom); CRgn rgnTop, rgnBottom, rgnIntersect; rcIntersect.IntersectRect(rcTop, rcBottom); rcIntersect.DeflateRect(4, 0); _CreateRectangleRgn(rgnTop, rcTop); _CreateRectangleRgn(rgnBottom, rcBottom); _CreateRectangleRgn(rgnIntersect, rcIntersect); rgnResult.CreateRectRgn(0, 0, 0, 0); rgnResult.CombineRgn(&rgnBottom, &rgnTop, RGN_OR); rgnResult.CombineRgn(&rgnResult, &rgnIntersect, RGN_XOR); } else { _CreateRectangleRgn(rgnResult, rc); } } void CXTPDockingPaneContext::DrawFocusRect(BOOL bRemoveRect) { if (m_pManager->m_bShowContentsWhileDragging && m_pContainer == NULL && m_bFloatable && !m_bAttach && !m_rectDragFrame.IsRectEmpty()) { CRect rect = m_rectDragFrame; m_wndAttachedTab.DestroyWindow(); m_wndContext.DestroyWindow(); if (!m_bUseAlphaContext && !m_bResetDC) { ASSERT(m_pDC != NULL); // determine new rect and size rect.SetRectEmpty(); // first, determine the update region and select it CRgn rgnNew, rgnLast, rgnUpdate; _CreateRgn(rgnNew, rect, m_bAttach, TRUE); _CreateRgn(rgnLast, m_rectLast, m_bAttachLast); rgnUpdate.CreateRectRgn(0, 0, 0, 0); rgnUpdate.CombineRgn(&rgnLast, &rgnNew, RGN_XOR); // draw into the update/new region m_pDC->SelectClipRgn(&rgnUpdate); m_pDC->GetClipBox(&rect); CBrush* pBrushOld = m_pDC->SelectObject(CDC::GetHalftoneBrush()); m_pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATINVERT); // cleanup DC if (pBrushOld != NULL) m_pDC->SelectObject(pBrushOld); m_pDC->SelectClipRgn(NULL); CWnd* pWnd = CWnd::GetDesktopWindow(); pWnd->UnlockWindowUpdate(); if (m_pDC != NULL) { pWnd->ReleaseDC(m_pDC); m_pDC = NULL; } m_bResetDC = TRUE; } if (m_pPane->GetType() == xtpPaneTypeSplitterContainer) { if (m_rectDragFrame != m_rectLast) { m_pPane->GetDockingSite()->MoveWindow(m_rectDragFrame); } } else if (!bRemoveRect) { XTPDockingPaneAction actionNotify = xtpPaneActionFloated; CXTPDockingPaneBaseList lst; m_pPane->FindPane(xtpPaneTypeDockingPane, &lst); if (m_rectDragFrame.top < 0) m_rectDragFrame.OffsetRect(0, -m_rectDragFrame.top); CXTPDockingPaneMiniWnd* pMiniWnd = m_pManager->FloatPane(m_pPane, m_rectDragFrame); m_pManager->RecalcFrameLayout(m_pPane); SAFE_CALLPTR(pMiniWnd, RecalcLayout()); m_pPane = pMiniWnd->GetTopPane(); POSITION pos = lst.GetHeadPosition(); while (pos) { CXTPDockingPane* pPane = (CXTPDockingPane*)lst.GetNext(pos); m_pManager->NotifyAction(actionNotify, pPane); } XTPGetThread()->PumpMessage(); XTPGetThread()->OnIdle(0); } m_rectLast = rect; m_bAttachLast = FALSE; return; } if (m_bResetDC) { ASSERT(m_pDC == NULL); ASSERT(m_bUseAlphaContext == FALSE); // handle pending WM_PAINT messages MSG msg; while (::PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_NOREMOVE)) { if (!GetMessage(&msg, NULL, WM_PAINT, WM_PAINT)) return; DispatchMessage(&msg); } // lock window update while dragging CWnd* pWnd = CWnd::GetDesktopWindow(); if (pWnd->LockWindowUpdate()) m_pDC = pWnd->GetDCEx(NULL, DCX_WINDOW | DCX_CACHE | DCX_LOCKWINDOWUPDATE); else m_pDC = pWnd->GetDCEx(NULL, DCX_WINDOW | DCX_CACHE); ASSERT(m_pDC != NULL); m_bResetDC = FALSE; m_sizeLast.cx = m_sizeLast.cy = 0; m_bDitherLast = FALSE; m_rectLast.SetRectEmpty(); } if (m_bUseAlphaContext) { ASSERT(bRemoveRect == FALSE); CRect rect = (m_pContainer == 0) ? m_rectDragFrame : m_rectContainer; m_rectLast = rect; if (!m_bFloatable && m_pContainer == 0) { rect.SetRectEmpty(); } if (m_bAttach != m_bAttachLast) { m_bAttachLast = m_bAttach; if (m_bAttach) CreateContextWindow(&m_wndAttachedTab); else m_wndAttachedTab.DestroyWindow(); } if (m_bAttach) { CSize szTab(min(50, rect.Width() - 5), min(20, rect.Height() / 2)); CRect rcTab; if (m_pManager->GetPaintManager()->GetTabPaintManager()->GetPosition() == xtpTabPositionTop && m_pContainer && m_pContainer->GetType() == xtpPaneTypeTabbedContainer) { if (((CXTPDockingPaneTabbedContainer*)m_pContainer)->IsTitleVisible()) { rect.top += m_pManager->GetPaintManager()->GetCaptionHeight() + 3; } rect.top += szTab.cy; rcTab = CRect(rect.left + 5, rect.top - szTab.cy, rect.left + 5 + szTab.cx, rect.top); } else { rect.bottom -= szTab.cy; rcTab = CRect(rect.left + 5, rect.bottom, rect.left + 5 + szTab.cx, rect.bottom + szTab.cy); } m_wndAttachedTab.SetWindowPos(0, rcTab.left, rcTab.top, rcTab.Width(), rcTab.Height(), SWP_NOZORDER | SWP_NOACTIVATE | SWP_SHOWWINDOW); } if (m_wndContext.GetSafeHwnd() == 0 || CXTPWindowRect(&m_wndContext).Size() != rect.Size()) { m_wndContext.DestroyWindow(); CreateContextWindow(&m_wndContext); } m_wndContext.SetWindowPos(0, rect.left, rect.top, rect.Width(), rect.Height(), SWP_NOZORDER | SWP_NOACTIVATE | SWP_SHOWWINDOW); } else { ASSERT(m_pDC != NULL); // determine new rect and size CRect rect = (m_pContainer == 0) ? m_rectDragFrame : m_rectContainer; if (!m_bFloatable && m_pContainer == 0) rect.SetRectEmpty(); // first, determine the update region and select it CRgn rgnNew, rgnLast, rgnUpdate; _CreateRgn(rgnNew, rect, m_bAttach, bRemoveRect); _CreateRgn(rgnLast, m_rectLast, m_bAttachLast); rgnUpdate.CreateRectRgn(0, 0, 0, 0); rgnUpdate.CombineRgn(&rgnLast, &rgnNew, RGN_XOR); m_rectLast = rect; m_bAttachLast = m_bAttach; // draw into the update/new region m_pDC->SelectClipRgn(&rgnUpdate); m_pDC->GetClipBox(&rect); CBrush* pBrushOld = m_pDC->SelectObject(CDC::GetHalftoneBrush()); m_pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATINVERT); // cleanup DC if (pBrushOld != NULL) m_pDC->SelectObject(pBrushOld); m_pDC->SelectClipRgn(NULL); } } BOOL CXTPDockingPaneContext::CanSideDock(CXTPDockingPaneBase* pPane, CRect rcFrame) { CRect rc = pPane->GetPaneWindowRect(); rc.DeflateRect(m_pManager->GetSideDockingMargin()); int dSize = 10; if (rc.Height() == 0 || rc.Width() == 0 || rcFrame.Height() == 0 || rcFrame.Width() == 0) return FALSE; if (!CRect().IntersectRect(rc, rcFrame)) return FALSE; m_rectContainer.SetRectEmpty(); if (abs(rcFrame.top - rc.top) < dSize) { m_containDirection = xtpPaneDockTop; m_rectContainer = CRect(rcFrame.left, rc.top, rcFrame.right, rc.top + rcFrame.Height()); dSize = abs(rcFrame.top - rc.top); } if (abs(rc.bottom - rcFrame.bottom) < dSize) { m_containDirection = xtpPaneDockBottom; m_rectContainer = CRect(rcFrame.left, rc.bottom - rcFrame.Height(), rcFrame.right, rc.bottom); dSize = abs(rc.bottom - rcFrame.bottom); } if (abs(rcFrame.left - rc.left) < dSize) { m_containDirection = xtpPaneDockLeft; m_rectContainer = CRect(rc.left, rcFrame.top, rc.left + rcFrame.Width(), rcFrame.bottom); dSize = abs(rcFrame.left - rc.left); } if (abs(rc.right - rcFrame.right) < dSize) { m_containDirection = xtpPaneDockRight; m_rectContainer = CRect(rc.right - rcFrame.Width(), rcFrame.top, rc.right, rcFrame.bottom); } if (!m_rectContainer.IsRectEmpty()) { if (!IsAllowDockingTo(pPane, m_containDirection)) return FALSE; m_pContainer = pPane; return TRUE; } return FALSE; } BOOL CXTPDockingPaneContext::CanDock(CRect rc, CPoint pt, CXTPDockingPaneBase* pPane, BOOL bInside) { double dSize = 20.0; double dRatio = 1.0; if (bInside && !m_bFloatable) { if (rc.Width() > 1 && rc.Height() > 1) dRatio = (double)rc.Height() / (double)rc.Width(); dSize = 32000.0; } if (rc.Height() == 0 || rc.Width() == 0) return FALSE; if (bInside && !rc.PtInRect(pt)) return FALSE; if (!bInside && !CRect(rc.left - 20, rc.top - 20, rc.right + 20, rc.bottom + 20).PtInRect(pt)) return FALSE; int nInside = bInside ? 1 : -1; BOOL bFound = FALSE; if ((double)abs(pt.y - rc.top) < dSize && nInside * (pt.y - rc.top) >= 0) { m_containDirection = xtpPaneDockTop; dSize = (double)abs(pt.y - rc.top); bFound = TRUE; } if ((double)abs(rc.bottom - pt.y) < dSize && nInside * (rc.bottom - pt.y) >= 0) { m_containDirection = xtpPaneDockBottom; dSize = (double)abs(rc.bottom - pt.y); bFound = TRUE; } if ((double)abs(pt.x - rc.left) * dRatio < dSize && nInside * (pt.x - rc.left) >= 0) { m_containDirection = xtpPaneDockLeft; dSize = (double)abs(pt.x - rc.left) * dRatio; bFound = TRUE; } if ((double)abs(rc.right - pt.x) * dRatio < dSize && nInside * (rc.right- pt.x) >= 0) { m_containDirection = xtpPaneDockRight; bFound = TRUE; } if (bFound) { if (!IsAllowDockingTo(pPane, m_containDirection)) return FALSE; m_rectContainer = m_pManager->_CalculateResultDockingRect(m_pPane, m_containDirection, pPane); m_pContainer = pPane; } return bFound; } BOOL CXTPDockingPaneContext::IsAllowDockingTo(CXTPDockingPaneBase* pPane, XTPDockingPaneDirection direction) { CXTPDockingPaneBaseList lst; m_pPane->FindPane(xtpPaneTypeDockingPane, &lst); POSITION pos = lst.GetHeadPosition(); while (pos) { CXTPDockingPane* p = (CXTPDockingPane*)lst.GetNext(pos); if (m_pManager->NotifyAction(xtpPaneActionDocking, p, pPane, direction)) { return FALSE; } } return TRUE; } BOOL CXTPDockingPaneContext::IsAllowAttachTo(CXTPDockingPaneBase* pPane) { CXTPDockingPaneBaseList lst; m_pPane->FindPane(xtpPaneTypeDockingPane, &lst); POSITION pos = lst.GetHeadPosition(); while (pos) { CXTPDockingPane* p = (CXTPDockingPane*)lst.GetNext(pos); if (m_pManager->NotifyAction(xtpPaneActionAttaching, p, pPane)) { return FALSE; } } return TRUE; } BOOL CXTPDockingPaneContext::IsBehind(CXTPDockingPaneBase* pPaneBase, CXTPDockingPaneBase* pPaneTest) { CWnd* pFrameBase = pPaneBase->GetDockingSite(); if (!pFrameBase || !pFrameBase->IsKindOf(RUNTIME_CLASS(CXTPDockingPaneMiniWnd))) return TRUE; CWnd* pFrameTest = pPaneTest->GetDockingSite(); if (!pFrameTest || !pFrameTest->IsKindOf(RUNTIME_CLASS(CXTPDockingPaneMiniWnd))) return FALSE; HWND hWndNext = ::GetWindow(pFrameBase->GetSafeHwnd(), GW_HWNDNEXT); while (hWndNext) { if (hWndNext == pFrameTest->GetSafeHwnd()) return FALSE; hWndNext = ::GetWindow(hWndNext, GW_HWNDNEXT); } return TRUE; } void CXTPDockingPaneContext::FindContainer(CPoint pt) { CXTPDockingPaneInfoList* pList = &m_pManager->GetPaneList(); CXTPDockingPaneBase* pFloatingPane = NULL; POSITION pos = pList->GetHeadPosition(); while (pos) { CXTPDockingPane* pNextPane = pList->GetNext(pos); CXTPDockingPaneBase* pPane = pNextPane->GetContainer(); if (pPane == NULL) continue; ASSERT(pPane->GetType() == xtpPaneTypeTabbedContainer); if (pPane->GetContainer() == 0 || pPane->GetContainer()->GetType() != xtpPaneTypeSplitterContainer) continue; if (! (::GetWindowLong(((CXTPDockingPaneTabbedContainer*)pPane)->GetSafeHwnd(), GWL_STYLE) & WS_VISIBLE)) continue; if (m_pPane->ContainPane(pPane)) continue; CRect rcClient = pPane->GetPaneWindowRect(); if (rcClient.PtInRect(pt) && pNextPane->IsFloating()) { if (pFloatingPane == NULL || IsBehind(pFloatingPane, pPane)) { pFloatingPane = pPane; } } } pos = pList->GetHeadPosition(); while (pos) { CXTPDockingPane* pNextPane = pList->GetNext(pos); if (pNextPane->GetOptions() & xtpPaneNoDockable) continue; CXTPDockingPaneBase* pPane = pNextPane->GetContainer(); if (pPane == NULL) continue; if (pFloatingPane != NULL && pFloatingPane != pPane) continue; ASSERT(pPane->GetType() == xtpPaneTypeTabbedContainer); if (pPane->GetContainer() == 0 || (pPane->GetContainer()->GetType() != xtpPaneTypeSplitterContainer && pPane->GetContainer()->GetType() != xtpPaneTypeSidePanel)) continue; if (! (::GetWindowLong(((CXTPDockingPaneTabbedContainer*)pPane)->GetSafeHwnd(), GWL_STYLE) & WS_VISIBLE)) continue; CRect rcClient = m_rectContainer = pPane->GetPaneWindowRect(); if (m_pPane->ContainPane(pPane)) continue; if (((CXTPDockingPaneTabbedContainer*)pPane)->CanAttach(rcClient, pt)) { if (IsAllowAttachTo(pPane)) { m_pContainer = pPane; m_bAttach = TRUE; m_pStickerPane = 0; m_rectStickerPane.SetRectEmpty(); return; } else { rcClient = m_rectContainer; } } if (pPane->GetContainer()->GetType() == xtpPaneTypeSidePanel) continue; if (m_bUseDockingStickers) { if (rcClient.PtInRect(pt)) { if (m_pStickerPane == NULL || IsBehind(m_pStickerPane, pPane)) { m_rectStickerPane = m_rectContainer; m_pStickerPane = pPane; } } } else { if (CanDock(rcClient, pt, pPane)) return; } } if (pFloatingPane && m_bUseDockingStickers && m_pStickerPane == NULL && m_rectStickerPane.IsRectEmpty()) { CXTPDockingPaneBase* pPane = m_pManager->GetTopPane(); if (pPane->GetPaneWindowRect().PtInRect(pt)) { m_rectStickerPane = pPane->GetPaneWindowRect(); } } if (pFloatingPane) return; if (m_pManager->IsSideDockingEnabled()) { if (CanSideDock(m_pManager->GetClientPane(), m_rectDragFrame)) { m_bSideDock = TRUE; return; } } if (m_bUseDockingStickers) { if (m_pStickerPane) { return; } if (m_rectStickerPane.IsRectEmpty()) { CXTPDockingPaneBase* pPane = m_pManager->GetClientPane(); if (pPane->GetPaneWindowRect().PtInRect(pt)) { m_rectStickerPane = pPane->GetPaneWindowRect(); m_pStickerPane = pPane; return; } pPane = m_pManager->GetTopPane(); if (pPane->GetPaneWindowRect().PtInRect(pt)) { m_rectStickerPane = pPane->GetPaneWindowRect(); } } } else { CXTPDockingPaneBase* pPane; pPane = m_pManager->GetClientPane(); m_rectContainer = pPane->GetPaneWindowRect(); if (CanDock(pPane->GetPaneWindowRect(), pt, pPane)) return; pPane = m_pManager->GetTopPane(); m_rectContainer = pPane->GetPaneWindowRect(); if (CanDock(pPane->GetPaneWindowRect(), pt, pPane, FALSE)) return; } } void CXTPDockingPaneContext::EnsureVisible(CRect& rectDragFrame) { CRect rcWork = XTPMultiMonitor()->GetWorkArea(rectDragFrame); int nGap = 10; if (rcWork.bottom - rectDragFrame.top < nGap) { rectDragFrame.OffsetRect(0, rcWork.bottom - rectDragFrame.top - nGap); } if (rectDragFrame.bottom - rcWork.top < nGap) { rectDragFrame.OffsetRect(0, rcWork.top - rectDragFrame.bottom + nGap); } if (rcWork.right - rectDragFrame.left < nGap) { rectDragFrame.OffsetRect(rcWork.right - rectDragFrame.left - nGap, 0); } if (rectDragFrame.right - rcWork.left < nGap) { rectDragFrame.OffsetRect(rcWork.left - rectDragFrame.right + nGap, 0); } } void CXTPDockingPaneContext::UpdateStickyFrame(CRect& rectDragFrame, CWnd* pHost) { int nGap = m_pManager->m_nStickyGap; CXTPWindowRect rcWork(pHost); if (rectDragFrame.bottom < rcWork.top - nGap || rectDragFrame.top > rcWork.bottom + nGap) return; if (rectDragFrame.right < rcWork.left - nGap || rectDragFrame.left > rcWork.right + nGap) return; if (abs(rcWork.bottom - rectDragFrame.top) < nGap) { rectDragFrame.OffsetRect(0, rcWork.bottom - rectDragFrame.top); } if (abs(rectDragFrame.bottom - rcWork.top) < nGap) { rectDragFrame.OffsetRect(0, rcWork.top - rectDragFrame.bottom); } if (abs(rcWork.left - rectDragFrame.right) < nGap) { rectDragFrame.OffsetRect(rcWork.left - rectDragFrame.right, 0); } if (abs(rectDragFrame.left - rcWork.right) < nGap) { rectDragFrame.OffsetRect(rcWork.right - rectDragFrame.left, 0); } if (abs(rectDragFrame.left - rcWork.left) < nGap) { rectDragFrame.OffsetRect(rcWork.left - rectDragFrame.left, 0); } if (abs(rectDragFrame.right - rcWork.right) < nGap) { rectDragFrame.OffsetRect(rcWork.right - rectDragFrame.right, 0); } if (abs(rectDragFrame.bottom - rcWork.bottom) < nGap) { rectDragFrame.OffsetRect(0, rcWork.bottom - rectDragFrame.bottom); } if (abs(rectDragFrame.top - rcWork.top) < nGap) { rectDragFrame.OffsetRect(0, rcWork.top - rectDragFrame.top); } } void CXTPDockingPaneContext::UpdateStickyFrame(CRect& rectDragFrame) { CRect rcWork = XTPMultiMonitor()->GetWorkArea(rectDragFrame); int nGap = m_pManager->m_nStickyGap; if (abs(rcWork.top - rectDragFrame.top) < nGap) { rectDragFrame.OffsetRect(0, rcWork.top - rectDragFrame.top); } if (abs(rectDragFrame.bottom - rcWork.bottom) < nGap) { rectDragFrame.OffsetRect(0, rcWork.bottom - rectDragFrame.bottom); } if (abs(rcWork.right - rectDragFrame.right) < nGap) { rectDragFrame.OffsetRect(rcWork.right - rectDragFrame.right, 0); } if (abs(rectDragFrame.left - rcWork.left) < nGap) { rectDragFrame.OffsetRect(rcWork.left - rectDragFrame.left, 0); } if ((m_pManager->GetSite()->GetStyle() & (WS_MAXIMIZE | WS_MINIMIZE)) == 0) UpdateStickyFrame(rectDragFrame, m_pManager->GetSite()); CXTPDockingPaneBaseList* pList = &m_pManager->GetPaneStack(); POSITION pos = pList->GetHeadPosition(); while (pos) { CXTPDockingPaneBase* pNextPane = pList->GetNext(pos); if (pNextPane->GetType() != xtpPaneTypeMiniWnd) continue; CXTPDockingPaneMiniWnd* pWnd = (CXTPDockingPaneMiniWnd*)pNextPane; if (pWnd->GetSafeHwnd() && pWnd->IsWindowVisible() && m_pPane->GetDockingSite() != pWnd) { UpdateStickyFrame(rectDragFrame, pWnd); } } } void CXTPDockingPaneContext::UpdateSizingStickyFrame(UINT nSide, CRect& rectDragFrame, CWnd* pHost) { int nGap = m_pManager->m_nStickyGap; CXTPWindowRect rcWork(pHost); if (rectDragFrame.bottom < rcWork.top - nGap || rectDragFrame.top > rcWork.bottom + nGap) return; if (rectDragFrame.right < rcWork.left - nGap || rectDragFrame.left > rcWork.right + nGap) return; if (abs(rectDragFrame.top - rcWork.bottom) < nGap && (nSide == WMSZ_TOP || nSide == WMSZ_TOPLEFT || nSide == WMSZ_TOPRIGHT)) { rectDragFrame.top = rcWork.bottom; } if (abs(rectDragFrame.bottom - rcWork.top) < nGap && (nSide == WMSZ_BOTTOM || nSide == WMSZ_BOTTOMLEFT || nSide == WMSZ_BOTTOMRIGHT)) { rectDragFrame.bottom = rcWork.top; } if (abs(rectDragFrame.left - rcWork.left) < nGap && (nSide == WMSZ_LEFT || nSide == WMSZ_TOPLEFT || nSide == WMSZ_BOTTOMLEFT)) { rectDragFrame.left = rcWork.left; } if (abs(rectDragFrame.left - rcWork.right) < nGap && (nSide == WMSZ_LEFT || nSide == WMSZ_TOPLEFT || nSide == WMSZ_BOTTOMLEFT)) { rectDragFrame.left = rcWork.right; } if (abs(rectDragFrame.right - rcWork.left) < nGap && (nSide == WMSZ_RIGHT || nSide == WMSZ_TOPRIGHT|| nSide == WMSZ_BOTTOMRIGHT)) { rectDragFrame.right = rcWork.left; } if (abs(rectDragFrame.right - rcWork.right) < nGap && (nSide == WMSZ_RIGHT || nSide == WMSZ_TOPRIGHT|| nSide == WMSZ_BOTTOMRIGHT)) { rectDragFrame.right = rcWork.right; } } void CXTPDockingPaneContext::OnSizingFloatingFrame(CXTPDockingPaneMiniWnd* pMiniWnd, UINT nSide, LPRECT lpRect) { if (!m_pManager->IsStickyFloatingFrames()) return; CRect rectDragFrame(lpRect); if ((m_pManager->GetSite()->GetStyle() & (WS_MAXIMIZE | WS_MINIMIZE)) == 0) UpdateSizingStickyFrame(nSide, rectDragFrame, m_pManager->GetSite()); CXTPDockingPaneBaseList* pList = &m_pManager->GetPaneStack(); POSITION pos = pList->GetHeadPosition(); while (pos) { CXTPDockingPaneBase* pNextPane = pList->GetNext(pos); if (pNextPane->GetType() != xtpPaneTypeMiniWnd) continue; CXTPDockingPaneMiniWnd* pWnd = (CXTPDockingPaneMiniWnd*)pNextPane; if (pWnd->GetSafeHwnd() && pWnd->IsWindowVisible() && pMiniWnd != pWnd) { UpdateSizingStickyFrame(nSide, rectDragFrame, pWnd); } } *lpRect = rectDragFrame; } void CXTPDockingPaneContext::Move(CPoint pt) { CPoint ptOffset = pt - m_ptLast; m_rectDragFrameScreen.OffsetRect(ptOffset); if (CRect().IntersectRect(m_rectDragFrameScreen, XTPMultiMonitor()->GetWorkArea(m_rectDragFrame))) { m_rectDragFrame = m_rectDragFrameScreen; } EnsureVisible(m_rectDragFrame); if (!m_rectDragFrame.IsRectEmpty() && m_pManager->m_bStickyFloatingFrames) { UpdateStickyFrame(m_rectDragFrame); } m_pContainer = 0; m_bAttach = FALSE; m_rectStickerPane.SetRectEmpty(); m_pStickerPane = NULL; m_bSideDock = FALSE; if (GetKeyState(VK_CONTROL) >= 0 && m_bDockable) { FindContainer(pt); } m_ptLast = pt; if (m_bUseDockingStickers) { UpdateDockingStickers(); BOOL bFound = FALSE; POSITION pos = m_lstStickers.GetTailPosition(); while (pos) { CXTPDockingPaneContextStickerWnd* pSticker = m_lstStickers.GetPrev(pos); XTPDockingPaneStickerType selectedSticker = xtpPaneStickerNone; if (!bFound) { XTPDockingPaneStickerType ht = pSticker->HitTest(pt); if (ht != xtpPaneStickerNone) { if ((pSticker->m_typeSticker & xtpPaneStickerClient) == xtpPaneStickerClient) { m_pContainer = m_pStickerPane; m_rectContainer = m_rectStickerPane; } else { m_pContainer = m_pManager->GetTopPane(); m_rectContainer = m_pContainer->GetPaneWindowRect(); } switch (ht) { case xtpPaneStickerTop: m_rectContainer.bottom = m_rectContainer.CenterPoint().y; m_containDirection = xtpPaneDockTop; break; case xtpPaneStickerBottom: m_rectContainer.top = m_rectContainer.CenterPoint().y; m_containDirection = xtpPaneDockBottom; break; case xtpPaneStickerLeft: m_rectContainer.right = m_rectContainer.CenterPoint().x; m_containDirection = xtpPaneDockLeft; break; case xtpPaneStickerRight: m_rectContainer.left = m_rectContainer.CenterPoint().x; m_containDirection = xtpPaneDockRight; break; case xtpPaneStickerCenter: m_bAttach = TRUE; break; } BOOL bAllow = TRUE; if ((ht != xtpPaneStickerCenter) && !IsAllowDockingTo(m_pContainer, m_containDirection)) { m_pContainer = NULL; bAllow = FALSE; } if ((ht == xtpPaneStickerCenter) && !IsAllowAttachTo(m_pContainer)) { m_pContainer = NULL; m_bAttach = FALSE; bAllow = FALSE; } if (bAllow) { if (ht != xtpPaneStickerCenter) m_rectContainer = m_pManager->_CalculateResultDockingRect(m_pPane, m_containDirection, m_pContainer); selectedSticker = ht; } bFound = TRUE; } } if (pSticker->m_selectedSticker != selectedSticker) { pSticker->m_selectedSticker = selectedSticker; pSticker->Invalidate(FALSE); } } } DrawFocusRect(); } void CXTPDockingPaneContext::Track() { // don't handle if capture already set if (::GetCapture() != NULL) return; HWND hwndCapture = m_pManager->GetSite()->GetSafeHwnd(); ASSERT(hwndCapture); if (!hwndCapture) return; // set capture to the window which received this message ::SetCapture(hwndCapture); ASSERT(hwndCapture == ::GetCapture()); BOOL bAccept = FALSE; // get messages until capture lost or cancelled/accepted while (::GetCapture() == hwndCapture) { MSG msg; // handle pending WM_PAINT messages while (::PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_REMOVE | PM_NOYIELD)) { DispatchMessage(&msg); } if (!::GetMessage(&msg, NULL, 0, 0)) { AfxPostQuitMessage((int)msg.wParam); break; } if (msg.message == WM_LBUTTONUP) { bAccept = TRUE; break; } else if (msg.message == WM_MOUSEMOVE) { CSize sz = m_ptSticky - CPoint(msg.pt); if (abs(sz.cx) > 4 || abs(sz.cy) > 4) { Move(msg.pt); m_ptSticky = CPoint(0, 0); } } else if (msg.message == WM_KEYDOWN || msg.message == WM_KEYUP) { if (m_bDragKeyboard && msg.message == WM_KEYDOWN) { if (msg.wParam == VK_RETURN) { bAccept = TRUE; break; } if (msg.wParam >= VK_LEFT && msg.wParam <= VK_DOWN) { CPoint pt(m_ptLast); if (msg.wParam == VK_LEFT) pt.x -= 10; else if (msg.wParam == VK_RIGHT) pt.x += 10; else if (msg.wParam == VK_UP) pt.y -= 10; else if (msg.wParam == VK_DOWN) pt.y += 10; AdjustCursor(pt); SetCursorPos(pt.x, pt.y); Move(pt); m_ptSticky = CPoint(0, 0); } } if (msg.wParam == VK_CONTROL) { Move(m_ptLast); m_ptSticky = CPoint(0, 0); } if (msg.wParam == VK_ESCAPE) { break; } } else DispatchMessage(&msg); } CancelLoop(); if (bAccept && m_ptSticky == CPoint(0, 0)) { XTPDockingPaneAction actionNotify = xtpPaneActionFloated; CXTPDockingPaneBaseList lst; m_pPane->FindPane(xtpPaneTypeDockingPane, &lst); if (m_bAttach) { ASSERT(m_pContainer->GetType() == xtpPaneTypeTabbedContainer); m_pManager->AttachPane(m_pPane, m_pContainer); actionNotify = xtpPaneActionAttached; } else if (m_bSideDock && m_pContainer && m_pContainer == m_pManager->GetClientPane()) { CRect rectSide(m_rectContainer); rectSide.OffsetRect(-m_pContainer->GetPaneWindowRect().TopLeft()); if (m_pPane->GetContainer() && m_pPane->GetContainer()->GetType() == xtpPaneTypeSidePanel) ((CXTPDockingPaneSidePanel*)m_pPane->GetContainer())->MovePanel(m_containDirection, rectSide); else m_pManager->DockSidePane(m_pPane, m_containDirection, rectSide); actionNotify = xtpPaneActionDocked; } else if (m_pContainer) { m_pManager->DockPane(m_pPane, m_pManager->GetRTLDirection(m_containDirection), m_pContainer); m_pManager->EnsureVisible(m_pContainer); actionNotify = xtpPaneActionDocked; } else if (m_bFloatable) { CRect rcWork = XTPMultiMonitor()->GetWorkArea(m_rectDragFrame); if (m_rectDragFrame.top < rcWork.top) m_rectDragFrame.OffsetRect(0, rcWork.top - m_rectDragFrame.top); if (m_pPane->GetType() == xtpPaneTypeSplitterContainer) m_pPane->GetDockingSite()->MoveWindow(m_rectDragFrame); else m_pManager->FloatPane(m_pPane, m_rectDragFrame); } else { bAccept = FALSE; } if (bAccept) { POSITION pos = lst.GetHeadPosition(); while (pos) { CXTPDockingPane* pPane = (CXTPDockingPane*)lst.GetNext(pos); m_pManager->NotifyAction(actionNotify, pPane, m_pContainer, m_containDirection); } } } } void CXTPDockingPaneContext::DestroyDockingStickers() { while (!m_lstStickers.IsEmpty()) { CWnd* pWnd = m_lstStickers.RemoveHead(); pWnd->DestroyWindow(); delete pWnd; } } void CXTPDockingPaneContext::IncludeRgnPart(CRgn* pRgn, int x1, int y, int x2) { if (x1 < x2) { CRgn rgnExclude; rgnExclude.CreateRectRgn(x1, y, x2, y + 1); pRgn->CombineRgn(pRgn, &rgnExclude, RGN_OR); } } void CXTPDockingPaneContext::RegionFromBitmap(CRgn* pRgn, CDC* pDC, CRect rc) { CSize sz = rc.Size(); pRgn->CreateRectRgn(0, 0, 0, 0); for (int y = 0; y < sz.cy; y++) { int nStart = 0, x = 0; BOOL bTransparent = TRUE; while (x < sz.cx) { BOOL bTransparentPixel = pDC->GetPixel(x, y) == 0; if (bTransparent && !bTransparentPixel) { nStart = x; bTransparent = FALSE; } else if (!bTransparent && bTransparentPixel) { IncludeRgnPart(pRgn, nStart, y, x); bTransparent = TRUE; } x++; } if (!bTransparent) { IncludeRgnPart(pRgn, nStart, y, x); } } } CXTPDockingPaneContextStickerWnd* CXTPDockingPaneContext::CreateNewSticker(CRect rc, XTPDockingPaneStickerType typeSticker) { if (typeSticker == xtpPaneStickerNone || typeSticker == xtpPaneStickerClient) return NULL; CXTPDockingPaneContextStickerWnd* pWnd = new CXTPDockingPaneContextStickerWnd(this); m_lstStickers.AddTail(pWnd); pWnd->CreateEx(WS_EX_TOOLWINDOW, AfxRegisterWndClass(NULL, AfxGetApp()->LoadStandardCursor(IDC_ARROW)), 0, WS_POPUP, CRect(0, 0, 0, 0), m_pManager->GetSite(), 0); pWnd->m_typeSticker = typeSticker; CRgn* pRgn = NULL; if (!m_rgnStickers.Lookup(typeSticker, pRgn)) { pRgn = new CRgn; m_rgnStickers.SetAt(typeSticker, pRgn); } ASSERT(pRgn != NULL); if (!pRgn) return NULL; if (!pRgn->GetSafeHandle()) { CClientDC dcClient(pWnd); CBitmap bmp; bmp.CreateCompatibleBitmap(&dcClient, rc.Width(), rc.Height()); if (bmp.GetSafeHandle()) { CXTPCompatibleDC dc(&dcClient, &bmp); dc.FillSolidRect(rc, RGB(0, 0, 0)); pWnd->OnDraw(&dc); RegionFromBitmap(pRgn, &dc, rc); } } HRGN hRgn = ::CreateRectRgn(0, 0, 0, 0); ::CombineRgn(hRgn, (HRGN)pRgn->GetSafeHandle(), NULL, RGN_COPY); pWnd->SetWindowRgn(hRgn, FALSE); pWnd->SetWindowPos(0, rc.left, rc.top, rc.Width(), rc.Height(), SWP_NOZORDER | SWP_NOACTIVATE | SWP_SHOWWINDOW); return pWnd; } CSize CXTPDockingPaneContext::GetStickerSize(XTPDockingPaneStickerType type) const { int cx, cy, sz; if (GetStickerStyle() == xtpPaneStickerStyleVisualStudio2005) { cx = 32; cy = 29; sz = 89; } else if (GetStickerStyle() == xtpPaneStickerStyleVisualStudio2008) { cx = 36; cy = 35; sz = 109; } else if (GetStickerStyle() == xtpPaneStickerStyleVisualStudio2010) { cx = 40; cy = 40; sz = 112; } else { cx = 30; cy = 43; sz = 93; } if (type == xtpPaneStickerTop) return CSize(cy, cx); if (type == xtpPaneStickerLeft) return CSize(cx, cy); if (type == xtpPaneStickerBottom) return CSize(cy, cx); if (type == xtpPaneStickerRight) return CSize(cx, cy); return CSize(sz, sz); } XTPDockingContextStickerStyle CXTPDockingPaneContext::GetStickerStyle() const { return m_pManager->GetDockingContextStickerStyle(); } void CXTPDockingPaneContext::UpdateDockingStickers() { if (m_rectStickerPane.IsRectEmpty()) { m_pLastStickerPane = NULL; DestroyDockingStickers(); return; } CSize sz(GetStickerSize(xtpPaneStickerClient)); CRect rc(m_rectStickerPane.CenterPoint(), sz); rc.OffsetRect(- sz.cx / 2, - sz.cy / 2); if (m_pLastStickerPane != m_pStickerPane || m_lstStickers.IsEmpty()) { DestroyDockingStickers(); if (m_pStickerPane) { UINT allowStickers = xtpPaneStickerNone; if (IsAllowDockingTo(m_pStickerPane, xtpPaneDockLeft)) allowStickers = allowStickers + xtpPaneStickerLeft; if (IsAllowDockingTo(m_pStickerPane, xtpPaneDockRight)) allowStickers = allowStickers + xtpPaneStickerRight; if (IsAllowDockingTo(m_pStickerPane, xtpPaneDockBottom)) allowStickers = allowStickers + xtpPaneStickerBottom; if (IsAllowDockingTo(m_pStickerPane, xtpPaneDockTop)) allowStickers = allowStickers + xtpPaneStickerTop; CreateNewSticker(rc, m_pStickerPane == m_pManager->GetClientPane() || !IsAllowAttachTo(m_pStickerPane) ? XTPDockingPaneStickerType(xtpPaneStickerClient + allowStickers) : XTPDockingPaneStickerType(xtpPaneStickerClient + allowStickers + xtpPaneStickerCenter)); } CXTPDockingPaneBase* pTopPane = m_pManager->GetTopPane(); CRect rcWindow = pTopPane->GetPaneWindowRect(); if (IsAllowDockingTo(pTopPane, xtpPaneDockTop)) CreateNewSticker(CRect(CPoint(rcWindow.CenterPoint().x - GetStickerSize(xtpPaneStickerTop).cx / 2, rcWindow.top + 16), GetStickerSize(xtpPaneStickerTop)), xtpPaneStickerTop); if (IsAllowDockingTo(pTopPane, xtpPaneDockLeft)) CreateNewSticker(CRect(CPoint(rcWindow.left + 16, rcWindow.CenterPoint().y - GetStickerSize(xtpPaneStickerLeft).cy/ 2), GetStickerSize(xtpPaneStickerLeft)), xtpPaneStickerLeft); if (IsAllowDockingTo(pTopPane, xtpPaneDockBottom)) CreateNewSticker(CRect(CPoint(rcWindow.CenterPoint().x - GetStickerSize(xtpPaneStickerBottom).cx / 2, rcWindow.bottom - 16 - GetStickerSize(xtpPaneStickerBottom).cy), GetStickerSize(xtpPaneStickerBottom)), xtpPaneStickerBottom); if (IsAllowDockingTo(pTopPane, xtpPaneDockRight)) CreateNewSticker(CRect(CPoint(rcWindow.right - GetStickerSize(xtpPaneStickerRight).cx - 16, rcWindow.CenterPoint().y - GetStickerSize(xtpPaneStickerRight).cy/ 2), GetStickerSize(xtpPaneStickerRight)), xtpPaneStickerRight); m_pLastStickerPane = m_pStickerPane; } ASSERT(m_lstStickers.GetCount() < 6); } void CXTPDockingPaneContext::CreateContextWindow(CXTPDockingPaneContextAlphaWnd* pWnd) { ASSERT(m_bUseAlphaContext); if (pWnd->GetSafeHwnd()) return; pWnd->CreateEx(WS_EX_LAYERED | WS_EX_TOPMOST | WS_EX_TOOLWINDOW, AfxRegisterWndClass(NULL, AfxGetApp()->LoadStandardCursor(IDC_ARROW)), 0, WS_POPUP, CRect(0, 0, 0, 0), m_pManager->GetSite(), 0); if (m_pfnSetLayeredWindowAttributes) { ((PFNSETLAYEREDWINDOWATTRIBUTES)m_pfnSetLayeredWindowAttributes) (pWnd->m_hWnd, 0, 100, LWA_ALPHA); } }