⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 multicolumnsortlistview.cpp

📁 数据结构链表的演示程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
	
	Usage:
		You generally should not use this class directly, though it
		is possible. You need to do two things to use it directly.
		Set m_strUniqueName to someting, and set m_strColumnWidthSection
		to where you want the column widths to be saved.

		The purpose of m_strUniqueName is to allow for saving of
		multiple instances of listview objects. So obviously you would
		need to set this differently for each instance. SetUniqueName must be called
		before calling InsertColumn() or LoadColumnWidths().

		If you are deriving from this class, you need to do the following:
		Add a class to your project derived from CListView, then go into the
		header file and include MultiColumnSortListView.h and change all
		references to CListView to CMultiColumnSortListView. Then in the .cpp
		file of your class, change all the message maps to CMultiColumnSortListView
		instead of CListView. That should do it.

  Compiling:
		One problem you will have is finding IDB_ARROWUP and IDB_ARROWDOWN.
		Those bitmaps will be included with this set of classes, You should
		add them to your project or add your own bitmaps named correctly.
		These are the bitmaps that show the sort order on the header control.

        I hope this is simple enough, kind of a pain to get started but after
		that it should be cake and hopefully it will be useful.
  
  Things to be aware of:
		
		Multithreading:
		     If you delete all the items from another thread
			 in the middle of a sort, it will crash. This is the only
			 bug i have found.
		
		Column Widths:
			 
			MINCOLWIDTH - Minimum width a column can be.
			MAXCOLWIDTH - Maximum width a column can be.
			These are hard coded in the header file. Be aware.
			
			MAXCOLUMNS  - The most columns you can have right
			now is 64, that is only because im use __int64 to
			hold the column sort states. Who needs more than
			64 columns anyway? If you do, you can change it to
			CUIntArray, i just didnt see the need for a whole int
			when all i needed was a bit. 
		        

  Credits:
		
		Iuri Apollonio -- Sorting Class ( great class )
		Zafir Anjum    -- CMultiColumnSortListView::GetColumnCount
		Roger Onslow   -- CMultiColumnSortListView::AutoSizeColumns
		Zafir Anjum    -- CSortableHeaderCtrl::SetSortImage
		Me             -- The Rest, I think.

*/
// MultiColumnSortListView.cpp : implementation file
//

#include "stdafx.h"
#include "MultiColumnSortListView.h"
#include "SortClass.h"

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

/////////////////////////////////////////////////////////////////////////////
// CMultiColumnSortListView

IMPLEMENT_DYNCREATE(CMultiColumnSortListView, CListView)
/*
When deriving from this class you must set m_strUniqueName to something
this name is used to save each instances column widths to the registry
*/
CMultiColumnSortListView::CMultiColumnSortListView()
{	
//	m_strUniqueName.Empty();
	m_strUniqueName="结果显示";
	m_strColumnWidthSection = "ColumnWidths";
	m_bSorting = false;
	m_lColumnSortStates = 0;
}

CMultiColumnSortListView::~CMultiColumnSortListView()
{
}


BEGIN_MESSAGE_MAP(CMultiColumnSortListView, CListView)
	//{{AFX_MSG_MAP(CMultiColumnSortListView)
	ON_WM_CREATE()
	ON_WM_DESTROY()
	//}}AFX_MSG_MAP
	ON_NOTIFY(HDN_ITEMCLICKA, 0, OnHeaderClicked) 
	ON_NOTIFY(HDN_ITEMCLICKW, 0, OnHeaderClicked)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMultiColumnSortListView drawing

void CMultiColumnSortListView::OnDraw(CDC* pDC)
{
	CDocument* pDoc = GetDocument();
}
/////////////////////////////////////////////////////////////////////////////
// CMultiColumnSortListView diagnostics
#ifdef _DEBUG
void CMultiColumnSortListView::AssertValid() const
{
	CListView::AssertValid();
}
void CMultiColumnSortListView::Dump(CDumpContext& dc) const
{
	CListView::Dump(dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CMultiColumnSortListView message handlers

/*
This function saves the columns widths of the listctrl to the registry.
This is called in two places, OnDestroy, and OnEndTrack in the headerCtrl class.
*/
void CMultiColumnSortListView::SaveColumnWidths()
{	//You must set a unique name for every listctrl
	ASSERT( m_strUniqueName.GetLength() );
	CString strEntry( m_strUniqueName );
	CString strValue;
	CListCtrl &rListCtrl = GetListCtrl();
	int iNumColumns = GetColumnCount();
	for( int i = 0; i < iNumColumns; i++ )
	{
		CString strTemp;
		strTemp.Format("%d,", rListCtrl.GetColumnWidth( i ) );
		strValue += strTemp;
	}
	AfxGetApp()->WriteProfileString( m_strColumnWidthSection, strEntry, strValue );
}

/*
This function loads all the column widths for each column that was saved and applies the width
to the column. This function should be called when you are done inserting data. Or you 
can call SetColumnWidth to set the column width right after you InsertColumn(), If you call 
my InsertColumn it will do this for you.
*/
int CMultiColumnSortListView::LoadColumnWidths()
{	//This function will load all the column widths and apply the widths to each respective column
	int iNumColumns = GetColumnCount();
	CListCtrl &rListCtrl = GetListCtrl();
	for( int i = 0; i < iNumColumns; i++ )
	{
		SetColumnWidth( i );
	}
	return 1;
}

/*
This function is the heart of the class. This will get called automatically
when you click a header, and if you press control while clicking the header,
a multi column sort will take place (ie: sorting the current columns within all the
previously control+clicked columns). The multi column sort saves all the previosuly
control+clicked columns in an array and sorts them in reverse order. So if you click 
column 0, 2, 3, 5 while holding control, it will sort 5, 3, 2, 0. ( this acheives a
muli-column sort).
*/
void CMultiColumnSortListView::SortColumn( int iSubItem, bool bSortingMultipleColumns )
{	
	CListCtrl &rListCtrl = GetListCtrl();
	int iNumCombinedSortedCols = GetNumCombinedSortedColumns();
	m_bSorting = true;

	if( bSortingMultipleColumns )
	{
		if( NotInCombinedSortedColumnList( iSubItem ) )
			m_aCombinedSortedColumns[ iNumCombinedSortedCols++ ] = iSubItem;
		else
			MoveItemInCombinedSortedListToEnd( iSubItem );

		for( int i = iNumCombinedSortedCols - 1; i >= 0 ; i-- )
		{
			SORT_STATE ssEachItem = GetItemSortState( m_aCombinedSortedColumns[i] );
			if( iNumCombinedSortedCols - 1 != i )
				ssEachItem = (SORT_STATE)!ssEachItem;
			
			CSortClass csc(&rListCtrl, m_aCombinedSortedColumns[i], IsColumnNumeric( m_aCombinedSortedColumns[i] ) , IsColumnFloat(m_aCombinedSortedColumns[i]));	
			csc.Sort( ssEachItem );
			if( i == iNumCombinedSortedCols - 1 )
			{	//Only swap the last column's sort order.
				m_ctlHeaderCtrl.SetSortImage( m_aCombinedSortedColumns[i], ssEachItem );
				SetItemSortState( m_aCombinedSortedColumns[i] , (SORT_STATE)!ssEachItem );			
			}
		}
	}
	else
	{
		m_ctlHeaderCtrl.RemoveAllSortImages();
		EmptyArray(m_aCombinedSortedColumns);
		m_aCombinedSortedColumns[ 0 ] = iSubItem;
		SORT_STATE ssEachItem = GetItemSortState( iSubItem );
		
		CSortClass csc(&rListCtrl, iSubItem, IsColumnNumeric( iSubItem ) ,IsColumnFloat(iSubItem));	
		csc.Sort( ssEachItem );
		m_ctlHeaderCtrl.SetSortImage( iSubItem, ssEachItem );
		SetItemSortState( iSubItem , (SORT_STATE)!ssEachItem );
	}
	m_bSorting = false;
}

/*
My version of InsertColumn that will automatically load the last column
width from the registry. 
*/
int CMultiColumnSortListView::InsertColumn(int nCol, LPCTSTR lpszColumnHeading, int nFormat, int nWidth, int nSubItem)
{
	CListCtrl &rListCtrl = GetListCtrl();
	GetListCtrl().InsertColumn( nCol, lpszColumnHeading, nFormat, nWidth, nSubItem );
	SetColumnWidth( nCol );
	return 1;
}

/*
Utility function to size columns based on its data.
written by Roger Onslow
*/
void CMultiColumnSortListView::AutoSizeColumn( int iColumn )
{
	CListCtrl &rListCtrl = GetListCtrl();
	rListCtrl.SetRedraw(false);
	
	rListCtrl.SetColumnWidth(iColumn,LVSCW_AUTOSIZE);
	int wc1 = rListCtrl.GetColumnWidth( iColumn );
	rListCtrl.SetColumnWidth(iColumn,LVSCW_AUTOSIZE_USEHEADER);
	int wc2 = rListCtrl.GetColumnWidth( iColumn );
	int wc = max(MINCOLWIDTH,max( wc1,wc2 ));
	
	if( wc > MAXCOLWIDTH )
		wc = MAXCOLWIDTH;
	
	rListCtrl.SetColumnWidth( iColumn,wc );  
	rListCtrl.SetRedraw(true);
}

/*
Utility function to get rid of all the columns
*/
void CMultiColumnSortListView::DeleteAllColumns()
{
	CListCtrl &rListCtrl = GetListCtrl();
	int iNumCols = GetColumnCount();
	for ( int i = 0; i < iNumCols; i++ )
		rListCtrl.DeleteColumn(0);
}

/*
Utility function to get rid of all items.
*/
void CMultiColumnSortListView::DeleteAllItems()
{
	CListCtrl &rListCtrl = GetListCtrl();
	if( rListCtrl.GetItemCount() > 0 )
		rListCtrl.DeleteAllItems();
}

/*
Utility function to get the number of columns
written by Zafir Anjum
*/
UINT CMultiColumnSortListView::GetColumnCount()
{
	CHeaderCtrl *pHeaderCtrl = (CHeaderCtrl*)GetListCtrl().GetDlgItem(0);
	return pHeaderCtrl->GetItemCount();
}

/*
Just add some extended styles from the new IE4 stuff.
Of course you can either change the code or change your
derived class's OnCreate to call CListView::OnCreate
*/
int CMultiColumnSortListView::OnCreate(LPCREATESTRUCT lpCreateStruct) 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -