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

📄 listctrlex.cpp

📁 List控件的使用,具有可编辑功能,方便的界面配置方法
💻 CPP
字号:
// ListCtrlEx.cpp : implementation file
//

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

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

/////////////////////////////////////////////////////////////////////////////
// CListCtrlEx
//=============================================================================
// 构造函数, 初始化变量
CListCtrlEx::CListCtrlEx()
{
	m_pEdit= NULL;
	m_pCombo = NULL;
	m_pLastCtrl = NULL;
	m_nUsedCtrl = 0;
	m_bShowCtrl =FALSE;
}

//=============================================================================
// 析构函数, 释放程序创建的对象
CListCtrlEx::~CListCtrlEx()
{
	if(m_pEdit)		delete m_pEdit;
	if(m_pCombo)	delete m_pCombo;
}

//=============================================================================
// 控件消息映射
BEGIN_MESSAGE_MAP(CListCtrlEx, CListCtrl)
	//{{AFX_MSG_MAP(CListCtrlEx)
	ON_WM_LBUTTONDOWN()
	ON_WM_KILLFOCUS()
	ON_WM_NCLBUTTONDBLCLK()
	ON_WM_LBUTTONDBLCLK()
	//}}AFX_MSG_MAP
	ON_EN_KILLFOCUS(IDC_INPLACE_EDIT, OnKillfocusEditBox)
	ON_EN_CHANGE(IDC_INPLACE_EDIT, OnChangeEditBox)
	ON_CBN_KILLFOCUS(IDC_INPLACE_COMBO, OnKillfocusCmbBox)
	ON_CBN_SELCHANGE(IDC_INPLACE_COMBO, OnSelchangeCmbBox)

END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CListCtrlEx message handlers
//#############################################################################
// 所有的贴上的控件消息处理

//=============================================================================
// 编辑框失去焦点, 如果内容发生改变, 更新显示并通知父窗口
void CListCtrlEx::OnKillfocusEditBox()
{
	CString newStr;
	m_pEdit->GetWindowText(newStr);
	if(newStr != GetItemText(m_nRow, m_nCol))
	{
		SetItemText(m_nRow,m_nCol,newStr);
		GetParent()->SendMessage(UM_EDITCHANGED, WPARAM(GetDlgCtrlID()), LPARAM(m_nCol));
	}
	m_pEdit->ShowWindow(SW_HIDE);

	Invalidate();
}

//=============================================================================
// 编辑框内容改变
void CListCtrlEx::OnChangeEditBox()
{
}

//=============================================================================
// 组合框失去焦点
void CListCtrlEx::OnKillfocusCmbBox() 
{
	m_pCombo->ShowWindow(SW_HIDE);

	Invalidate();
}

//=============================================================================
// 组合框项选择改变
void CListCtrlEx::OnSelchangeCmbBox()
{
	CString newStr;
	if (m_pCombo)
	{
		m_pCombo->GetLBText(m_pCombo->GetCurSel(),newStr);
		m_strComboOld = GetItemText(m_nRow, m_nCol);
		if(newStr != m_strComboOld)
		{
		SetItemText(m_nRow,m_nCol,newStr);
		GetParent()->SendMessage(UM_SELECTCHANGE, WPARAM(GetDlgCtrlID()), LPARAM(m_nCol));
		}
	}
}

//#############################################################################
// 列表框控件函数

//=============================================================================
// 鼠标左键按下, 即某个单元格被双击(选择)
void CListCtrlEx::OnLButtonDblClk(UINT nFlags, CPoint point) 
{
	CListCtrl::OnLButtonDblClk(nFlags, point);

	// 针对禁止用户选择复选框
	MSG message;
	while( PeekMessage( &message, NULL, 0, 0 ,PM_REMOVE)) 
	{
		TranslateMessage(&message);
		DispatchMessage(&message);
	}
	SelectCell(point);	
}

//=============================================================================
// 鼠标左键按下, 即某个单元格被单击(选择)
void CListCtrlEx::OnLButtonDown(UINT nFlags, CPoint point) 
{
	CListCtrl::OnLButtonDown(nFlags, point);
	MSG message;
	while( PeekMessage( &message, NULL, 0, 0 ,PM_REMOVE)) 
	{
		TranslateMessage(&message);
		DispatchMessage(&message);
	}
	SelectCell(point);	
}

//=============================================================================
// 根据点位置,选中对应的单元格
void CListCtrlEx::SelectCell(CPoint point)
{
	SetFocus();				// 设置列表框获得焦点
	MSG message;			// 分发消息, 让编辑框等附属控件先失去焦点
	while( PeekMessage( &message, NULL, 0, 0 ,PM_REMOVE)) 
	{
		TranslateMessage(&message);
		DispatchMessage(&message);
	}

	if( HitTestEx(point) != -1 )
	{
		if(m_pLastCtrl)
			m_pLastCtrl->ShowWindow(SW_HIDE);
		UINT flag = LVIS_FOCUSED;
		if( (GetItemState( m_nRow, flag ) & flag) == flag && m_nCol > 0)
		{
			// ???
		}
		else
			SetItemState( m_nRow, LVIS_SELECTED | LVIS_FOCUSED , LVIS_SELECTED | LVIS_FOCUSED); 

		GetParent()->SendMessage(UM_CHECKSTATECHANGE, WPARAM(GetDlgCtrlID()), LPARAM(m_nCol)) ;

		ShowCtrl();
	}
}
//=============================================================================
// 外部函数,用来显示某个控件
void CListCtrlEx::ShowCtrl(int nRow, int nCol, CWnd* pCtrl)
{
	if(m_pLastCtrl)
		m_pLastCtrl->ShowWindow(SW_HIDE);
	m_nRow = nRow;
	m_nCol = nCol;
//	SetFocus();
	SetItemState( m_nRow, LVIS_SELECTED | LVIS_FOCUSED , LVIS_SELECTED | LVIS_FOCUSED); 
	
	m_pLastCtrl = pCtrl;
	m_bShowCtrl = TRUE;
	ShowCtrl();	
}

//=============================================================================
// 内部函数, 显示当前控件
void CListCtrlEx::ShowCtrl()
{
	//-----------------------------------------------------------
	// 计算单元格位置
	if( !EnsureVisible( m_nRow, TRUE ) )
		return;			// 确认该行可见
	CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
	int nColumnCount = pHeader->GetItemCount();
	if( m_nCol >= nColumnCount ||GetColumnWidth(m_nCol) < 5 )	// 确认该列有效
		return;
	
	// 获取列的偏移量
	int offset = 0;
	for( int i = 0; i < m_nCol; i++ )
		offset += GetColumnWidth( i );
	
	CRect rect;
	GetItemRect(m_nRow,&rect,LVIR_BOUNDS);
	// Now scroll if we need to expose the column
	CRect rcClient;
	GetClientRect( &rcClient );
	if( offset + rect.left < 0 || offset + rect.left > rcClient.right )
	{
		CSize size;
		size.cx = offset + rect.left;
		size.cy = 0;
		Scroll( size );
		rect.left -= size.cx;
	}
	
	rect.left += offset;
	rect.right = rect.left + GetColumnWidth( m_nCol )  ;
	int n=0;
	rect.top -= n;
	rect.bottom -= n;
	
	if( rect.right > rcClient.right) rect.right = rcClient.right;
	if(m_bShowCtrl)
	{
		if(m_pEdit)
		{
			m_pEdit->SetMargins(4,4);
		}
		if( m_pLastCtrl == m_pCombo)
		{
			rect.left += 2;
			//rect.right -= 4;
			n=1;
			rect.top -= n-1;
			rect.bottom -= n;
		}
		
		m_pLastCtrl->MoveWindow(rect);
		m_pLastCtrl->ShowWindow(SW_SHOW);
		if( m_pLastCtrl == m_pEdit)
		{
			m_pEdit->SetSel(0,-1);
			m_pEdit->SetFocus();
		}
		if( m_pLastCtrl == m_pCombo)
		{
			m_pCombo->SetItemHeight(-1,rect.Height()-3);
			m_pCombo->SetItemHeight(0,rect.Height()+2);
		}
		
	}
}

//=============================================================================
//根据point值,判断point所在行和列:
int CListCtrlEx::HitTestEx(CPoint point)
{
//	m_nRow = 0;			// 获取所在的行
//	m_nCol =0;
//	return 0;
	m_nRow = HitTest( point,NULL );			// 获取所在的行
	m_nCol =0;
	
	// 只有在风格为LVS_REPORT时才处理
	if( (GetWindowLong(m_hWnd, GWL_STYLE) & LVS_TYPEMASK) != LVS_REPORT )
		return m_nRow;

	// 获取当前可见的顶行和末行
	m_nRow = GetTopIndex();
	int bottom = m_nRow + GetCountPerPage();
	if( bottom > GetItemCount() )
		bottom = GetItemCount();
	
	// 获取列数
	CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
	int nColumnCount = pHeader->GetItemCount();

	// 循环处理所有可见的行
	for( ;m_nRow <=bottom;m_nRow++)
	{
		// 获取每行绑定的单元格,并判断鼠标点是否落在某行上
		CRect rect;
		GetItemRect( m_nRow, &rect, LVIR_BOUNDS );
		if( rect.PtInRect(point) )
		{	// 如果鼠标点落在本行内
			// 循环所有列,判断鼠标点落在哪列内
			for(int column = 0; column < nColumnCount; column++ )
			{
				int colwidth = GetColumnWidth(column);
				if( point.x >= rect.left && point.x <= (rect.left + colwidth ) )
				{
					m_nCol =column;
					CString tp;
					return m_nRow;
				}
				rect.left += colwidth;
			}
		}
	}
	m_nCol = -1;
	return -1;
}

//=============================================================================
// 设置使用的控件种类
void CListCtrlEx::SetUsedCtrl(int nUsedCtrl)
{
	m_nUsedCtrl = nUsedCtrl;
	CRect rect(0,0,10,200);

	//---------------------------------------------------------------
	// 如果使用编辑控件
	if(nUsedCtrl&USED_CTRL_EDIT == USED_CTRL_EDIT)
	{
		m_pEdit = new CEdit();
		m_pEdit->Create(WS_CHILD|WS_BORDER|ES_AUTOHSCROLL,rect,this,IDC_INPLACE_EDIT );
		m_pEdit->SetFont(GetFont());
	}

	//---------------------------------------------------------------
	// 如果使用组合框控件
	if((nUsedCtrl&USED_CTRL_COMBO) == USED_CTRL_COMBO)
	{
		m_pCombo = new CComboBox();
		m_pCombo->Create(WS_CHILD|WS_VSCROLL|CBS_DROPDOWNLIST|CBS_AUTOHSCROLL,\
			rect,this,IDC_INPLACE_COMBO );
		int n=GetItemRect(0,&rect,LVIR_BOUNDS );
		m_pCombo->SetFont(GetFont());
	}
}

//=============================================================================
// 列表控件失去焦点时
void CListCtrlEx::OnKillFocus(CWnd* pNewWnd) 
{
	CListCtrl::OnKillFocus(pNewWnd);
	
	//---------------------------------------------------------------
	// 列表框控件真正失去焦点时,隐藏上次使用的贴上的控件(如果有的话)
	if(m_pLastCtrl)
	{
		if(m_pLastCtrl->GetFocus() != m_pLastCtrl)	
		{	//列表框控件失去的焦点不是由贴上的控件获取焦点引起
			m_pLastCtrl->ShowWindow(SW_HIDE);
		}
	}
}


void CListCtrlEx::OnNcLButtonDblClk(UINT nHitTest, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
//	MessageBox("ffdsafdsjkda;");
	
	CListCtrl::OnNcLButtonDblClk(nHitTest, point);
}

⌨️ 快捷键说明

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