📄 treepropsheetsplitter.cpp
字号:
m_orig = new int[m_nPanes + 1];
m_pzMinSize = new int[m_nPanes];
m_frozen = new bool[m_nPanes];
::ZeroMemory(m_pane, m_nPanes * sizeof(CWnd*));
for (int i = 0; i < m_nPanes - 1; i++)
{
// Initialize sizes. Default, set equal size to all panes
m_size[i] = (FULL_SIZE + m_nPanes / 2) / m_nPanes;
total += m_size[i];
}
m_size[m_nPanes - 1] = FULL_SIZE - total;
ResetFrozenPanes();
}
///////////////////////////////////////////////////////////////////////////////
// CTreePropSheetSplitter protected
///////////////////////////////////////////////////////////////////////////////
void CTreePropSheetSplitter::RecalcLayout()
{
int i, size_sum, remain, remain_new = 0;
bool bGrow = true;
CRect rcOuter;
GetAdjustedClientRect(&rcOuter);
size_sum = m_nOrientation == SSP_HORZ ? rcOuter.Width() : rcOuter.Height();
size_sum -= (m_nPanes - 1) * m_nBarThickness;
// Frozen panes
/* Get the previous size and adjust the size of the frozen pane. We need to
do this as the size array contains ratio to FULL_SIZE. */
// If we have some frozen columns use this algorithm otherwise adjust for minimum sizes.
// If all the panes are frozen, do not use frozen pane algorithm.
bool bFrozenOnly = m_nFrozenPaneCount && m_nPanes - m_nFrozenPaneCount;
if( bFrozenOnly )
{
int prev_size_sum = m_orig[m_nPanes] - m_orig[0] - m_nBarThickness * m_nPanes;
int non_frozen_count = m_nPanes - m_nFrozenPaneCount;
int nTotalPanes = 0;
for( int i = 0; i < m_nPanes; ++i )
{
if( i + 1 == m_nPanes )
{
// Assigned all remaining value to the last pane without computation.
// This is done in order to prevent propagation of computation errors.
m_size[i] = FULL_SIZE - nTotalPanes;
}
else
{
if( m_frozen[i] )
{ // Frozen pane
m_size[i] = MulDivRound( m_size[i], prev_size_sum, size_sum);
}
else
{ // Non frozen pane
m_size[i] = MulDivRound( m_size[i], prev_size_sum, size_sum ) +
MulDivRound( size_sum - prev_size_sum, FULL_SIZE, size_sum * non_frozen_count );
}
}
// If a pane become to small, it will be adjusted with the proportional algorithm.
bFrozenOnly &= ( MulDivRound(m_size[i], size_sum, FULL_SIZE) <= m_pzMinSize[i] );
// Compute running sumof pane sizes.
nTotalPanes += m_size[i];
}
}
/* The previous section might set the flag bFrozenOnly in case a pane became too small.
In this case, we also want to execute this algorithm in order to respect the minimum
pane size constraint. */
if( !bFrozenOnly )
{
while (bGrow) // adjust sizes on the beginning
{ // and while we have growed something
bGrow = false;
remain = remain_new = FULL_SIZE;
for (i = 0; i < m_nPanes; i++) // grow small panes to minimal size
if ( MulDivRound(m_size[i], size_sum, FULL_SIZE) <= m_pzMinSize[i])
{
remain -= m_size[i];
if (MulDivRound(m_size[i], size_sum, FULL_SIZE) < m_pzMinSize[i])
{
if (m_pzMinSize[i] > size_sum)
m_size[i] = FULL_SIZE;
else
m_size[i] = MulDivRound(m_pzMinSize[i], FULL_SIZE, size_sum);
bGrow = true;
}
remain_new -= m_size[i];
}
if (remain_new <= 0) // if there isn't place to all panes
{ // set the minimal size to the leftmost/topmost
remain = FULL_SIZE; // and set zero size to the remainimg
for (i = 0; i < m_nPanes; i++)
{
if (size_sum == 0)
m_size[i] = 0;
else
m_size[i] = MulDivRound(m_pzMinSize[i], FULL_SIZE, size_sum);
if (m_size[i] > remain)
m_size[i] = remain;
remain -= m_size[i];
}
break;
}
if (remain_new != FULL_SIZE) // adjust other pane sizes, if we have growed some
for (i = 0; i < m_nPanes; i++)
if ( MulDivRound(m_size[i], size_sum, FULL_SIZE) != m_pzMinSize[i])
m_size[i] = MulDivRound(m_size[i], remain_new, remain);
}
}
// calculate positions (in pixels) from relative sizes
m_orig[0] = ( m_nOrientation == SSP_HORZ ? rcOuter.left:rcOuter.top );
for (i = 0; i < m_nPanes - 1; i++)
m_orig[i + 1] = m_orig[i] + MulDivRound(m_size[i], size_sum, FULL_SIZE) + m_nBarThickness;
m_orig[m_nPanes] = m_orig[0] + size_sum + m_nBarThickness * m_nPanes;
}
///////////////////////////////////////////////////////////////////////////////
//
void CTreePropSheetSplitter::ResizePanes()
{
int i;
CRect rcOuter;
GetAdjustedClientRect(&rcOuter);
if (m_nOrientation == SSP_HORZ)
for (i = 0; i < m_nPanes; i++)
{
if (m_pane[i])
m_pane[i]->MoveWindow(m_orig[i], rcOuter.top, m_orig[i + 1] - m_orig[i] - m_nBarThickness, rcOuter.Height(), FALSE);
}
else
for (i = 0; i < m_nPanes; i++)
{
if (m_pane[i])
m_pane[i]->MoveWindow(rcOuter.left, m_orig[i], rcOuter.Width(), m_orig[i + 1] - m_orig[i] - m_nBarThickness, FALSE);
}
UpdateParentRect( &rcOuter );
}
///////////////////////////////////////////////////////////////////////////////
//
void CTreePropSheetSplitter::InvertTracker()
{
CDC* pDC = GetDC();
CBrush* pBrush = CDC::GetHalftoneBrush();
HBRUSH hOldBrush;
CRect rcWnd;
GetAdjustedClientRect(&rcWnd);
hOldBrush = (HBRUSH)SelectObject(pDC->m_hDC, pBrush->m_hObject);
if (m_nOrientation == SSP_HORZ)
pDC->PatBlt(m_nTracker - m_nBarThickness - rcWnd.left, 0, m_nBarThickness, m_nTrackerLength, PATINVERT);
else
pDC->PatBlt(0, m_nTracker - m_nBarThickness - rcWnd.top, m_nTrackerLength, m_nBarThickness, PATINVERT);
if (hOldBrush != NULL)
SelectObject(pDC->m_hDC, hOldBrush);
ReleaseDC(pDC);
}
///////////////////////////////////////////////////////////////////////////////
//
void CTreePropSheetSplitter::GetAdjustedClientRect(CRect* pRect) const
{
GetWindowRect(pRect);
GetParent()->ScreenToClient(pRect);
}
///////////////////////////////////////////////////////////////////////////////
// CTreePropSheetSplitter messages
///////////////////////////////////////////////////////////////////////////////
void CTreePropSheetSplitter::OnPaint()
{
CPaintDC dc(this);
CRect rcClip, rcClipPane;
int i;
// retrieve the background brush
HWND hWnd = GetParent()->GetSafeHwnd();
// send a message to the dialog box
HBRUSH hBrush = (HBRUSH)::SendMessage(hWnd, WM_CTLCOLORDLG, (WPARAM)dc.m_ps.hdc, (LPARAM)hWnd);
ASSERT( hBrush );
CRect rcWnd;
GetAdjustedClientRect(&rcWnd);
dc.GetClipBox(&rcClip);
CRect rect;
int top, left;
if (m_nOrientation == SSP_HORZ)
{
for (i = 1; i < m_nPanes; i++)
{
left = m_orig[i] - m_nBarThickness - rcWnd.left;
top = rcClip.top;
rect.SetRect( left, top, left + m_nBarThickness, top + rcClip.Height() );
dc.FillRect( &rect, CBrush::FromHandle(hBrush) );
}
}
else
{
for (i = 1; i < m_nPanes; i++)
{
left = rcClip.left;
top = m_orig[i] - m_nBarThickness - rcWnd.top;
rect.SetRect( left, top, left + rcClip.Width(), top + m_nBarThickness );
dc.FillRect( &rect, CBrush::FromHandle(hBrush) );
}
}
}
///////////////////////////////////////////////////////////////////////////////
//
void CTreePropSheetSplitter::OnSize(UINT nType, int cx, int cy)
{
CWnd::OnSize(nType, cx, cy);
RecalcLayout();
ResizePanes();
}
///////////////////////////////////////////////////////////////////////////////
//
void CTreePropSheetSplitter::OnLButtonDown(UINT nFlags, CPoint point)
{
UNREFERENCED_PARAMETER(nFlags);
// Must be in AllowUserResizing mode.
if( !m_bAllowUserResizing )
return;
CRect rcClient;
int mouse_pos = m_nOrientation == SSP_HORZ ? point.x : point.y;
SetCapture();
for (m_nTrackIndex = 1; (m_nTrackIndex < m_nPanes && m_orig[m_nTrackIndex] < mouse_pos); m_nTrackIndex++);
m_nTracker = m_orig[m_nTrackIndex];
m_nTrackerMouseOffset = mouse_pos - m_nTracker;
GetWindowRect(&rcClient);
GetParent()->ScreenToClient(&rcClient);
m_nTrackerLength = m_nOrientation == SSP_HORZ ? rcClient.Height() : rcClient.Width();
InvertTracker();
}
///////////////////////////////////////////////////////////////////////////////
//
void CTreePropSheetSplitter::OnLButtonUp(UINT nFlags, CPoint point)
{
UNREFERENCED_PARAMETER(nFlags);
UNREFERENCED_PARAMETER(point);
if (GetCapture() != this)
return;
CRect rcOuter;
int size_sum;
GetAdjustedClientRect(&rcOuter);
size_sum = m_nOrientation == SSP_HORZ ? rcOuter.Width() : rcOuter.Height();
size_sum -= (m_nPanes - 1) * m_nBarThickness;
InvertTracker();
ReleaseCapture();
m_orig[m_nTrackIndex] = m_nTracker;
m_size[m_nTrackIndex - 1] = MulDivRound(m_orig[m_nTrackIndex] - m_orig[m_nTrackIndex - 1] - m_nBarThickness, FULL_SIZE, size_sum);
m_size[m_nTrackIndex] = MulDivRound(m_orig[m_nTrackIndex + 1] - m_orig[m_nTrackIndex] - m_nBarThickness, FULL_SIZE, size_sum);
ResizePanes();
}
///////////////////////////////////////////////////////////////////////////////
//
void CTreePropSheetSplitter::OnMouseMove(UINT nFlags, CPoint point)
{
UNREFERENCED_PARAMETER(nFlags);
if (GetCapture() != this)
return;
InvertTracker();
m_nTracker = (m_nOrientation == SSP_HORZ ? point.x : point.y) - m_nTrackerMouseOffset;
ASSERT( m_nTrackIndex > 0 );
if (m_nTracker > m_orig[m_nTrackIndex + 1] - m_nBarThickness - m_pzMinSize[m_nTrackIndex])
{
m_nTracker = m_orig[m_nTrackIndex + 1] - m_nBarThickness - m_pzMinSize[m_nTrackIndex];
}
else if (m_nTracker < m_orig[m_nTrackIndex - 1] + m_nBarThickness + m_pzMinSize[m_nTrackIndex-1])
{
m_nTracker = m_orig[m_nTrackIndex - 1] + m_nBarThickness + m_pzMinSize[m_nTrackIndex-1];
}
InvertTracker();
CRect rcOuter;
GetAdjustedClientRect(&rcOuter);
// Real-time update.
if( m_bRealtimeUpdate )
{
m_orig[m_nTrackIndex] = m_nTracker;
ResizePanes();
}
}
///////////////////////////////////////////////////////////////////////////////
//
BOOL CTreePropSheetSplitter::OnNcCreate(LPCREATESTRUCT lpCreateStruct)
{
if (!CWnd::OnNcCreate(lpCreateStruct))
return FALSE;
CWnd* pParent = GetParent();
ASSERT_VALID(pParent);
pParent->ModifyStyleEx(WS_EX_CLIENTEDGE, 0, SWP_DRAWFRAME);
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////
//
void CTreePropSheetSplitter::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)
{
lpwndpos->flags |= SWP_NOCOPYBITS;
CWnd::OnWindowPosChanging(lpwndpos);
}
}; // namespace TreePropSheet
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -