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

📄 listctrlex.cpp

📁 本程序为求解博弈纳什均衡解的源程序
💻 CPP
字号:
// ListCtrlEx.cpp : implementation file
//

#include "stdafx.h"
#include "Game.h"
#include "ListCtrlEx.h"

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

/////////////////////////////////////////////////////////////////////////////
// CListCtrlEx

CListCtrlEx::CListCtrlEx()
{
	// 设置排序的列号初始为-1,表示没有列要排序
	m_nSortedCol = -1;

	// 设置排序的初始方向为升序
	m_bSortAscending = TRUE;

	// 当前编辑的列编号
	curSelCol = 0;

	// 一个单元格存储单个数据的标志
	isOneValueInEdit = TRUE;
}

CListCtrlEx::~CListCtrlEx()
{
}


BEGIN_MESSAGE_MAP(CListCtrlEx, CListCtrl)
	//{{AFX_MSG_MAP(CListCtrlEx)
	ON_NOTIFY(HDN_ITEMCLICKA, 0, OnItemclick) 
	ON_WM_CREATE()
	ON_WM_DESTROY()
	ON_NOTIFY(HDN_ITEMCLICKW, 0, OnItemclick) 
	ON_WM_LBUTTONDBLCLK()
	ON_NOTIFY_REFLECT(LVN_ENDLABELEDIT, OnEndlabeledit)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CListCtrlEx message handlers
void CListCtrlEx::OnItemclick(NMHDR* pNMHDR, LRESULT* pResult) 
{
	HD_NOTIFY *phdn = (HD_NOTIFY *) pNMHDR;

	if( phdn->iButton == 0 )
	{
		//鼠标左键点中表头
		if( phdn->iItem == m_nSortedCol )
			m_bSortAscending = !m_bSortAscending;
		else
			m_bSortAscending = TRUE;

		m_nSortedCol = phdn->iItem;
		SortTextItems( m_nSortedCol, m_bSortAscending );
		m_headerCtrl.SetSortImage(m_nSortedCol, m_bSortAscending);
	}

	*pResult = 0;
}

void CListCtrlEx::PreSubclassWindow() 
{
	CListCtrl::PreSubclassWindow();
	InitializeFlatHeader();
}

int CListCtrlEx::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CListCtrl::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	return InitializeFlatHeader();
	
	//return 0;
}

void CListCtrlEx::OnDestroy() 
{
	CListCtrl::OnDestroy();
	
	
}

/*******************************************************************

功能:初始化扁平表头
参数:无

*******************************************************************/

int CListCtrlEx::InitializeFlatHeader()
{
	if (!m_headerCtrl.SubclassWindow(GetDlgItem(0)->GetSafeHwnd()))
		return -1;

	m_headerCtrl.FlatHeader();
	//SaveColumnState(_T("Settings"), _T("Control"));

	return 0;
}

/*******************************************************************

功能:对选定列进行排序
参数:nCol--要排序的列号
      bAscending--排序的方向,升序或降序
      low--排序开始扫描的行,缺省为0
	  high--排序的结束行,-1表示到最后一行结束

*******************************************************************/

BOOL CListCtrlEx::SortTextItems(int nCol, BOOL bAscending, int low, int high)
{
	if( nCol >= ((CHeaderCtrl*)GetDlgItem(0))->GetItemCount() )
		return FALSE;

	if( high == -1 ) high = GetItemCount() - 1;

	int lo = low;
	int hi = high;
	CString midItem;

	if( hi <= lo ) return FALSE;

	midItem = GetItemText( (lo+hi)/2, nCol );

	//遍历要排序的所有行
	while( lo <= hi )
	{
		//定义中间变量保存一行的所有列的文本
		CStringArray rowText;

		//采用二分排序法进行比较.
		if( bAscending ) {
			while( ( lo < high ) && ( GetItemText(lo, nCol) < midItem ) )
				++lo;
		}
		else {
			while( ( lo < high ) && ( GetItemText(lo, nCol) > midItem ) )
				++lo;
		}

		if( bAscending ) {
			while( ( hi > low ) && ( GetItemText(hi, nCol) > midItem ) )
				--hi;
		}

		else {
			while( ( hi > low ) && ( GetItemText(hi, nCol) < midItem ) )
				--hi;
		}

		//交换两行
		if( lo <= hi )
		{
			//进交换不等的项
			if( GetItemText(lo, nCol) != GetItemText(hi, nCol))
			{
				//交换行
				LV_ITEM lvitemlo, lvitemhi;
				int nColCount =
					((CHeaderCtrl*)GetDlgItem(0))->GetItemCount();
				rowText.SetSize( nColCount );
				int i;
				for( i=0; i<nColCount; i++)
					rowText[i] = GetItemText(lo, i);
				lvitemlo.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_STATE;
				lvitemlo.iItem = lo;
				lvitemlo.iSubItem = 0;
				lvitemlo.stateMask = LVIS_CUT | LVIS_DROPHILITED |
					LVIS_FOCUSED | LVIS_SELECTED |
					LVIS_OVERLAYMASK | LVIS_STATEIMAGEMASK;
				
				lvitemhi = lvitemlo;
				lvitemhi.iItem = hi;
				
				GetItem( &lvitemlo );
				GetItem( &lvitemhi );
				
				for( i=0; i<nColCount; i++)
					SetItemText(lo, i, GetItemText(hi, i));
				
				lvitemhi.iItem = lo;
				SetItem( &lvitemhi );
				
				for( i=0; i<nColCount; i++)
					SetItemText(hi, i, rowText[i]);
				
				lvitemlo.iItem = hi;
				SetItem( &lvitemlo );
			}
			
			++lo;
			--hi;
		}
	}
	
	//一次交换排序未完成,继续排序
	if( low < hi )
		SortTextItems( nCol, bAscending , low, hi);
	
	//一次交换排序未完成,继续排序
	if( lo < high )
		SortTextItems( nCol, bAscending , lo, high );
	
	return TRUE;
}

/*******************************************************************

功能:设置列表的扩展样式
参数:dwNewStyle--列表的扩展样式

*******************************************************************/

void CListCtrlEx::SetExtendedStyle(DWORD dwNewStyle)
{
	//返回列表的扩展样式
	DWORD dwStyle = ::SendMessage (m_hWnd, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);

	//增加新样式
	dwStyle |= dwNewStyle;

	//设置新的扩展样式
	::SendMessage (m_hWnd, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, dwStyle);
}

/*******************************************************************

功能:鼠标左键双击,触发在位编辑
参数:系统参数

*******************************************************************/

void CListCtrlEx::OnLButtonDblClk(UINT nFlags, CPoint point) 
{
	int index;
	int colnum;

	//确保用户点击了LISTCTRL的正确行和列 
	if( ( index = HitTestEx( point, &colnum )) != -1 )
	{
		UINT flag = LVIS_FOCUSED;//LVIS_SELECTED
		
		// 获取在位编辑的列编号
		curSelCol = colnum;

		//获取焦点的行,可选择在位编辑的列
		if( (GetItemState( index, flag ) & flag) == flag )
		{
			// Add check for LVS_EDITLABELS
			//if( GetWindowLong(m_hWnd, GWL_STYLE) & LVS_EDITLABELS )
		    
			//保证可在位编辑列数不为空
			if(m_editLines.GetSize() > 0)
			{
			    //判断当前点击的列是否为可在位编辑列
				for(int i=0 ; i<m_editLines.GetSize() ; i++)
				{
					//在位编辑指定的项 
					if( colnum == m_editLines.GetAt(i) )
			            EditSubLabel( index, colnum );
				}
			}
		}

		//用户仅仅选择了行,没有双击某一列,不执行在位编辑
		else 
			SetItemState( index, LVIS_SELECTED | LVIS_FOCUSED ,
			    	LVIS_SELECTED | LVIS_FOCUSED); 
	}

	CListCtrl::OnLButtonDblClk(nFlags, point);
}

/*******************************************************************

功能:完成用户对LISTCTRL的修改
参数:系统参数

*******************************************************************/

void CListCtrlEx::OnEndlabeledit(NMHDR* pNMHDR, LRESULT* pResult) 
{
	LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;

	//定义行数据的结构体,并获得用户点击的行
	LV_ITEM	*plvItem = &pDispInfo->item;

	//在位编辑成功后,修改LISTCTRL对应项的文本
	if (plvItem->pszText != NULL)
	{
		SetItemText(plvItem->iItem, plvItem->iSubItem, 
			plvItem->pszText);
	}

	*pResult = 0;
}

/*******************************************************************

功能:测试鼠标左键的点击事件
参数:point--鼠标点击的位置(设备坐标)
      col--鼠标点击的列

*******************************************************************/

