XTSplitterWnd.cpp
上传用户:szled88
上传日期:2015-04-09
资源大小:43957k
文件大小:33k
- // SplitterWndXT.cpp : implementation file
- //
- // This file is a part of the XTREME CONTROLS MFC class library.
- // (c)1998-2008 Codejock Software, All Rights Reserved.
- //
- // THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
- // RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
- // CONSENT OF CODEJOCK SOFTWARE.
- //
- // THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
- // IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
- // YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
- // SINGLE COMPUTER.
- //
- // CONTACT INFORMATION:
- // support@codejock.com
- // http://www.codejock.com
- //
- /////////////////////////////////////////////////////////////////////////////
- #include "stdafx.h"
- #include "Common/XTPColorManager.h"
- #include "Common/XTPSystemHelpers.h"
- #include "XTGlobal.h"
- #include "XTSplitterWnd.h"
- #include "XTSplitterWndTheme.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- /////////////////////////////////////////////////////////////////////////////
- // Visual attributes and other constants
- // HitTest return values (values and spacing between values is important)
- enum HitTestValue
- {
- noHit = 0,
- vSplitterBox = 1,
- hSplitterBox = 2,
- bothSplitterBox = 3, // just for keyboard
- vSplitterBar1 = 101,
- vSplitterBar15 = 115,
- hSplitterBar1 = 201,
- hSplitterBar15 = 215,
- splitterIntersection1 = 301,
- splitterIntersection225 = 525
- };
- /////////////////////////////////////////////////////////////////////////////
- // CXTSplitterWnd
- IMPLEMENT_THEME_HOST(CXTSplitterWnd)
- IMPLEMENT_THEME_REFRESH(CXTSplitterWnd, CSplitterWnd)
- CXTSplitterWnd::CXTSplitterWnd()
- : CXTThemeManagerStyleHost(GetThemeFactoryClass())
- {
- m_nHiddenCol = -1;
- m_nHiddenRow = -1;
- m_point = CPoint(-1, -1);
- m_dwxStyle = XT_SPLIT_NOFULLDRAG;
- m_bFlatSplit = TRUE;
- m_cxSplitter = 6;
- m_cySplitter = 6;
- m_cxSplitterGap = 6;
- m_cySplitterGap = 6;
- // Get system settings for full drag.
- ::SystemParametersInfo(SPI_GETDRAGFULLWINDOWS,
- 0, &m_bFullDrag, 0);
- m_bForceFullDrag = FALSE;
- m_bClipStyles = FALSE;
- }
- CXTSplitterWnd::~CXTSplitterWnd()
- {
- }
- IMPLEMENT_DYNAMIC(CXTSplitterWnd, CSplitterWnd)
- BEGIN_MESSAGE_MAP(CXTSplitterWnd, CSplitterWnd)
- //{{AFX_MSG_MAP(CXTSplitterWnd)
- ON_WM_SETTINGCHANGE()
- ON_MESSAGE(WM_PRINTCLIENT, OnPrintClient)
- ON_WM_MOUSEMOVE()
- ON_WM_NCHITTEST_EX()
- ON_WM_LBUTTONUP()
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
- /////////////////////////////////////////////////////////////////////////////
- // CXTSplitterWnd message handlers
- LRESULT CXTSplitterWnd::OnPrintClient(WPARAM wParam, LPARAM /*lParam*/)
- {
- CDC* pDC = CDC::FromHandle((HDC)wParam);
- if (pDC)
- {
- CRect rectClient;
- GetClientRect(&rectClient);
- rectClient.InflateRect(-m_cxBorder, -m_cyBorder);
- CRect rectInside;
- GetInsideRect(rectInside);
- // draw the splitter boxes
- if (m_bHasVScroll && m_nRows < m_nMaxRows)
- {
- OnDrawSplitter(pDC, splitBox,
- CRect(rectInside.right, rectClient.top,
- rectClient.right, rectClient.top + m_cySplitter));
- }
- if (m_bHasHScroll && m_nCols < m_nMaxCols)
- {
- OnDrawSplitter(pDC, splitBox,
- CRect(rectClient.left, rectInside.bottom,
- rectClient.left + m_cxSplitter, rectClient.bottom));
- }
- // extend split bars to window border (past margins)
- DrawAllSplitBars(pDC, rectInside.right, rectInside.bottom);
- }
- return TRUE;
- }
- void CXTSplitterWnd::ShowColumn()
- {
- ASSERT_VALID(this);
- if (m_nCols == m_nMaxCols && m_nHiddenCol == -1)
- {
- return;
- }
- ASSERT(m_nHiddenCol != -1);
- int nShowCol = m_nHiddenCol;
- m_nHiddenCol = -1;
- int cxNew = m_pColInfo[m_nCols].nCurSize;
- m_nCols++; // add a column
- ASSERT(m_nCols == m_nMaxCols);
- int nCol;
- // Show the hidden column
- int nRow;
- for (nRow = 0; nRow < m_nRows; ++nRow)
- {
- int nShowRow = m_nHiddenRow != -1 && m_nHiddenRow <= nRow ? nRow + 1 : nRow;
- CWnd* pPaneShow = GetDlgItem(AFX_IDW_PANE_FIRST + nShowRow * 16 + m_nCols);
- ASSERT(pPaneShow != NULL);
- if (!pPaneShow)
- return;
- pPaneShow->ShowWindow(SW_SHOWNA);
- for (nCol = m_nCols - 2; nCol >= nShowCol; --nCol)
- {
- CWnd* pPane = GetPane(nRow, nCol);
- ASSERT(pPane != NULL);
- if (!pPane)
- return;
- pPane->SetDlgCtrlID(IdFromRowCol(nRow, nCol + 1));
- }
- pPaneShow->SetDlgCtrlID(IdFromRowCol(nRow, nShowCol));
- }
- if (m_nHiddenRow != -1)
- {
- CWnd* pPaneHide = GetDlgItem(AFX_IDW_PANE_FIRST + m_nHiddenRow * 16 + m_nCols);
- if (pPaneHide)
- {
- pPaneHide->SetDlgCtrlID(AFX_IDW_PANE_FIRST + m_nMaxRows * 16 + nShowCol);
- }
- }
- // new panes have been created -- recalculate layout
- for (nCol = nShowCol + 1; nCol < m_nCols; nCol++)
- m_pColInfo[nCol].nIdealSize = m_pColInfo[nCol - 1].nCurSize;
- m_pColInfo[nShowCol].nIdealSize = cxNew;
- RecalcLayout();
- }
- void CXTSplitterWnd::HideColumn(int nColHide)
- {
- ASSERT_VALID(this);
- if (m_nHiddenCol != -1)
- {
- // return if the requested one is hidden
- if (m_nHiddenCol == nColHide)
- {
- return;
- }
- ShowColumn();
- }
- ASSERT(m_nCols > 1);
- ASSERT(nColHide < m_nCols);
- ASSERT(m_nHiddenCol == -1);
- m_nHiddenCol = nColHide;
- // if the column has an active window -- change it
- int nActiveRow, nActiveCol;
- if (GetActivePane(&nActiveRow, &nActiveCol) != NULL)
- {
- if (nActiveCol == nColHide)
- {
- if (++nActiveCol >= m_nCols)
- nActiveCol = 0;
- SetActivePane(nActiveRow, nActiveCol);
- }
- }
- // hide all column panes
- int nRow;
- for (nRow = 0; nRow < m_nRows; nRow++)
- {
- CWnd* pPaneHide = GetPane(nRow, nColHide);
- ASSERT(pPaneHide != NULL);
- if (!pPaneHide)
- return;
- pPaneHide->ShowWindow(SW_HIDE);
- int nRowHide = m_nHiddenRow != -1 && m_nHiddenRow <= nRow ? nRow + 1 : nRow;
- pPaneHide->SetDlgCtrlID(AFX_IDW_PANE_FIRST + nRowHide * 16 + m_nCols);
- int nCol;
- for (nCol = nColHide + 1; nCol < m_nCols; nCol++)
- {
- CWnd* pPane = GetPane(nRow, nCol);
- ASSERT(pPane != NULL);
- if (!pPane)
- return;
- pPane->SetDlgCtrlID(IdFromRowCol(nRow, nCol - 1));
- }
- }
- m_nCols--;
- m_pColInfo[m_nCols].nCurSize = m_pColInfo[nColHide].nCurSize;
- RecalcLayout();
- }
- void CXTSplitterWnd::ShowRow()
- {
- ASSERT_VALID(this);
- if (m_nRows == m_nMaxRows && m_nHiddenRow == -1)
- {
- return;
- }
- ASSERT(m_nHiddenRow != -1);
- int nShowRow = m_nHiddenRow;
- m_nHiddenRow = -1;
- int cyNew = m_pRowInfo[m_nRows].nCurSize;
- m_nRows++; // add a nRow
- ASSERT(m_nRows == m_nMaxRows);
- int nRow;
- // Show the hidden nRow
- int nCol;
- for (nCol = 0; nCol < m_nCols; ++nCol)
- {
- int nShowCol = m_nHiddenCol != -1 && m_nHiddenCol <= nCol ? nCol + 1 : nCol;
- CWnd* pPaneShow = GetDlgItem(AFX_IDW_PANE_FIRST + m_nRows * 16 + nShowCol);
- ASSERT(pPaneShow != NULL);
- if (!pPaneShow)
- return;
- pPaneShow->ShowWindow(SW_SHOWNA);
- for (nRow = m_nRows - 2; nRow >= nShowRow; --nRow)
- {
- CWnd* pPane = GetPane(nRow, nCol);
- ASSERT(pPane != NULL);
- if (!pPane)
- return;
- pPane->SetDlgCtrlID(IdFromRowCol(nRow + 1, nCol));
- }
- pPaneShow->SetDlgCtrlID(IdFromRowCol(nShowRow, nCol));
- }
- if (m_nHiddenCol != -1)
- {
- CWnd* pPaneHide = GetDlgItem(AFX_IDW_PANE_FIRST + m_nRows * 16 + m_nHiddenCol);
- if (pPaneHide)
- {
- pPaneHide->SetDlgCtrlID(AFX_IDW_PANE_FIRST + nShowRow * 16 + m_nMaxCols);
- }
- }
- // new panes have been created -- recalculate layout
- for (nRow = nShowRow + 1; nRow < m_nRows; nRow++)
- m_pRowInfo[nRow].nIdealSize = m_pRowInfo[nRow - 1].nCurSize;
- m_pRowInfo[nShowRow].nIdealSize = cyNew;
- RecalcLayout();
- }
- void CXTSplitterWnd::HideRow(int nRowHide)
- {
- ASSERT_VALID(this);
- if (m_nHiddenRow != -1)
- {
- // return if the requested one is hidden
- if (m_nHiddenRow == nRowHide)
- {
- return;
- }
- ShowRow();
- }
- ASSERT(m_nRows > 1);
- ASSERT(nRowHide < m_nRows);
- ASSERT(m_nHiddenRow == -1);
- m_nHiddenRow = nRowHide;
- int nActiveRow, nActiveCol;
- // if the nRow has an active window -- change it
- if (GetActivePane(&nActiveRow, &nActiveCol) != NULL)
- {
- if (nActiveRow == nRowHide)
- {
- if (++nActiveRow >= m_nRows)
- nActiveRow = 0;
- SetActivePane(nActiveRow, nActiveCol);
- }
- }
- // hide all nRow panes.
- int nCol;
- for (nCol = 0; nCol < m_nCols; ++nCol)
- {
- CWnd* pPaneHide = GetPane(nRowHide, nCol);
- ASSERT(pPaneHide != NULL);
- if (!pPaneHide)
- return;
- pPaneHide->ShowWindow(SW_HIDE);
- int nColHide = m_nHiddenCol != -1 && m_nHiddenCol <= nCol ? nCol + 1 : nCol;
- pPaneHide->SetDlgCtrlID(AFX_IDW_PANE_FIRST + m_nRows * 16 + nColHide);
- int nRow;
- for (nRow = nRowHide + 1; nRow < m_nRows; ++nRow)
- {
- CWnd* pPane = GetPane(nRow, nCol);
- ASSERT(pPane != NULL);
- if (!pPane)
- return;
- pPane->SetDlgCtrlID(IdFromRowCol(nRow-1, nCol));
- }
- }
- m_nRows--;
- m_pRowInfo[m_nRows].nCurSize = m_pRowInfo[nRowHide].nCurSize;
- RecalcLayout();
- }
- BOOL CXTSplitterWnd::SwitchView(int nRow, int nCol, CView* pNewView)
- {
- CView *pOldView = DYNAMIC_DOWNCAST(CView, GetPane(nRow, nCol));
- ASSERT_KINDOF(CView, pOldView);
- if (pOldView == pNewView)
- return FALSE;
- int nOldID = pOldView->GetDlgCtrlID();
- int nNewID = pNewView->GetDlgCtrlID();
- // hide the views.
- pOldView->ShowWindow(SW_HIDE);
- pNewView->ShowWindow(SW_HIDE);
- // swap ids.
- pOldView->SetDlgCtrlID(nNewID);
- pNewView->SetDlgCtrlID(nOldID);
- // show the views.
- pOldView->ShowWindow(SW_SHOW);
- pNewView->ShowWindow(SW_SHOW);
- RecalcLayout();
- return TRUE;
- }
- CView* CXTSplitterWnd::ReplaceView(int nRow, int nCol, CView* pNewView)
- {
- CView* pOldView = DYNAMIC_DOWNCAST(CView, GetPane (nRow, nCol));
- ASSERT_KINDOF (CView, pOldView);
- if (pOldView == pNewView)
- return NULL;
- int nCtrlID = pOldView->GetDlgCtrlID();
- // swap ids.
- pOldView->SetDlgCtrlID(0);
- pNewView->SetDlgCtrlID(nCtrlID);
- // show the views.
- pOldView->ShowWindow(SW_HIDE);
- pNewView->ShowWindow(SW_SHOW);
- RecalcLayout();
- return pOldView;
- }
- CView* CXTSplitterWnd::ReplaceView(int nRow, int nCol, CRuntimeClass* pViewClass)
- {
- CView* pOldView = DYNAMIC_DOWNCAST(CView, GetPane (nRow, nCol));
- ASSERT_KINDOF (CView, pOldView);
- if (pOldView->IsKindOf(pViewClass))
- return NULL;
- // Get pointer to CDocument object so that it can be used in the creation
- // process of the new view
- CDocument* pDocument = pOldView->GetDocument();
- int nCtrlID = pOldView->GetDlgCtrlID();
- int nWidth, nHeight, nMinWidth, nMinHeight;
- GetRowInfo(nRow, nWidth, nMinWidth);
- GetColumnInfo(nCol, nHeight, nMinHeight);
- // Create new view
- CCreateContext contextT;
- contextT.m_pLastView = NULL;
- contextT.m_pCurrentDoc = pDocument;
- contextT.m_pNewViewClass = pViewClass;
- contextT.m_pNewDocTemplate = pDocument ? pDocument->GetDocTemplate() : NULL;
- contextT.m_pCurrentFrame = NULL;
- CWnd* pWnd = NULL;
- TRY
- {
- pWnd = (CWnd*)pViewClass->CreateObject();
- if (pWnd == NULL)
- AfxThrowMemoryException();
- }
- CATCH_ALL(e)
- {
- TRACE0("Out of memory creating a view.n");
- // Note: DELETE_EXCEPTION(e) not required
- return NULL;
- }
- END_CATCH_ALL
- ASSERT_KINDOF(CWnd, pWnd);
- ASSERT(pWnd->m_hWnd == NULL); // not yet created.
- // Create with the right size (wrong position)
- if (!pWnd->Create(NULL, NULL, WS_CHILD | WS_VISIBLE,
- CRect(0, 0, 0, 0), this, nCtrlID, &contextT))
- {
- TRACE0("Warning: couldn't create new view.n");
- // pWnd will be cleaned up by PostNcDestroy
- return NULL;
- }
- // Hide the old view.
- pOldView->ShowWindow(SW_HIDE);
- pOldView->SetDlgCtrlID(0);
- SetRowInfo (nRow, nWidth, nMinWidth);
- SetColumnInfo (nCol, nHeight, nMinHeight);
- RecalcLayout ();
- CView* pNewView = DYNAMIC_DOWNCAST (CView, GetPane (nRow, nCol));
- ASSERT_KINDOF (CView, pNewView);
- pNewView->OnInitialUpdate();
- return pOldView;
- }
- void CXTSplitterWnd::SetSplitCursor(int ht)
- {
- if (ht == vSplitterBox || ht >= vSplitterBar1 && ht <= vSplitterBar15)
- {
- SetCursor(XTAuxData().hcurVSplitBar);
- }
- else if (ht == hSplitterBox || ht >= hSplitterBar1 && ht <= hSplitterBar15)
- {
- SetCursor(XTAuxData().hcurHSplitBar);
- }
- else
- {
- CSplitterWnd::SetSplitCursor(ht);
- }
- }
- void CXTSplitterWnd::OnSettingChange(UINT uFlags, LPCTSTR lpszSection)
- {
- CSplitterWnd::OnSettingChange(uFlags, lpszSection);
- if (!m_bForceFullDrag)
- {
- // Get system settings for full drag.
- ::SystemParametersInfo(SPI_GETDRAGFULLWINDOWS,
- 0, &m_bFullDrag, 0);
- // Force no display of windows contents while dragging,
- // regardless of windows setting.
- if (m_dwxStyle & XT_SPLIT_NOFULLDRAG)
- {
- m_bFullDrag = FALSE;
- }
- }
- }
- void CXTSplitterWnd::SetFullDrag(BOOL bFullDrag)
- {
- m_bFullDrag = bFullDrag;
- m_bForceFullDrag = TRUE;
- }
- void CXTSplitterWnd::DrawTracker(const CRect& rect, CBrush* pBrush)
- {
- if (m_bFullDrag == FALSE)
- {
- ASSERT_VALID(this);
- ASSERT(!rect.IsRectEmpty());
- ASSERT((GetStyle() & WS_CLIPCHILDREN) == 0);
- CWindowDC dc(this);
- int nSavedDC = dc.SaveDC();
- if (m_dwxStyle & XT_SPLIT_DOTTRACKER)
- {
- CRect rc;
- GetInsideRect(rc);
- if (rect.Width() < rect.Height())
- {
- rc.right = rect.right;
- }
- else
- {
- rc.bottom = rect.top;
- }
- dc.DrawFocusRect(rc);
- }
- else
- {
- CRect rcTracker(&rect);
- BOOL bVert = rcTracker.Height() > rcTracker.Width();
- if (bVert)
- {
- if (rcTracker.Width() != 4)
- {
- rcTracker.left = rcTracker.right - 4;
- }
- }
- else
- {
- if (rcTracker.Height() != 4)
- {
- rcTracker.bottom = rcTracker.top + 4;
- }
- }
- dc.SelectObject(pBrush);
- dc.PatBlt(rcTracker.left, rcTracker.top, rcTracker.Width(), rcTracker.Height(), PATINVERT);
- }
- dc.RestoreDC(nSavedDC);
- }
- }
- void CXTSplitterWnd::OnInvertTracker(const CRect& rect)
- {
- CBrush* pBrush = NULL;
- if (m_bFlatSplit)
- {
- pBrush = CBrush::FromHandle((HBRUSH)::GetStockObject(WHITE_BRUSH));
- }
- else
- {
- pBrush = CDC::GetHalftoneBrush();
- }
- DrawTracker(rect, pBrush);
- }
- void CXTSplitterWnd::OnMouseMove(UINT nFlags, CPoint point)
- {
- if (m_bFullDrag == FALSE)
- {
- CSplitterWnd::OnMouseMove(nFlags, point);
- return;
- }
- if (GetCapture() != this)
- {
- StopTracking(FALSE);
- }
- if (m_bTracking)
- {
- // move tracker to current cursor position
- point.Offset(m_ptTrackOffset); // point is the upper right of hit detect
- // limit the point to the valid split range
- if (point.y < m_rectLimit.top)
- {
- point.y = m_rectLimit.top;
- }
- else if (point.y > m_rectLimit.bottom)
- {
- point.y = m_rectLimit.bottom;
- }
- if (point.x < m_rectLimit.left)
- {
- point.x = m_rectLimit.left;
- }
- else if (point.x > m_rectLimit.right)
- {
- point.x = m_rectLimit.right;
- }
- if (m_htTrack == vSplitterBox || m_htTrack >= vSplitterBar1 && m_htTrack <= vSplitterBar15)
- {
- if (m_rectTracker.top != point.y)
- {
- OnInvertTracker(m_rectTracker);
- m_rectTracker.OffsetRect(0, point.y - m_rectTracker.top);
- OnInvertTracker(m_rectTracker);
- }
- }
- else if (m_htTrack == hSplitterBox || m_htTrack >= hSplitterBar1 && m_htTrack <= hSplitterBar15)
- {
- if (m_rectTracker.left != point.x)
- {
- OnInvertTracker(m_rectTracker);
- m_rectTracker.OffsetRect(point.x - m_rectTracker.left, 0);
- OnInvertTracker(m_rectTracker);
- }
- }
- else if (m_htTrack == bothSplitterBox || (m_htTrack >= splitterIntersection1 && m_htTrack <= splitterIntersection225))
- {
- if (m_rectTracker.top != point.y)
- {
- OnInvertTracker(m_rectTracker);
- m_rectTracker.OffsetRect(0, point.y - m_rectTracker.top);
- OnInvertTracker(m_rectTracker);
- }
- if (m_rectTracker2.left != point.x)
- {
- OnInvertTracker(m_rectTracker2);
- m_rectTracker2.OffsetRect(point.x - m_rectTracker2.left, 0);
- OnInvertTracker(m_rectTracker2);
- }
- }
- OnLButtonUp(MK_LBUTTON, point);
- OnLButtonDown(MK_LBUTTON, point);
- if (m_point != point)
- {
- RedrawWindow(NULL, NULL, RDW_ALLCHILDREN | RDW_UPDATENOW);
- m_point = point;
- }
- }
- else
- {
- // simply hit-test and set appropriate cursor
- int ht = HitTest(point);
- SetSplitCursor(ht);
- }
- }
- void CXTSplitterWnd::StartTracking(int ht)
- {
- m_bClipStyles = FALSE;
- if (!m_bFullDrag)
- {
- if (GetStyle() & WS_CLIPCHILDREN)
- {
- ModifyStyle(WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0);
- m_bClipStyles = TRUE;
- }
- CSplitterWnd::StartTracking(ht);
- return;
- }
- ASSERT_VALID(this);
- if (ht == noHit)
- {
- return;
- }
- // GetHitRect will restrict 'm_rectLimit' as appropriate
- GetInsideRect(m_rectLimit);
- if (ht >= splitterIntersection1 && ht <= splitterIntersection225)
- {
- // split two directions (two tracking rectangles)
- int row = (ht - splitterIntersection1) / 15;
- int col = (ht - splitterIntersection1) % 15;
- GetHitRect(row + vSplitterBar1, m_rectTracker);
- int yTrackOffset = m_ptTrackOffset.y;
- m_bTracking2 = TRUE;
- GetHitRect(col + hSplitterBar1, m_rectTracker2);
- m_ptTrackOffset.y = yTrackOffset;
- }
- else if (ht == bothSplitterBox)
- {
- // hit on splitter boxes (for keyboard)
- GetHitRect(vSplitterBox, m_rectTracker);
- int yTrackOffset = m_ptTrackOffset.y;
- m_bTracking2 = TRUE;
- GetHitRect(hSplitterBox, m_rectTracker2);
- m_ptTrackOffset.y = yTrackOffset;
- // center it
- m_rectTracker.OffsetRect(0, m_rectLimit.Height()/2);
- m_rectTracker2.OffsetRect(m_rectLimit.Width()/2, 0);
- }
- else
- {
- // only hit one bar
- GetHitRect(ht, m_rectTracker);
- }
- // steal focus and capture
- SetCapture();
- // set tracking state and appropriate cursor
- m_bTracking = TRUE;
- m_htTrack = ht;
- SetSplitCursor(ht);
- }
- void CXTSplitterWnd::StopTracking(BOOL bAccept)
- {
- if (!m_bFullDrag)
- {
- CSplitterWnd::StopTracking(bAccept);
- if (m_bClipStyles)
- {
- ModifyStyle(0, WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
- m_bClipStyles = FALSE;
- }
- return;
- }
- ASSERT_VALID(this);
- if (!m_bTracking)
- {
- return;
- }
- ReleaseCapture();
- // erase tracker rectangle
- OnInvertTracker(m_rectTracker);
- if (m_bTracking2)
- OnInvertTracker(m_rectTracker2);
- m_bTracking = m_bTracking2 = FALSE;
- // save old active view
- CWnd* pOldActiveView = GetActivePane();
- // m_rectTracker is set to the new splitter position (without border)
- // (so, adjust relative to where the border will be)
- m_rectTracker.OffsetRect(-CX_BORDER , -CY_BORDER);
- m_rectTracker2.OffsetRect(-CX_BORDER, -CY_BORDER);
- if (bAccept)
- {
- if (m_htTrack == vSplitterBox)
- {
- SplitRow(m_rectTracker.top);
- }
- else if (m_htTrack >= vSplitterBar1 && m_htTrack <= vSplitterBar15)
- {
- // adjust the tracking rect for flat splitter.
- if (m_bFlatSplit)
- {
- m_rectTracker.top = m_rectTracker.bottom - 4;
- }
- // set row height
- TrackRowSize(m_rectTracker.top, m_htTrack - vSplitterBar1);
- RecalcLayout();
- }
- else if (m_htTrack == hSplitterBox)
- {
- SplitColumn(m_rectTracker.left);
- }
- else if (m_htTrack >= hSplitterBar1 && m_htTrack <= hSplitterBar15)
- {
- // adjust the tracking rect for flat splitter.
- if (m_bFlatSplit)
- {
- m_rectTracker.left = m_rectTracker.right - 4;
- }
- // set column width
- TrackColumnSize(m_rectTracker.left, m_htTrack - hSplitterBar1);
- RecalcLayout();
- }
- else if (m_htTrack >= splitterIntersection1 &&
- m_htTrack <= splitterIntersection225)
- {
- // set row height and column width
- int row = (m_htTrack - splitterIntersection1) / 15;
- int col = (m_htTrack - splitterIntersection1) % 15;
- TrackRowSize(m_rectTracker.top, row);
- TrackColumnSize(m_rectTracker2.left, col);
- RecalcLayout();
- }
- else if (m_htTrack == bothSplitterBox)
- {
- // rectTracker is vSplitter (splits rows)
- // rectTracker2 is hSplitter (splits cols)
- SplitRow(m_rectTracker.top);
- SplitColumn(m_rectTracker2.left);
- }
- }
- if ((pOldActiveView == GetActivePane()) &&
- (pOldActiveView != NULL))
- {
- SetActivePane(-1, -1, pOldActiveView); // re-activate
- }
- }
- void CXTSplitterWnd::SetSplitterStyle(DWORD dwxStyle)
- {
- m_dwxStyle = dwxStyle;
- // Force no display of windows contents while dragging,
- // regardless of windows setting.
- if (m_dwxStyle & XT_SPLIT_NOFULLDRAG)
- {
- m_bFullDrag = FALSE;
- }
- else
- {
- // Get system settings for full drag.
- ::SystemParametersInfo(SPI_GETDRAGFULLWINDOWS,
- 0, &m_bFullDrag, 0);
- }
- }
- LRESULT CXTSplitterWnd::OnNcHitTest(CPoint point)
- {
- // If XT_SPLIT_NOSIZE style is defined, just return a border
- // hit so can at least activate the app if needed.
- if ((m_dwxStyle & XT_SPLIT_NOSIZE) == XT_SPLIT_NOSIZE)
- {
- return HTBORDER;
- }
- return (LRESULT)CSplitterWnd::OnNcHitTest(point);
- }
- void CXTSplitterWnd::EnableFlatLook(BOOL bFlatSplitter)
- {
- m_bFlatSplit = bFlatSplitter;
- m_cxSplitter = m_bFlatSplit ? 6 : 7;
- m_cySplitter = m_bFlatSplit ? 6 : 7;
- m_cxSplitterGap = m_bFlatSplit ? 6 : 7;
- m_cySplitterGap = m_bFlatSplit ? 6 : 7;
- RecalcLayout();
- }
- void CXTSplitterWnd::OnDrawSplitter(CDC* pDC, ESplitType nType, const CRect& rectArg)
- {
- COLORREF clr3DFace = GetTheme()->m_clrSplitterFace;
- COLORREF clr3DShadow = GetTheme()->m_clrSplitterBorders;
- // if pDC == NULL, then just invalidate
- if (pDC == NULL)
- {
- RedrawWindow(rectArg, NULL, RDW_INVALIDATE | RDW_NOCHILDREN);
- return;
- }
- ASSERT_VALID(pDC);
- // otherwise, actually draw
- CRect rect = rectArg;
- switch (nType)
- {
- case splitBorder:
- if (m_bFlatSplit)
- {
- if (!(m_dwxStyle & XT_SPLIT_NOBORDER))
- {
- pDC->Draw3dRect(rect, clr3DFace, clr3DFace);
- rect.InflateRect(-CX_BORDER, -CY_BORDER);
- pDC->Draw3dRect(rect, clr3DShadow, GetXtremeColor(COLOR_3DHILIGHT));
- }
- else
- {
- pDC->Draw3dRect(rect, clr3DFace, clr3DFace);
- rect.InflateRect(-CX_BORDER, -CY_BORDER);
- pDC->Draw3dRect(rect, clr3DFace, clr3DFace);
- }
- }
- else
- {
- pDC->Draw3dRect(rect, clr3DShadow, GetXtremeColor(COLOR_3DHILIGHT));
- rect.InflateRect(-CX_BORDER, -CY_BORDER);
- pDC->Draw3dRect(rect, GetXtremeColor(COLOR_WINDOWFRAME), clr3DFace);
- }
- return;
- case splitIntersection:
- ASSERT(!XTOSVersionInfo()->IsWin95OrGreater());
- break;
- case splitBox:
- if (m_bFlatSplit)
- {
- pDC->Draw3dRect(rect, clr3DFace, clr3DFace);
- rect.InflateRect(-CX_BORDER, -CY_BORDER);
- pDC->Draw3dRect(rect, GetXtremeColor(COLOR_3DHILIGHT), clr3DShadow);
- rect.InflateRect(-CX_BORDER, -CY_BORDER);
- }
- else
- {
- pDC->Draw3dRect(rect, clr3DFace, GetXtremeColor(COLOR_WINDOWFRAME));
- rect.InflateRect(-CX_BORDER, -CY_BORDER);
- pDC->Draw3dRect(rect, GetXtremeColor(COLOR_3DHILIGHT), clr3DShadow);
- rect.InflateRect(-CX_BORDER, -CY_BORDER);
- }
- break;
- case splitBar:
- break;
- default:
- ASSERT(FALSE); // unknown splitter type
- }
- // fill the middle
- COLORREF clr = clr3DFace;
- pDC->FillSolidRect(rect, clr);
- }
- void CXTSplitterWnd::OnLButtonUp(UINT nFlags, CPoint point)
- {
- CSplitterWnd::OnLButtonUp(nFlags, point);
- Invalidate();
- }
- void CXTSplitterWnd::SetActivePane(int row, int col, CWnd* pWnd/*= NULL*/)
- {
- // set the focus to the pane
- CWnd* pPane = pWnd == NULL ? GetPane(row, col) : pWnd;
- if (pPane->IsKindOf(RUNTIME_CLASS(CView)))
- {
- CFrameWnd* pFrameWnd = GetParentFrame();
- ASSERT_VALID(pFrameWnd);
- pFrameWnd->SetActiveView((CView*)pPane);
- }
- else
- {
- pPane->SetFocus();
- }
- }
- //////////////////////////////////////////////////////////////////////
- // CXTSplitterWndEx
- //
- IMPLEMENT_DYNAMIC(CXTSplitterWndEx, CXTSplitterWnd)
- BEGIN_MESSAGE_MAP(CXTSplitterWndEx, CXTSplitterWnd)
- //{{AFX_MSG_MAP(CXTSplitterWndEx)
- ON_WM_ERASEBKGND()
- ON_WM_PAINT()
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
- CXTSplitterWndEx::CXTSplitterWndEx()
- {
- m_cxBorder = 0;
- m_cyBorder = 0;
- m_cxSplitter = 4;
- m_cySplitter = 4;
- m_cxSplitterGap = 4;
- m_cySplitterGap = 4;
- m_cyTopBorderGap = 6;
- m_bShowTopBorder = true;
- }
- CXTSplitterWndEx::~CXTSplitterWndEx()
- {
- }
- void CXTSplitterWndEx::OnDrawSplitter(CDC* pDC, ESplitType nType, const CRect& rectArg)
- {
- COLORREF clr3DFace = GetTheme()->m_clrSplitterFace;
- COLORREF clr3DShadow = GetTheme()->m_clrSplitterBorders;
- if (pDC == NULL)
- {
- RedrawWindow(rectArg, NULL, RDW_INVALIDATE | RDW_NOCHILDREN);
- return;
- }
- ASSERT_VALID(pDC);
- CRect rect = rectArg;
- switch (nType)
- {
- case splitBorder:
- return;
- case splitBox:
- pDC->Draw3dRect(rect, clr3DFace, GetXtremeColor(COLOR_WINDOWFRAME));
- rect.InflateRect(-CX_BORDER, -CY_BORDER);
- pDC->Draw3dRect(rect, GetXtremeColor(COLOR_3DHILIGHT), clr3DShadow);
- rect.InflateRect(-CX_BORDER, -CY_BORDER);
- break;
- }
- pDC->FillSolidRect(rect, clr3DFace);
- }
- // Generic routine:
- // for X direction: pInfo = m_pColInfo, nMax = m_nMaxCols, nSize = cx
- // for Y direction: pInfo = m_pRowInfo, nMax = m_nMaxRows, nSize = cy
- void CXTSplitterWndEx::LayoutRowCol(CSplitterWnd::CRowColInfo* pInfoArray,
- int nMax, int nSize, int nSizeSplitter)
- {
- ASSERT(pInfoArray != NULL);
- ASSERT(nMax > 0);
- ASSERT(nSizeSplitter > 0);
- if (!pInfoArray)
- return;
- CSplitterWnd::CRowColInfo* pInfo = NULL;
- int i;
- if (nSize < 0)
- nSize = 0; // if really too small, layout as zero size
- // start with ideal sizes
- for (i = 0, pInfo = pInfoArray; i < nMax-1; i++, pInfo++)
- {
- if (pInfo->nIdealSize < pInfo->nMinSize)
- pInfo->nIdealSize = 0; // too small to see
- pInfo->nCurSize = pInfo->nIdealSize;
- }
- if (!pInfo)
- return;
- pInfo->nCurSize = INT_MAX; // last row/column takes the rest
- for (i = 0, pInfo = pInfoArray; i < nMax; i++, pInfo++)
- {
- ASSERT(nSize >= 0);
- if (nSize == 0)
- {
- // no more room (set pane to be invisible)
- pInfo->nCurSize = 0;
- continue; // don't worry about splitters
- }
- else if (nSize < pInfo->nMinSize && i != 0)
- {
- // additional panes below the recommended minimum size
- // aren't shown and the size goes to the previous pane
- pInfo->nCurSize = 0;
- // previous pane already has room for splitter + border
- // add remaining size and remove the extra border
- ASSERT(CX_BORDER * 2 == CY_BORDER * 2);
- (pInfo-1)->nCurSize += nSize + CX_BORDER * 2;
- nSize = 0;
- }
- else
- {
- // otherwise we can add the second pane
- ASSERT(nSize > 0);
- if (pInfo->nCurSize == 0)
- {
- // too small to see
- if (i != 0)
- pInfo->nCurSize = 0;
- }
- else if (nSize < pInfo->nCurSize)
- {
- // this row/col won't fit completely - make as small as possible
- pInfo->nCurSize = nSize;
- nSize = 0;
- }
- else
- {
- // can fit everything
- nSize -= pInfo->nCurSize;
- }
- }
- // see if we should add a splitter
- ASSERT(nSize >= 0);
- if (i != nMax - 1)
- {
- // should have a splitter
- if (nSize > nSizeSplitter)
- {
- nSize -= nSizeSplitter; // leave room for splitter + border
- ASSERT(nSize > 0);
- }
- else
- {
- // not enough room - add left over less splitter size
- ASSERT(CX_BORDER * 2 == CY_BORDER * 2);
- pInfo->nCurSize += nSize;
- if (pInfo->nCurSize > (nSizeSplitter - CX_BORDER * 2))
- pInfo->nCurSize -= (nSizeSplitter - CY_BORDER * 2);
- nSize = 0;
- }
- }
- }
- ASSERT(nSize == 0); // all space should be allocated
- }
- // repositions client area of specified window
- // assumes everything has WS_BORDER or is inset like it does
- // (includes scroll bars)
- void CXTSplitterWndEx::DeferClientPos(AFX_SIZEPARENTPARAMS* lpLayout,
- CWnd* pWnd, int x, int y, int cx, int cy, BOOL bScrollBar)
- {
- ASSERT(pWnd != NULL);
- if (!pWnd)
- return;
- ASSERT(pWnd->m_hWnd != NULL);
- if (bScrollBar)
- {
- // if there is enough room, draw scroll bar without border
- // if there is not enough room, set the WS_BORDER bit so that
- // we will at least get a proper border drawn
- BOOL bNeedBorder = (cx <= CX_BORDER || cy <= CY_BORDER);
- pWnd->ModifyStyle(bNeedBorder ? 0 : WS_BORDER,
- bNeedBorder ? WS_BORDER : 0);
- }
- CRect rect(x, y, x + cx, y + cy);
- // adjust for border size (even if zero client size)
- // adjust for 3d border (splitter windows have implied border)
- if ((pWnd->GetExStyle() & WS_EX_CLIENTEDGE) ||
- pWnd->IsKindOf(RUNTIME_CLASS(CSplitterWnd)))
- rect.InflateRect(CX_BORDER * 2, CY_BORDER * 2);
- // first check if the new rectangle is the same as the current
- CRect rectOld;
- pWnd->GetWindowRect(rectOld);
- pWnd->GetParent()->ScreenToClient(&rectOld);
- if (rect != rectOld)
- AfxRepositionWindow(lpLayout, pWnd->m_hWnd, rect);
- }
- void CXTSplitterWndEx::RecalcLayout()
- {
- ASSERT_VALID(this);
- ASSERT(m_nRows > 0 && m_nCols > 0); // must have at least one pane
- CRect rectClient;
- GetClientRect(rectClient);
- rectClient.InflateRect(-m_cxBorder, -m_cyBorder);
- rectClient.top += m_cyTopBorderGap;
- CRect rectInside;
- GetInsideRect(rectInside);
- // layout columns (restrict to possible sizes)
- LayoutRowCol(m_pColInfo, m_nCols, rectInside.Width(), m_cxSplitterGap);
- LayoutRowCol(m_pRowInfo, m_nRows, rectInside.Height(), m_cySplitterGap);
- // adjust the panes (and optionally scroll bars)
- // give the hint for the maximum number of HWNDs
- AFX_SIZEPARENTPARAMS layout;
- layout.hDWP = ::BeginDeferWindowPos((m_nCols + 1) * (m_nRows + 1) + 1);
- // size of scrollbars
- int cx = (rectClient.right - rectInside.right);
- int cy = (rectClient.bottom - rectInside.bottom);
- // reposition size box
- if (m_bHasHScroll && m_bHasVScroll)
- {
- CWnd* pScrollBar = GetDlgItem(AFX_IDW_SIZE_BOX);
- ASSERT(pScrollBar != NULL);
- // fix style if necessary
- BOOL bSizingParent = (GetSizingParent() != NULL);
- // modifyStyle returns TRUE if style changes
- if (pScrollBar->ModifyStyle(SBS_SIZEGRIP | SBS_SIZEBOX,
- bSizingParent ? SBS_SIZEGRIP : SBS_SIZEBOX))
- pScrollBar->Invalidate();
- pScrollBar->EnableWindow(bSizingParent);
- // reposition the size box
- DeferClientPos(&layout, pScrollBar,
- rectInside.right, rectInside.bottom, cx, cy, TRUE);
- }
- // reposition scroll bars
- if (m_bHasHScroll)
- {
- int cxSplitterBox = m_cxSplitter;// split box bigger
- int x = rectClient.left;
- int y = rectInside.bottom;
- int col;
- for (col = 0; col < m_nCols; col++)
- {
- CWnd* pScrollBar = GetDlgItem(AFX_IDW_HSCROLL_FIRST + col);
- ASSERT(pScrollBar != NULL);
- int cxColumn = m_pColInfo[col].nCurSize;
- if (col == 0 && m_nCols < m_nMaxCols)
- x += cxSplitterBox, cxColumn -= cxSplitterBox;
- DeferClientPos(&layout, pScrollBar, x, y, cxColumn, cy, TRUE);
- x += cxColumn + m_cxSplitterGap;
- }
- }
- if (m_bHasVScroll)
- {
- int cySplitterBox = m_cySplitter;// split box bigger
- int x = rectInside.right;
- int y = rectClient.top;
- int row;
- for (row = 0; row < m_nRows; row++)
- {
- CWnd* pScrollBar = GetDlgItem(AFX_IDW_VSCROLL_FIRST + row);
- ASSERT(pScrollBar != NULL);
- int cyColumn = m_pRowInfo[row].nCurSize;
- if (row == 0 && m_nRows < m_nMaxRows)
- y += cySplitterBox, cyColumn -= cySplitterBox;
- DeferClientPos(&layout, pScrollBar, x, y, cx, cyColumn, TRUE);
- y += cyColumn + m_cySplitterGap;
- }
- }
- //BLOCK: Reposition all the panes
- {
- int x = rectClient.left;
- int col;
- for (col = 0; col < m_nCols; col++)
- {
- int cxColumn = m_pColInfo[col].nCurSize;
- int y = rectClient.top;
- int row;
- for (row = 0; row < m_nRows; row++)
- {
- int cyColumn = m_pRowInfo[row].nCurSize;
- CWnd* pWnd = GetPane(row, col);
- DeferClientPos(&layout, pWnd, x, y, cxColumn, cyColumn, FALSE);
- y += cyColumn + m_cySplitterGap;
- }
- x += cxColumn + m_cxSplitterGap;
- }
- }
- // move and resize all the windows at once!
- if (layout.hDWP == NULL || !::EndDeferWindowPos(layout.hDWP))
- TRACE0("Warning: DeferWindowPos failed - low system resources.n");
- // invalidate all the splitter bars (with NULL pDC)
- DrawAllSplitBars(NULL, rectInside.right, rectInside.bottom);
- }
- void CXTSplitterWndEx::GetInsideRect(CRect& rect) const
- {
- CSplitterWnd::GetInsideRect(rect);
- rect.top += m_cyTopBorderGap;
- }
- void CXTSplitterWndEx::OnPaint()
- {
- CSplitterWnd::OnPaint();
- if (m_bShowTopBorder)
- {
- CClientDC dc(this);
- int iSavedDC = dc.SaveDC();
- CRect rectClient;
- GetClientRect(rectClient);
- if (GetTheme()->GetTheme() == xtThemeDefault)
- {
- CPen penShadow(PS_SOLID, 1, GetXtremeColor(COLOR_3DSHADOW));
- dc.SelectObject(&penShadow);
- dc.MoveTo(rectClient.left, rectClient.top);
- dc.LineTo(rectClient.right, rectClient.top);
- }
- CPen penHilight(PS_SOLID, 1, GetXtremeColor(COLOR_3DHILIGHT));
- dc.SelectObject(&penHilight);
- dc.MoveTo(rectClient.left, rectClient.top + 1);
- dc.LineTo(rectClient.right, rectClient.top + 1);
- dc.RestoreDC(iSavedDC);
- }
- }
- BOOL CXTSplitterWndEx::OnEraseBkgnd(CDC* pDC)
- {
- CRect rectClient;
- GetClientRect(rectClient);
- rectClient.InflateRect(-m_cxBorder, -m_cyBorder);
- rectClient.bottom = rectClient.top + m_cyTopBorderGap;
- COLORREF clr3DFace = GetTheme()->m_clrSplitterFace;
- pDC->FillSolidRect(rectClient, clr3DFace);
- return TRUE;
- }