现在的位置: 首页 > 综合 > 正文

mfc 窗口分割 CSplitterWnd扩展类实现隐藏/显示列Pan

2018年02月09日 ⁄ 综合 ⁄ 共 9084字 ⁄ 字号 评论关闭

http://blog.csdn.net/hejianhua/article/details/7328997

// 2DArray.h: interface for the C2DArray class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_2DARRAY_H__86045FE5_1A92_4495_AAD7_C276F3E7758E__INCLUDED_)
#define AFX_2DARRAY_H__86045FE5_1A92_4495_AAD7_C276F3E7758E__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

class C2DArray  
{
public:

	typedef void *W_PTR;

	C2DArray();
	
	void Init(int rows, int cols);

	virtual ~C2DArray();

	W_PTR& operator()(int row,int col)
	{
		ASSERT(m_pData);
		ASSERT(row*m_cols + col < m_rows*m_cols);
		
		return *(m_pData+row*m_cols + col);
	}

protected:
	W_PTR	*m_pData;
	int		m_rows;
	int		m_cols;
};

#endif // !defined(AFX_2DARRAY_H__86045FE5_1A92_4495_AAD7_C276F3E7758E__INCLUDED_)

// 2DArray.cpp: implementation of the C2DArray class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Msp.h"
#include "2DArray.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
C2DArray::C2DArray():
	m_rows(0), m_cols(0), m_pData(0)
{
}

void C2DArray::Init(int rows, int cols)
{
	m_rows=rows;
	m_cols=cols;
	m_pData =  new W_PTR[m_rows * m_cols];
	memset(m_pData, 0, m_rows * m_cols);
}

C2DArray::~C2DArray()
{
	if(m_pData)
		delete[] m_pData;
}

#if !defined(AFX_EXTSPLITTER_H__BB454230_2E7D_4794_BE28_A5020F3B054C__INCLUDED_)
#define AFX_EXTSPLITTER_H__BB454230_2E7D_4794_BE28_A5020F3B054C__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// ExtSplitter.h : header file
//

/////////////////////////////////////////////////////////////////////////////
// CExtSplitter frame with splitter

#ifndef __AFXEXT_H__
#include <afxext.h>
#endif

#include <list>
#include <algorithm>
#include "2DArray.h"

class CExtSplitter : public CSplitterWnd
{

public:
	typedef std::list<int> LIST_INT;

	CExtSplitter();           

	virtual ~CExtSplitter();

	BOOL	CreateStatic(CWnd* pParentWnd,
			int nRows, int nCols,
			DWORD dwStyle = WS_CHILD | WS_VISIBLE,
			UINT nID = AFX_IDW_PANE_FIRST);
	
	virtual BOOL CreateView( int row, int col, CRuntimeClass* pViewClass, SIZE sizeInit, CCreateContext* pContext );

	void	HideColumn(int colHide);
	void	ShowColumn(int colShow);
	void	HideRow(int colRow);
	void	ShowRow(int row);

protected:

	void	Init();
	int		AbsToRelPosition(LIST_INT &list, int col);
	void	RestoreColInfo(int place,int col);
	void	RestoreRowInfo(int place,int col);
	void	RemoveColInfo(int place,int col);
	void	RemoveRowInfo(int place,int col);
	void	RenumeratePanes();
	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);



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;


// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CExtSplitter)
	protected:
	//}}AFX_VIRTUAL


	// Generated message map functions
	//{{AFX_MSG(CExtSplitter)
		// NOTE - the ClassWizard will add and remove member functions here.
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_EXTSPLITTER_H__BB454230_2E7D_4794_BE28_A5020F3B054C__INCLUDED_)
// ExtSplitter.cpp : implementation file
//
#include "stdafx.h"
#include "ExtSplitter.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CExtSplitter

CExtSplitter::CExtSplitter(): m_pSavedColInfo(NULL)
{
}

CExtSplitter::~CExtSplitter()
{
	if(m_pSavedColInfo)
		delete[] m_pSavedColInfo;
	
	if(m_pSavedRowInfo)
		delete[] m_pSavedRowInfo;
}

BOOL CExtSplitter::CreateStatic(CWnd* pParentWnd,
		int nRows, int nCols,
		DWORD dwStyle,
		UINT nID )
{
	BOOL ret;

	ret= CSplitterWnd::CreateStatic(pParentWnd, nRows, nCols, dwStyle , nID );
	Init();
	return ret;
}
BOOL CExtSplitter::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 CExtSplitter::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];
}


void CExtSplitter::ShowColumn(int col)
{
     ASSERT_VALID(this);
     ASSERT(m_nCols < m_nMaxCols);

	std::list<int>::iterator col_pos;  

	col_pos = std::find(m_shown_cols.begin(),m_shown_cols.end(),col);
	
	if(col_pos!=m_shown_cols.end())
	{
		ASSERT(0);
		return;
	}

	int place = AbsToRelPosition(m_shown_cols, col);

	m_nCols++;  // add a column
	
	m_shown_cols.push_back(col);
	m_shown_cols.sort();
	m_hid_cols.remove(col);

	RenumeratePanes();

	RestoreColInfo(place,col);
	RecalcLayout();
}