int CListCtrlEx::HitTestEx(CPoint &point, int *col)
{
	int colnum = 0;

	//获取用户点击的行
	int row = HitTest( point, NULL );
	
	//初始化用户点击的列为0,即第一列
	if( col )
		*col = 0;

	//确定LISTCTRL的样式为LVS_REPORT
	if( (GetWindowLong(m_hWnd, GWL_STYLE) & LVS_TYPEMASK) != 
		LVS_REPORT )
		return row;

	//获取可见行的范围,即开始行和最后一行
	
	//本页可见的第一行
	row = GetTopIndex();
	
	//本页可见的最后一行
	int bottom = row + GetCountPerPage();
	if( bottom > GetItemCount() )
		bottom = GetItemCount();
	
	//获取LISTCTRL的列数总和
	CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
	int nColumnCount = pHeader->GetItemCount();

	//在可见行中循环
	for( ; row <= bottom ; row++)
	{
		//获取点击行的尺寸范围
		CRect rect;
		GetItemRect( row, &rect, LVIR_BOUNDS );

        //判断鼠标点击是否发生在此行中
		if( rect.PtInRect(point) )
		{
			//循环遍历所有列
			for( colnum = 0; colnum < nColumnCount; colnum++ )
			{
				int colwidth = GetColumnWidth(colnum);
				if( point.x >= rect.left 
					&& point.x <= (rect.left + colwidth ) )
				{
					if( col ) *col = colnum;
					return row;
				}
				rect.left += colwidth;
			}
		}
	}

	//用户没点击任何行和列,返回此值
	return -1; 
}

/*******************************************************************

功能:使LISTCTRL的一项可以在位编辑
参数:nItem--在位编辑项的行
      nCol--在位编辑项的列

*******************************************************************/

CFlatEdit* CListCtrlEx::EditSubLabel(int nItem, int nCol)
{
	//保证在位编辑项可见
	if( !EnsureVisible( nItem, TRUE ) ) 
		return NULL;

	//确定选择列合法
	CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
	int nColumnCount = pHeader->GetItemCount();
	
	//确保选择列在LISTCTRL范围内,且最小的列宽为5
	if( nCol >= nColumnCount || GetColumnWidth(nCol) < 5 )
		return NULL;

	//获取选择列相对于第一列的尺寸偏移
	int offset = 0;
	for( int i = 0; i < nCol; i++ )
		offset += GetColumnWidth( i );

	//计算EDIT的尺寸范围
	CRect rect;
	GetItemRect( nItem, &rect, LVIR_BOUNDS );

	//扩展列
	CRect rcClient;

	//获取对用户可见的EDIT范围
	GetClientRect( &rcClient );
	if( offset + rect.left < 0 || offset + rect.left > rcClient.right )
	{
		CSize size;
		size.cx = offset + rect.left;
		size.cy = 0;

		//向左或右扩展EDIT尺寸
		Scroll( size ); 
		
		rect.left -= size.cx;
	}

	//获取调整尺寸后的列
	LV_COLUMN lvcol;
	lvcol.mask = LVCF_FMT;
	GetColumn( nCol, &lvcol );
	DWORD dwStyle ;

	//确定LISTCTRL中的文本对齐方式和EDIT的相对位置
	if((lvcol.fmt&LVCFMT_JUSTIFYMASK) == LVCFMT_LEFT)
		dwStyle = ES_LEFT;
	else if((lvcol.fmt&LVCFMT_JUSTIFYMASK) == LVCFMT_RIGHT)
		dwStyle = ES_RIGHT;
	else dwStyle = ES_CENTER;
    
	//获取EDIT的真正尺寸
	rect.left += offset+4;
	rect.right = rect.left + GetColumnWidth( nCol ) - 3 ;
	
	// 确保EDIT在LISTCTRL客户区内
	if( rect.right > rcClient.right)
		rect.right = rcClient.right;

	// 设置EDIT的样式
	dwStyle |= WS_BORDER|WS_CHILD|WS_VISIBLE|ES_AUTOHSCROLL;

	//初始化EDIT
	CFlatEdit *pEdit = new CFlatEdit(nItem, nCol, GetItemText( nItem, nCol ));
    
	// 动态创建在位编辑EDIT
	pEdit->Create(dwStyle, rect, this, 1 );

	// 设置EDIT的单个数据标志位
	if(isOneValueInEdit == FALSE)
		pEdit->SetOneValue(FALSE);

	return pEdit;
}

/*******************************************************************

功能:设置LISTCTRL中可在位编辑列的集合
参数:lines--在位编辑列的集合

*******************************************************************/

void CListCtrlEx::SetEditLines(CString lines)
{
	CString mid = lines , temp;
	int pos1 = 0 , pos2 = 0 , num = 0 ;
    
	while( (pos2 = mid.Find("," , pos1) ) != -1 
		&& pos1 < mid.GetLength() )
	{
		//将各可在位编辑的列记录下来
		temp = mid.Mid(pos1 , pos2 - pos1);
		num = atoi(temp);
        m_editLines.Add(num);

		pos1 = pos2 + 1;
	}
}

/*******************************************************************

功能:设置一个单元格存储单个数据的标志
参数:BOOL oneValueInEdit--		标志

*******************************************************************/

void CListCtrlEx::SetOneValueInEdit(BOOL oneValueInEdit)
{
	isOneValueInEdit = oneValueInEdit;
}

⌨️ 快捷键说明

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