2025-11-27 16:46:48 +09:00

337 lines
7.8 KiB
C++

// ==========================================================================
// Class Implementation: COXSplitterWnd
// ==========================================================================
// Version: 9.3
// This software along with its related components, documentation and files ("The Libraries")
// is © 1994-2007 The Code Project (1612916 Ontario Limited) and use of The Libraries is
// governed by a software license agreement ("Agreement"). Copies of the Agreement are
// available at The Code Project (www.codeproject.com), as part of the package you downloaded
// to obtain this file, or directly from our office. For a copy of the license governing
// this software, you may contact us at legalaffairs@codeproject.com, or by calling 416-849-8900.
// //////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "OXSplitterWnd.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// COXSplitterWnd pane bar
IMPLEMENT_DYNCREATE(COXSplitterWnd, CSplitterWnd)
COXSplitterWnd::COXSplitterWnd()
{
}
COXSplitterWnd::~COXSplitterWnd()
{
}
BEGIN_MESSAGE_MAP(COXSplitterWnd, CSplitterWnd)
//{{AFX_MSG_MAP(COXSplitterWnd)
ON_WM_DESTROY()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
void COXSplitterWnd::OnDestroy()
{
CSplitterWnd::OnDestroy();
// reset variables
m_nMaxRows=0;
m_nMaxCols=0;
m_nRows=0;
m_nCols=0;
m_bHasHScroll=FALSE;
m_bHasVScroll=FALSE;
delete[] m_pColInfo;
m_pColInfo=NULL;
delete[] m_pRowInfo;
m_pRowInfo=NULL;
}
BOOL COXSplitterWnd::InsertColumn(int nInsertBefore, int nWidth)
{
ASSERT(nInsertBefore>=0 && nInsertBefore<=GetColumnCount());
ASSERT(::IsWindow(GetSafeHwnd()));
// create new array of column info
CRowColInfo* pColInfo=new CRowColInfo[m_nMaxCols+1];
int nCol=0;
for(nCol=0; nCol<m_nMaxCols+1; nCol++)
{
int nExistingCol=(nCol<nInsertBefore ? nCol : nCol-1);
if(nCol==nInsertBefore)
{
// set data for inserted column
pColInfo[nCol].nMinSize=0;
pColInfo[nCol].nIdealSize=nWidth;
pColInfo[nCol].nCurSize=-1;
}
else
{
// copy existing column data
pColInfo[nCol].nMinSize=m_pColInfo[nExistingCol].nMinSize;
pColInfo[nCol].nIdealSize=m_pColInfo[nExistingCol].nIdealSize;
pColInfo[nCol].nCurSize=m_pColInfo[nExistingCol].nCurSize;
}
}
// delete old array
delete[] m_pColInfo;
// save new one
m_pColInfo=pColInfo;
// set new number of columns
m_nMaxCols++;
m_nCols=m_nMaxCols;
// reset pane IDs (do that in backward direction)
for(nCol=m_nMaxCols-2; nCol>=nInsertBefore; nCol--)
{
for(int nRow=m_nMaxRows-1; nRow>=0; nRow--)
{
CWnd* pView=GetDlgItem(IdFromRowCol(nRow,nCol));
ASSERT(pView!=NULL);
pView->SetDlgCtrlID(IdFromRowCol(nRow,nCol+1));
}
}
return TRUE;
}
BOOL COXSplitterWnd::RemoveColumn(int nDelCol)
{
ASSERT(GetColumnCount()>1);
if(GetColumnCount()<=1)
{
return FALSE;
}
ASSERT(nDelCol>=0 && nDelCol<GetColumnCount());
ASSERT(::IsWindow(GetSafeHwnd()));
// delete all views in specified column
for(int nRow=0; nRow<m_nMaxRows; nRow++)
{
CWnd* pView=GetDlgItem(IdFromRowCol(nRow,nDelCol));
if(pView!=NULL)
{
DeleteView(nRow,nDelCol);
}
}
// create new array of column info
CRowColInfo* pColInfo=new CRowColInfo[m_nMaxCols-1];
int nCol=0;
for(nCol=0; nCol<m_nMaxCols-1; nCol++)
{
int nExistingCol=(nCol<nDelCol ? nCol : nCol+1);
if(nExistingCol!=nDelCol)
{
// copy existing column data
pColInfo[nCol].nMinSize=m_pColInfo[nExistingCol].nMinSize;
pColInfo[nCol].nIdealSize=m_pColInfo[nExistingCol].nIdealSize;
pColInfo[nCol].nCurSize=m_pColInfo[nExistingCol].nCurSize;
}
}
// delete old array
delete[] m_pColInfo;
// save new one
m_pColInfo=pColInfo;
// reset pane IDs (in forward direction)
for(nCol=nDelCol+1; nCol<m_nMaxCols; nCol++)
{
for(int nRow=0; nRow<m_nMaxRows; nRow++)
{
CWnd* pView=GetDlgItem(IdFromRowCol(nRow,nCol));
ASSERT(pView!=NULL);
pView->SetDlgCtrlID(IdFromRowCol(nRow,nCol-1));
}
}
// set new number of columns
m_nMaxCols--;
m_nCols=m_nMaxCols;
return TRUE;
}
BOOL COXSplitterWnd::InsertRow(int nInsertBefore, int nHeight)
{
ASSERT(nInsertBefore>=0 && nInsertBefore<=GetRowCount());
ASSERT(::IsWindow(GetSafeHwnd()));
// create new array of row info
CRowColInfo* pRowInfo=new CRowColInfo[m_nMaxRows+1];
int nRow=0;
for(nRow=0; nRow<m_nMaxRows+1; nRow++)
{
int nExistingRow=(nRow<nInsertBefore ? nRow : nRow-1);
if(nRow==nInsertBefore)
{
// set data for inserted row
pRowInfo[nRow].nMinSize=0;
pRowInfo[nRow].nIdealSize=nHeight;
pRowInfo[nRow].nCurSize=-1;
}
else
{
// copy existing row data
pRowInfo[nRow].nMinSize=m_pRowInfo[nExistingRow].nMinSize;
pRowInfo[nRow].nIdealSize=m_pRowInfo[nExistingRow].nIdealSize;
pRowInfo[nRow].nCurSize=m_pRowInfo[nExistingRow].nCurSize;
}
}
// delete old array
delete[] m_pRowInfo;
// save new one
m_pRowInfo=pRowInfo;
// set new number of rows
m_nMaxRows++;
m_nRows=m_nMaxRows;
// reset pane IDs (do that in backward direction)
for(nRow=m_nMaxRows-2; nRow>=nInsertBefore; nRow--)
{
for(int nCol=m_nMaxCols-1; nCol>=0; nCol--)
{
CWnd* pView=GetDlgItem(IdFromRowCol(nRow,nCol));
ASSERT(pView!=NULL);
pView->SetDlgCtrlID(IdFromRowCol(nRow+1,nCol));
}
}
return TRUE;
}
BOOL COXSplitterWnd::RemoveRow(int nDelRow)
{
ASSERT(GetRowCount()>1);
if(GetRowCount()<=1)
{
return FALSE;
}
ASSERT(nDelRow>=0 && nDelRow<GetRowCount());
ASSERT(::IsWindow(GetSafeHwnd()));
// delete all views in specified row
for(int nCol=0; nCol<m_nMaxCols; nCol++)
{
CWnd* pView=GetDlgItem(IdFromRowCol(nDelRow,nCol));
if(pView!=NULL)
{
DeleteView(nDelRow,nCol);
}
}
// create new array of row info
CRowColInfo* pRowInfo=new CRowColInfo[m_nMaxRows-1];
int nRow=0;
for(nRow=0; nRow<m_nMaxRows-1; nRow++)
{
int nExistingRow=(nRow<nDelRow ? nRow : nRow+1);
if(nExistingRow!=nDelRow)
{
// copy existing row data
pRowInfo[nRow].nMinSize=m_pRowInfo[nExistingRow].nMinSize;
pRowInfo[nRow].nIdealSize=m_pRowInfo[nExistingRow].nIdealSize;
pRowInfo[nRow].nCurSize=m_pRowInfo[nExistingRow].nCurSize;
}
}
// delete old array
delete[] m_pRowInfo;
// save new one
m_pRowInfo=pRowInfo;
// reset pane IDs (in forward direction)
for(nRow=nDelRow+1; nRow<m_nMaxRows; nRow++)
{
for(int nCol=0; nCol<m_nMaxCols; nCol++)
{
CWnd* pView=GetDlgItem(IdFromRowCol(nRow,nCol));
ASSERT(pView!=NULL);
pView->SetDlgCtrlID(IdFromRowCol(nRow-1,nCol));
}
}
// set new number of rows
m_nMaxRows--;
m_nRows=m_nMaxRows;
return TRUE;
}
void COXSplitterWnd::DeleteView(int row, int col)
{
ASSERT_VALID(this);
// if active child is being deleted - activate next
CWnd* pPane=GetPane(row,col);
ASSERT_VALID(pPane);
if(GetActivePane()==pPane)
{
ActivateNext(FALSE);
}
// default implementation assumes view will auto delete in PostNcDestroy
pPane->DestroyWindow();
}
#ifdef _DEBUG
void COXSplitterWnd::AssertValid() const
{
CWnd::AssertValid();
}
#endif
BOOL COXSplitterWnd::SwapPanes(CWnd* pFirstWnd, CWnd* pSecondWnd)
{
ASSERT(pFirstWnd && pSecondWnd);
int nCol1, nCol2, nRow1, nRow2;
if (!IsChildPane(pFirstWnd, &nRow1, &nCol1) ||
!IsChildPane(pSecondWnd, &nRow2, &nCol2))
{
return FALSE;
}
int nID1=IdFromRowCol(nRow1,nCol1);
int nID2=IdFromRowCol(nRow2,nCol2);
pSecondWnd->SetDlgCtrlID(nID1);
pFirstWnd->SetDlgCtrlID(nID2);
//exchange by row info
CSplitterWnd::CRowColInfo info;
CSplitterWnd::CRowColInfo* pInfo1=m_pRowInfo;
CSplitterWnd::CRowColInfo* pInfo2=m_pRowInfo;
pInfo1+=nID1 - (AFX_IDW_PANE_FIRST + nRow1 * 16 + nCol1);
pInfo2+=nID2 - (AFX_IDW_PANE_FIRST + nRow2 * 16 + nCol2);
memcpy(&info, pInfo1, sizeof(CSplitterWnd::CRowColInfo));
memcpy(pInfo1, pInfo2, sizeof(CSplitterWnd::CRowColInfo));
memcpy(pInfo2, &info, sizeof(CSplitterWnd::CRowColInfo));
RecalcLayout();
RedrawWindow();
return TRUE;
}