int CExtSplitter::AbsToRelPosition(LIST_INT &list, int value)
{
	LIST_INT::iterator pos;
	int index = -1;

	pos = std::find_if(list.begin(),list.end(), std::bind2nd(std::greater<int>(),value));

	if(pos!=list.end())
	{
		index = std::distance(list.begin(),pos);
	}
	else
	{
		index = list.size();
	}

	return index;
}

void CExtSplitter::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];
	}
}

void CExtSplitter::RestoreColInfo(int place,int col)
{
	ASSERT(m_nCols<=m_nMaxCols);

	for(int i = m_nCols-1; i>=place + 1; i--)
	{
		m_pColInfo[i] = m_pColInfo[i-1];
	}

	m_pColInfo[place] = m_pSavedColInfo[col];
}

void CExtSplitter::HideColumn(int colHide)
{
	ASSERT_VALID(this);
	ASSERT(m_nCols > 1);
	ASSERT(colHide < m_nMaxCols);

	std::list<int>::iterator col_pos;  

	col_pos = std::find(m_shown_cols.begin(),m_shown_cols.end(),colHide);
	
	if(col_pos==m_shown_cols.end())
	{
		ASSERT(0);
		return;
	}

	int place = std::distance(m_shown_cols.begin(),col_pos);
	
	// if the column has an active window -- change it
    int rowActive, colActive;
    if (GetActivePane(&rowActive, &colActive) != NULL &&
         colActive == place)
    {
          if (++colActive >= m_nCols)
              colActive = 0;
          SetActivePane(rowActive, colActive);
    }

	m_shown_cols.remove(colHide);
	m_hid_cols.push_back(colHide);

    m_nCols--;

	RenumeratePanes();

	RemoveColInfo(place,colHide);

    RecalcLayout();
}


CPoint CExtSplitter::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 CExtSplitter::RelToAbsPosition(LIST_INT &vis_list, LIST_INT &hid_list, int cur_index)
{
	int org_index;

	int i;
	LIST_INT::iterator it;
	if( cur_index < 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-vis_list.size(); i++)
		{
			it++;
		}

		org_index = *it;
	}

	return org_index;
}


BOOL CExtSplitter::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;
}

void CExtSplitter::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 CExtSplitter::HideRow(int rowHide)
{
	ASSERT_VALID(this);
	ASSERT(m_nCols > 1);
	ASSERT(rowHide < m_nMaxCols);

	std::list<int>::iterator row_pos;  

	row_pos = std::find(m_shown_rows.begin(),m_shown_rows.end(),rowHide);
	
	if(row_pos==m_shown_rows.end())
	{
		ASSERT(0);
		return;
	}

	int place = std::distance(m_shown_rows.begin(),row_pos);
	
	// if the column has an active window -- change it
    int rowActive, colActive;
    if (GetActivePane(&rowActive, &colActive) != NULL &&
         rowActive == place)
    {
          if (++rowActive >= m_nRows)
              rowActive = 0;
          SetActivePane(rowActive, colActive);
    }


	m_shown_rows.remove(rowHide);
	m_hid_rows.push_back(rowHide);


    m_nRows--;

	RenumeratePanes();

	RemoveRowInfo(place,rowHide);

    RecalcLayout();
}

void CExtSplitter::RemoveRowInfo(int place,int col)
{
	ASSERT(m_nRows<=m_nMaxRows);

	m_pSavedRowInfo[col] = m_pRowInfo[place];

	for(int i=place; i<m_nRows; i++)
	{
		m_pRowInfo[i] = m_pRowInfo[i+1];
	}
}

void CExtSplitter::ShowRow(int row)
{
     ASSERT_VALID(this);
     ASSERT(m_nRows < m_nMaxRows);

	std::list<int>::iterator row_pos;  

	row_pos = std::find(m_shown_rows.begin(),m_shown_rows.end(),row);
	
	if(row_pos!=m_shown_rows.end())
	{
		ASSERT(0);
		return;
	}

	int place = AbsToRelPosition(m_shown_rows, row);

	m_nRows++;  // add a column
	
	m_shown_rows.push_back(row);
	m_shown_rows.sort();
	m_hid_rows.remove(row);

	RenumeratePanes();

	RestoreRowInfo(place, row);
	RecalcLayout();
}

void CExtSplitter::RestoreRowInfo(int place,int col)
{
	ASSERT(m_nRows<=m_nMaxRows);

	for(int i = m_nRows-1; i>=place + 1; i--)
	{
		m_pRowInfo[i] = m_pRowInfo[i-1];
	}

	m_pRowInfo[place] = m_pSavedRowInfo[col];
}


BEGIN_MESSAGE_MAP(CExtSplitter, CSplitterWnd)
	//{{AFX_MSG_MAP(CExtSplitter)
		// NOTE - the ClassWizard will add and remove mapping macros here.
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CExtSplitter message handlers

抱歉!评论已关闭.