这是一位仁兄的代码: CSplitterWnd实现隐藏/显示列Pan ////////////////////////////////////////////////////////////////// // // splitex.h // (c) 1997, Oleg G. Galkin class CSplitterWndEx : public CSplitterWnd { protected: int m_nHidedCol; // hide column number, -1 if all columns // are shown public: CSplitterWndEx(); void ShowColumn(); void HideColumn(int colHide); // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CSplitterWndEx) //}}AFX_VIRTUAL // Generated message map functions protected: //{{AFX_MSG(CSplitterWndEx) // NOTE - the ClassWizard will add and remove member // functions here. //}}AFX_MSG DECLARE_MESSAGE_MAP() }; ////////////////////////////////////////////////////////////////// // // splitex.cpp // (c) 1997, Oleg G. Galkin #include "stdafx.h" #include "splitex.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ////////////////////////////////////////////////////////////////// / // CSplitterWndEx CSplitterWndEx::CSplitterWndEx() :m_nHidedCol(-1) { } void CSplitterWndEx::ShowColumn() { ASSERT_VALID(this); ASSERT(m_nCols < m_nMaxCols); ASSERT(m_nHidedCol != -1); int colNew = m_nHidedCol; m_nHidedCol = -1; int cxNew = m_pColInfo[m_nCols].nCurSize; m_nCols++; // add a column ASSERT(m_nCols == m_nMaxCols); // fill the hidden column int col; for (int row = 0; row < m_nRows; row++) { CWnd* pPaneShow = GetDlgItem( AFX_IDW_PANE_FIRST + row * 16 + m_nCols); ASSERT(pPaneShow != NULL); pPaneShow->ShowWindow(SW_SHOWNA); for (col = m_nCols - 2; col >= colNew; col--) { CWnd* pPane = GetPane(row, col); ASSERT(pPane != NULL); pPane->SetDlgCtrlID(IdFromRowCol(row, col + 1)); } pPaneShow->SetDlgCtrlID(IdFromRowCol(row, colNew)); } // new panes have been created -- recalculate layout for (col = colNew + 1; col < m_nCols; col++) m_pColInfo[col].nIdealSize = m_pColInfo[col - 1].nCurSize; m_pColInfo[colNew].nIdealSize = cxNew; RecalcLayout(); } void CSplitterWndEx::HideColumn(int colHide) { ASSERT_VALID(this); ASSERT(m_nCols > 1); ASSERT(colHide < m_nCols); ASSERT(m_nHidedCol == -1); m_nHidedCol = colHide; // if the column has an active window -- change it int rowActive, colActive; if (GetActivePane(&rowActive, &colActive) != NULL && colActive == colHide) { if (++colActive >= m_nCols) colActive = 0; SetActivePane(rowActive, colActive); } // hide all column panes for (int row = 0; row < m_nRows; row++) { CWnd* pPaneHide = GetPane(row, colHide); ASSERT(pPaneHide != NULL); pPaneHide->ShowWindow(SW_HIDE); pPaneHide->SetDlgCtrlID( AFX_IDW_PANE_FIRST + row * 16 + m_nCols); for (int col = colHide + 1; col < m_nCols; col++) { CWnd* pPane = GetPane(row, col); ASSERT(pPane != NULL); pPane->SetDlgCtrlID(IdFromRowCol(row, col - 1)); } } m_nCols--; m_pColInfo[m_nCols].nCurSize = m_pColInfo[colHide].nCurSize; RecalcLayout(); } BEGIN_MESSAGE_MAP(CSplitterWndEx, CSplitterWnd) //{{AFX_MSG_MAP(CSplitterWndEx) // NOTE - the ClassWizard will add and remove mapping macros here. //}}AFX_MSG_MAP END_MESSAGE_MAP()
视图分割,以前写的代码,今天也要用到,加了些新的东西,跟大家分享一下。。视图分割,视图隐藏等,分割条的移动与否。
下面是代码:
头文件:
#pragma once #include "afxext.h" #include "2DArray.h" class CSplitterWndEx : public CSplitterWnd { public: CSplitterWndEx(void); virtual ~CSplitterWndEx(); typedef std::list<int> LIST_INT;//模板函数 // Attributes public: // Operations public: void ShowColumn();//显示列视图 void HideColumn(int colHide);//隐藏列视图 BOOL CreateStatic(CWnd* pParentWnd,int nRows,int nCols, DWORD dwStyle=WS_CHILD|WS_VISIBLE,UINT nID=AFX_IDW_PANE_FIRST); void Init();//初始化 BOOL CreateView(int row,int col,CRuntimeClass* pViewClass,SIZE sizeInit,CCreateContext* pContext); protected: void RenumeratePanes(); void RemoveColInfo(int place,int col); CPoint RelToAbsPosition(int i, int j); int RelToAbsPosition(LIST_INT &vis_list, LIST_INT &hid_list, int cur_index); BOOL IsPaneVisible(int row, int col); // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CSplitterWndEx) //}}AFX_VIRTUAL // Implementation public: void OnInvertTracker(const CRect& rect); void OnDrawSplitter( CDC* pDC, ESplitType nType, const CRect& rectArg ); // Generated message map functions protected: //{{AFX_MSG(CSplitterWndEx) DECLARE_MESSAGE_MAP() afx_msg void OnLButtonDown(UINT nFlags, CPoint point); afx_msg void OnMouseMove(UINT nFlags, CPoint point); afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message); // NOTE - the ClassWizard will add and remove member functions here. //}}AFX_MSG public: LIST_INT m_shown_cols; //shown column list LIST_INT m_hid_cols; //hidden column list LIST_INT m_shown_rows; //shown rows list LIST_INT m_hid_rows; //hidden rows list protected: C2DArray m_pane_ptr_array; // array of pointers to splitter panes CRowColInfo* m_pSavedColInfo; CRowColInfo* m_pSavedRowInfo; protected: int m_nHidedCol; // hide column number, -1 if all columns };#include "StdAfx.h" #include "SplitterWndEx.h" CSplitterWndEx::CSplitterWndEx() { //更改分割条和窗格间距大小 m_cxSplitter = m_cySplitter = 1; m_cxSplitterGap = m_cySplitterGap = 1; } CSplitterWndEx::~CSplitterWndEx() { if(m_pSavedColInfo != NULL) { delete []m_pSavedColInfo; m_pSavedColInfo = NULL; } if(m_pSavedRowInfo != NULL) { delete []m_pSavedRowInfo; m_pSavedRowInfo = NULL; } } BEGIN_MESSAGE_MAP(CSplitterWndEx, CSplitterWnd) ON_WM_LBUTTONDOWN() ON_WM_MOUSEMOVE() ON_WM_SETCURSOR() END_MESSAGE_MAP() void CSplitterWndEx::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default CWnd::OnLButtonDown(nFlags, point); } void CSplitterWndEx::OnMouseMove(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default CWnd::OnMouseMove(nFlags, point); } BOOL CSplitterWndEx::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) { // TODO: Add your message handler code here and/or call default return CWnd::OnSetCursor(pWnd, nHitTest, message); } //绘制分割窗口特征 void CSplitterWndEx::OnDrawSplitter( CDC* pDC, ESplitType nType, const CRect& rectArg) { if (pDC == NULL) { RedrawWindow(rectArg, NULL, RDW_INVALIDATE|RDW_NOCHILDREN); return; } ASSERT_VALID(pDC); // otherwise, actually draw CRect rc = rectArg; switch(nType) { case splitBorder: //重画分割窗口边界,使为绿色 pDC->Draw3dRect(rc,RGB(0,200,0),RGB(0,200,0)); rc.InflateRect(-1,-1); pDC->Draw3dRect(rc,RGB(0,100,0),RGB(0,100,0)); return; case splitBox: pDC->Draw3dRect(rc,RGB(0,0,0),RGB(0,0,0)); rc.InflateRect(-1,-1); pDC->Draw3dRect(rc,RGB(0,0,0),RGB(0,0,0)); rc.InflateRect(-1,-1); pDC->FillSolidRect(rc,RGB(0,0,0)); pDC->Draw3dRect(rc,RGB(0,0,0),RGB(0,0,0)); return; case splitBar: //重画分割条,使之为绿色 pDC->FillSolidRect(rc,RGB(0,80,0)); rc.InflateRect(-1,-1); pDC->Draw3dRect(rc,RGB(0,0,200),RGB(0,0,200)); return; default: ASSERT(FALSE); } // fill the middle pDC->FillSolidRect(rc,RGB(0,200,0)); } //绘制分割条 void CSplitterWndEx::OnInvertTracker(const CRect& rect) { ASSERT_VALID(this); ASSERT(!rect.IsRectEmpty()); ASSERT((GetStyle() & WS_CLIPCHILDREN) == 0); // pat-blt without clip children on CDC* pDC = GetDC(); //翻转画刷模式 CBrush* pBrush = CDC::GetHalftoneBrush(); HBRUSH hOldBrush = NULL; if (pBrush != NULL) hOldBrush = (HBRUSH)SelectObject(pDC->m_hDC, pBrush->m_hObject); //在设备上下文创建位模式 pDC->PatBlt(rect.left,rect.top,rect.Width(),rect.Height(),PATINVERT); if (hOldBrush != NULL) SelectObject(pDC->m_hDC, hOldBrush); ReleaseDC(pDC); } void CSplitterWndEx::ShowColumn() { ASSERT_VALID(this); ASSERT(m_nCols < m_nMaxCols); ASSERT(m_nHidedCol != -1); int colNew = m_nHidedCol; m_nHidedCol = -1; int cxNew = m_pColInfo[m_nCols].nCurSize; m_nCols++; // add a column ASSERT(m_nCols == m_nMaxCols); // fill the hidden column int col; for (int row = 0; row < m_nRows; row++) { CWnd* pPaneShow = GetDlgItem( AFX_IDW_PANE_FIRST + row * 16 + m_nCols); ASSERT(pPaneShow != NULL); pPaneShow->ShowWindow(SW_SHOWNA); for (col = m_nCols - 2; col >= colNew; col--) { CWnd* pPane = GetPane(row, col); ASSERT(pPane != NULL); pPane->SetDlgCtrlID(IdFromRowCol(row, col + 1)); } pPaneShow->SetDlgCtrlID(IdFromRowCol(row, colNew)); } // new panes have been created -- recalculate layout for (col = colNew + 1; col < m_nCols; col++) m_pColInfo[col].nIdealSize = m_pColInfo[col - 1].nCurSize; m_pColInfo[colNew].nIdealSize = cxNew; RecalcLayout(); } //隐藏视图 void CSplitterWndEx::HideColumn(int colHide) { ASSERT_VALID(this); ASSERT(m_nCols > 1); ASSERT(colHide < m_nCols); ASSERT(m_nHidedCol != -1); m_nHidedCol = colHide; // if the column has an active window -- change it int rowActive, colActive; if (GetActivePane(&rowActive, &colActive) != NULL && colActive == colHide) { if (++colActive >= m_nCols) colActive = 0; SetActivePane(rowActive, colActive); } // hide all column panes for (int row = 0; row < m_nRows; row++) { CWnd* pPaneHide = GetPane(row, colHide); ASSERT(pPaneHide != NULL); pPaneHide->ShowWindow(SW_HIDE); pPaneHide->SetDlgCtrlID( AFX_IDW_PANE_FIRST + row * 16 + m_nCols); for (int col = colHide + 1; col < m_nCols; col++) { CWnd* pPane = GetPane(row, col); ASSERT(pPane != NULL); pPane->SetDlgCtrlID(IdFromRowCol(row, col - 1)); } } m_nCols--; m_pColInfo[m_nCols].nCurSize = m_pColInfo[colHide].nCurSize; RecalcLayout(); } //重载静态视图创建 BOOL CSplitterWndEx::CreateStatic(CWnd* pParentWnd,int nRows,int nCols,DWORD dwStyle,UINT nID) { BOOL ret; ret= CSplitterWnd::CreateStatic(pParentWnd,nRows,nCols,dwStyle,nID); Init(); return ret; } void CSplitterWndEx::Init()//初始化 { int i,j; m_pane_ptr_array.Init(m_nMaxRows,m_nMaxCols); for(i=0; i<m_nMaxRows; i++){ m_shown_rows.push_back(i); } for(j=0; j<m_nMaxCols; j++){ m_shown_cols.push_back(j); } m_pSavedColInfo = new CRowColInfo[m_nMaxCols]; m_pSavedRowInfo = new CRowColInfo[m_nMaxRows]; } //重载视图创建 BOOL CSplitterWndEx::CreateView(int row,int col,CRuntimeClass* pViewClass,SIZE sizeInit,CCreateContext* pContext ) { BOOL ret = CSplitterWnd::CreateView(row, col, pViewClass, sizeInit, pContext ); CWnd* pWnd = GetPane(row,col); ASSERT(pWnd); m_pane_ptr_array(row,col)= pWnd; return ret; } void CSplitterWndEx::RenumeratePanes() { int i,j,id; for(i=0; i<m_nMaxRows; i++){ for(j=0;j<m_nMaxCols;j++){ CPoint pos = RelToAbsPosition(i,j); CWnd* pPane = (CWnd*) m_pane_ptr_array(pos.x, pos.y); ASSERT(pPane != NULL); id=AFX_IDW_PANE_FIRST+i*16+j; int r=pPane->SetDlgCtrlID(id); ASSERT(r); if(IsPaneVisible(pos.x,pos.y)) pPane->ShowWindow(SW_SHOW); else pPane->ShowWindow(SW_HIDE); } } } void CSplitterWndEx::RemoveColInfo(int place,int col) { ASSERT(m_nCols<=m_nMaxCols); m_pSavedColInfo[col] = m_pColInfo[place]; for(int i=place; i<m_nCols; i++){ m_pColInfo[i] = m_pColInfo[i+1]; } } CPoint CSplitterWndEx::RelToAbsPosition(int row,int col) { CPoint pos; pos.x = RelToAbsPosition(m_shown_rows, m_hid_rows,row); pos.y = RelToAbsPosition(m_shown_cols, m_hid_cols,col); return pos; } int CSplitterWndEx::RelToAbsPosition(LIST_INT &vis_list, LIST_INT &hid_list, int cur_index) { int org_index; int i; LIST_INT::iterator it; if( cur_index < (int)vis_list.size()){ it=vis_list.begin(); for(i=0;i<cur_index; i++){ it++; } org_index = *it; } else{ it=hid_list.begin(); for(i=0;i<cur_index-(int)vis_list.size(); i++){ it++; } org_index = *it; } return org_index; } BOOL CSplitterWndEx::IsPaneVisible(int row, int col) { BOOL bRow, bCol; ASSERT(m_nRows<=m_nMaxCols); if( m_shown_rows.end() != std::find(m_shown_rows.begin(),m_shown_rows.end(),row)){ bRow = TRUE; } else{ bRow=FALSE; } ASSERT(m_nCols<=m_nMaxCols); if( m_shown_cols.end() != std::find(m_shown_cols.begin(),m_shown_cols.end(),col)){ bCol = TRUE; } else{ bCol=FALSE; } return bRow && bCol; }