📄 dlgsplitter.cpp
字号:
if (m_bHasHScroll)
{
int cxSplitterBox = m_cxSplitter + afxData.bNotWin4;// split box bigger
int x = rectClient.left;
int y = rectInside.bottom + afxData.bNotWin4;
for (int col = 0; col < m_nCols; col++)
{
CWnd* pScrollBar = GetDlgItem(AFX_IDW_HSCROLL_FIRST + col);
ASSERT(pScrollBar != NULL);
int cx = m_pColInfo[col].nCurSize;
if (col == 0 && m_nCols < m_nMaxCols)
x += cxSplitterBox, cx -= cxSplitterBox;
_AfxDeferClientPos(&layout, pScrollBar, x, y, cx, cy, TRUE);
x += cx + m_cxSplitterGap;
}
}
if (m_bHasVScroll)
{
int cySplitterBox = m_cySplitter + afxData.bNotWin4;// split box bigger
int x = rectInside.right + afxData.bNotWin4;
int y = rectClient.top;
for (int row = 0; row < m_nRows; row++)
{
CWnd* pScrollBar = GetDlgItem(AFX_IDW_VSCROLL_FIRST + row);
ASSERT(pScrollBar != NULL);
int cy = m_pRowInfo[row].nCurSize;
if (row == 0 && m_nRows < m_nMaxRows)
y += cySplitterBox, cy -= cySplitterBox;
_AfxDeferClientPos(&layout, pScrollBar, x, y, cx, cy, TRUE);
y += cy + m_cySplitterGap;
}
}
//BLOCK: Reposition all the panes
{
int x = rectClient.left;
for (int col = 0; col < m_nCols; col++)
{
int cx = m_pColInfo[col].nCurSize;
int y = rectClient.top;
for (int row = 0; row < m_nRows; row++)
{
int cy = m_pRowInfo[row].nCurSize;
CWnd* pWnd = GetPane(row, col);
_AfxDeferClientPos(&layout, pWnd, x, y, cx, cy, FALSE);
y += cy + m_cySplitterGap;
}
x += cx + 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 CDlgSplitterWnd::DrawAllSplitBars(CDC* pDC, int cxInside, int cyInside)
{
ASSERT_VALID(this);
// draw column split bars
CRect rect;
GetClientRect(rect);
rect.left += m_cxBorder;
for (int col = 0; col < m_nCols - 1; col++)
{
rect.left += m_pColInfo[col].nCurSize + m_cxBorderShare;
rect.right = rect.left + m_cxSplitter;
if (rect.left > cxInside)
break; // stop if not fully visible
OnDrawSplitter(pDC, splitBar, rect);
rect.left = rect.right + m_cxBorderShare;
}
// draw row split bars
GetClientRect(rect);
rect.top += m_cyBorder;
for (int row = 0; row < m_nRows - 1; row++)
{
rect.top += m_pRowInfo[row].nCurSize + m_cyBorderShare;
rect.bottom = rect.top + m_cySplitter;
if (rect.top > cyInside)
break; // stop if not fully visible
OnDrawSplitter(pDC, splitBar, rect);
rect.top = rect.bottom + m_cyBorderShare;
}
// draw pane borders
if (afxData.bWin4)
{
GetClientRect(rect);
int x = rect.left;
for (col = 0; col < m_nCols; col++)
{
int cx = m_pColInfo[col].nCurSize + 2*m_cxBorder;
if (col == m_nCols-1 && m_bHasVScroll)
cx += afxData.cxVScroll - CX_BORDER;
int y = rect.top;
for (int row = 0; row < m_nRows; row++)
{
int cy = m_pRowInfo[row].nCurSize + 2*m_cyBorder;
if (row == m_nRows-1 && m_bHasHScroll)
cy += afxData.cyHScroll - CX_BORDER;
OnDrawSplitter(pDC, splitBorder, CRect(x, y, x+cx, y+cy));
y += cy + m_cySplitterGap - 2*m_cyBorder;
}
x += cx + m_cxSplitterGap - 2*m_cxBorder;
}
}
}
void CDlgSplitterWnd::OnPaint()
{
ASSERT_VALID(this);
CPaintDC dc(this);
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(&dc, splitBox,
CRect(rectInside.right + afxData.bNotWin4, rectClient.top,
rectClient.right, rectClient.top + m_cySplitter));
}
if (m_bHasHScroll && m_nCols < m_nMaxCols)
{
OnDrawSplitter(&dc, splitBox,
CRect(rectClient.left, rectInside.bottom + afxData.bNotWin4,
rectClient.left + m_cxSplitter, rectClient.bottom));
}
// extend split bars to window border (past margins)
DrawAllSplitBars(&dc, rectInside.right, rectInside.bottom);
if (!afxData.bWin4)
{
// draw splitter intersections (inside only)
GetInsideRect(rectInside);
dc.IntersectClipRect(rectInside);
CRect rect;
rect.top = rectInside.top;
for (int row = 0; row < m_nRows - 1; row++)
{
rect.top += m_pRowInfo[row].nCurSize + m_cyBorderShare;
rect.bottom = rect.top + m_cySplitter;
rect.left = rectInside.left;
for (int col = 0; col < m_nCols - 1; col++)
{
rect.left += m_pColInfo[col].nCurSize + m_cxBorderShare;
rect.right = rect.left + m_cxSplitter;
OnDrawSplitter(&dc, splitIntersection, rect);
rect.left = rect.right + m_cxBorderShare;
}
rect.top = rect.bottom + m_cxBorderShare;
}
}
}
BOOL CDlgSplitterWnd::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
if (nHitTest == HTCLIENT && pWnd == this && !m_bTracking)
return TRUE; // we will handle it in the mouse move
return CWnd::OnSetCursor(pWnd, nHitTest, message);
}
// cache of last needed cursor
AFX_STATIC_DATA HCURSOR _afx_hcurLast = NULL;
AFX_STATIC_DATA HCURSOR _afx_hcurDestroy = NULL;
AFX_STATIC_DATA UINT _afx_idcPrimaryLast = 0; // store the primary IDC
void CDlgSplitterWnd::SetSplitCursor(int ht)
{
UINT idcPrimary; // app supplied cursor
LPCTSTR idcSecondary; // system supplied cursor (MAKEINTRESOURCE)
AfxLockGlobals(CRIT_SPLITTERWND);
if (ht == vSplitterBox ||
ht >= vSplitterBar1 && ht <= vSplitterBar15)
{
idcPrimary = AFX_IDC_VSPLITBAR;
idcSecondary = IDC_SIZENS;
}
else if (ht == hSplitterBox ||
ht >= hSplitterBar1 && ht <= hSplitterBar15)
{
idcPrimary = AFX_IDC_HSPLITBAR;
idcSecondary = IDC_SIZEWE;
}
else if (ht == bothSplitterBox ||
(ht >= splitterIntersection1 && ht <= splitterIntersection225))
{
idcPrimary = AFX_IDC_SMALLARROWS;
idcSecondary = IDC_SIZEALL;
}
else
{
SetCursor(afxData.hcurArrow);
idcPrimary = 0; // don't use it
idcSecondary = 0; // don't use it
}
if (idcPrimary != 0)
{
HCURSOR hcurToDestroy = NULL;
if (idcPrimary != _afx_idcPrimaryLast)
{
HINSTANCE hInst = AfxFindResourceHandle(
MAKEINTRESOURCE(idcPrimary), RT_GROUP_CURSOR);
// load in another cursor
hcurToDestroy = _afx_hcurDestroy;
// Note: If this LoadCursor call fails, it is likely that
// _AFX_NO_SPLITTER_RESOURCES is defined in your .RC file.
// To correct the situation, remove the following line from your
// resource script:
// #define _AFX_NO_SPLITTER_RESOURCES
// This should be done using the Resource.Set Includes... command.
if ((_afx_hcurDestroy = _afx_hcurLast =
::LoadCursor(hInst, MAKEINTRESOURCE(idcPrimary))) == NULL)
{
// will not look as good
TRACE0("Warning: Could not find splitter cursor - using system provided alternative.\n");
ASSERT(_afx_hcurDestroy == NULL); // will not get destroyed
_afx_hcurLast = ::LoadCursor(NULL, idcSecondary);
ASSERT(_afx_hcurLast != NULL);
}
_afx_idcPrimaryLast = idcPrimary;
}
ASSERT(_afx_hcurLast != NULL);
::SetCursor(_afx_hcurLast);
ASSERT(_afx_hcurLast != hcurToDestroy);
if (hcurToDestroy != NULL)
::DestroyCursor(hcurToDestroy); // destroy after being set
}
AfxUnlockGlobals(CRIT_SPLITTERWND);
}
void CDlgSplitterWnd::OnMouseMove(UINT /*nFlags*/, CPoint pt)
{
if (GetCapture() != this)
StopTracking(FALSE);
if (m_bTracking)
{
// move tracker to current cursor position
pt.Offset(m_ptTrackOffset); // pt is the upper right of hit detect
// limit the point to the valid split range
if (pt.y < m_rectLimit.top)
pt.y = m_rectLimit.top;
else if (pt.y > m_rectLimit.bottom)
pt.y = m_rectLimit.bottom;
if (pt.x < m_rectLimit.left)
pt.x = m_rectLimit.left;
else if (pt.x > m_rectLimit.right)
pt.x = m_rectLimit.right;
if (m_htTrack == vSplitterBox ||
m_htTrack >= vSplitterBar1 && m_htTrack <= vSplitterBar15)
{
if (m_rectTracker.top != pt.y)
{
OnInvertTracker(m_rectTracker);
m_rectTracker.OffsetRect(0, pt.y - m_rectTracker.top);
OnInvertTracker(m_rectTracker);
}
}
else if (m_htTrack == hSplitterBox ||
m_htTrack >= hSplitterBar1 && m_htTrack <= hSplitterBar15)
{
if (m_rectTracker.left != pt.x)
{
OnInvertTracker(m_rectTracker);
m_rectTracker.OffsetRect(pt.x - m_rectTracker.left, 0);
OnInvertTracker(m_rectTracker);
}
}
else if (m_htTrack == bothSplitterBox ||
(m_htTrack >= splitterIntersection1 &&
m_htTrack <= splitterIntersection225))
{
if (m_rectTracker.top != pt.y)
{
OnInvertTracker(m_rectTracker);
m_rectTracker.OffsetRect(0, pt.y - m_rectTracker.top);
OnInvertTracker(m_rectTracker);
}
if (m_rectTracker2.left != pt.x)
{
OnInvertTracker(m_rectTracker2);
m_rectTracker2.OffsetRect(pt.x - m_rectTracker2.left, 0);
OnInvertTracker(m_rectTracker2);
}
}
}
else
{
// simply hit-test and set appropriate cursor
int ht = HitTest(pt);
SetSplitCursor(ht);
}
}
void CDlgSplitterWnd::OnLButtonDown(UINT /*nFlags*/, CPoint pt)
{
if (m_bTracking)
return;
StartTracking(HitTest(pt));
}
void CDlgSplitterWnd::OnLButtonDblClk(UINT /*nFlags*/, CPoint pt)
{
int ht = HitTest(pt);
CRect rect;
StopTracking(FALSE);
if ((GetStyle() & SPLS_DYNAMIC_SPLIT) == 0)
return; // do nothing if layout is static
if (ht == vSplitterBox)
{
// half split
SplitRow(m_pRowInfo[0].nCurSize / 2);
}
else if (ht == hSplitterBox)
{
// half split
SplitColumn(m_pColInfo[0].nCurSize / 2);
}
else if (ht >= vSplitterBar1 && ht <= vSplitterBar15)
{
int rowDelete = ht - vSplitterBar1;
// don't delete the active row
int row;
if (GetActivePane(&row, NULL) != NULL && rowDelete == row)
++rowDelete;
DeleteRow(rowDelete);
}
else if (ht >= hSplitterBar1 && ht <= hSplitterBar15)
{
int colDelete = ht - hSplitterBar1;
// don't delete the active column
int col;
if (GetActivePane(NULL, &col) != NULL && colDelete == col)
++colDelete;
DeleteColumn(colDelete);
}
else if (ht >= splitterIntersection1 && ht <= splitterIntersection225)
{
int rowDelete = (ht - splitterIntersection1) / 15;
int colDelete = (ht - splitterIntersection1) % 15;
int row, col;
if (GetActivePane(&row, &col) != NULL)
{
// don't delete the active row or column
if (col == colDelete)
++colDelete;
if (row == rowDelete)
++rowDelete;
}
DeleteRow(rowDelete);
DeleteColumn(colDelete);
}
}
void CDlgSplitterWnd::OnLButtonUp(UINT /*nFlags*/, CPoint /*pt*/)
{
StopTracking(TRUE);
}
void CDlgSplitterWnd::OnCancelMode()
{
StopTracking(FALSE);
}
void CDlgSplitterWnd::OnKeyDown(UINT nChar, UINT /*nRepCnt*/, UINT /*nFlags*/)
{
CPoint pt;
GetCursorPos(&pt);
int cz = GetKeyState(VK_CONTROL) < 0 ? 1 : 16;
int dx = 0;
int dy = 0;
switch (nChar)
{
case VK_ESCAPE:
StopTracking(FALSE);
return;
case VK_RETURN:
StopTracking(TRUE);
return;
case VK_LEFT:
dx = -1;
break;
case VK_RIGHT:
dx = +1;
break;
case VK_UP:
dy = -1;
break;
case VK_DOWN:
dy = +1;
break;
default:
Default(); // pass other keys through
return;
}
if (m_htTrack == vSplitterBox ||
m_htTrack >= vSplitterBar1 && m_htTrack <= vSplitterBar15)
{
// no movement along X axis
dx = 0;
}
if (m_htTrack == hSplitterBox ||
m_htTrack >= hSplitterBar1 && m_htTrack <= hSplitterBar15)
{
// no movement along Y axis
dy = 0;
}
// adjust to new position
pt.x += dx * cz;
pt.y += dy * cz;
// make sure within valid limits
ScreenToClient(&pt);
if (pt.y < m_rectLimit.top)
pt.y = m_rectLimit.top;
else if (pt.y > m_rectLimit.bottom)
pt.y = m_rectLimit.bottom;
if (pt.x < m_rectLimit.left)
pt.x = m_rectLimit.left;
else if (pt.x > m_rectLimit.right)
pt.x = m_rectLimit.right;
ClientToScreen(&pt);
// cause WM_MOUSEMOVE to filter through
SetCursorPos(pt.x, pt.y);
}
void CDlgSplitterWnd::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == SC_SIZE)
{
CWnd* pParent = GetSizingParent();
if (pParent != NULL)
{
pParent->SendMessage(WM_SYSCOMMAND, (WPARAM)nID, lParam);
return;
}
}
CWnd::OnSysCommand(nID, lParam);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -