MFC——LIstCtrl中嵌入Edit和Combobox控件

在MFC中经常会使用到ListCtrl控件,并且在控件中可以对单元格进行Edit的编辑或者ComboBox的编辑。实现ListCtrl中用edit和combobox编辑并数据同步,下面就是我用到的这个功能的简单实例。


为了让ListCtrol能更好的为我们所用,我们创建一个CEditListCtrl类继承自CListCtrl:


EditListCtrl.h

#pragma once
#include "ListEdit.h"
#include "ListComboBox.h"
#include "_PersistAttriMapXML.h"

#define  IDC_CELL_EDIT		0xffe0
#define  IDC_CELL_COMBOBOX	0xffe1

// CEditListCtrl

class CEditListCtrl : public CListCtrl
{
	DECLARE_DYNAMIC(CEditListCtrl)

public:
	CEditListCtrl();
	virtual ~CEditListCtrl();

protected:
	DECLARE_MESSAGE_MAP()

private:
	CListEdit m_edit;
	CListComboBox m_comboBox;
	int m_nRow; //行
	int m_nCol; //列

public:

	// 当编辑完成后同步数据
	void DisposeEdit(void);

	//发送失效消息
	void SendInvalidateMsg();

	// 设置当前窗口的风格
	void SetStyle(void);
	afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
	afx_msg void OnCbnSelchangeCbCellComboBox();

	afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
	afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
};


EditListCtrl.cpp

// EditListCtrl.cpp : implementation file
//

#include "stdafx.h"
#include "CADIPlatform.h"
#include "EditListCtrl.h"
#include "CodeDBHelper.h"
#include "PersistXmlParser.h"

// CEditListCtrl

IMPLEMENT_DYNAMIC(CEditListCtrl, CListCtrl)

CEditListCtrl::CEditListCtrl()
{

}

CEditListCtrl::~CEditListCtrl()
{
}


BEGIN_MESSAGE_MAP(CEditListCtrl, CListCtrl)
	ON_WM_LBUTTONDBLCLK()
	ON_CBN_SELCHANGE(IDC_CELL_COMBOBOX, &CEditListCtrl::OnCbnSelchangeCbCellComboBox)
	ON_WM_HSCROLL()
	ON_WM_VSCROLL()
END_MESSAGE_MAP()



// CEditListCtrl message handlers

// 当编辑完成后同步数据
void CEditListCtrl::DisposeEdit(void)
{
	int nIndex = GetSelectionMark();
	//同步更新处理数据
	CString sLable;
	_PersistItem* pPersistItem = (_PersistItem*)GetItemData(m_nRow);
	if(NULL == pPersistItem) return ;

	if(0 == m_nCol) //edit控件
	{
		CString szLable;
		m_edit.GetWindowText(szLable);
		SetItemText(m_nRow,m_nCol,szLable);
		pPersistItem->szPersistence = szLable;

		m_edit.ShowWindow(SW_HIDE);
	}
	else if((1 == m_nCol) || (2 == m_nCol))
	{
		m_comboBox.ShowWindow(SW_HIDE);
	}

}

// 设置当前窗口的风格
void CEditListCtrl::SetStyle(void)
{
	LONG lStyle;
	lStyle = GetWindowLong(m_hWnd,GWL_STYLE);
	lStyle &= ~LVS_TYPEMASK; //清除显示方式
	lStyle |= LVS_REPORT; //list模式
	lStyle |= LVS_SINGLESEL; //单选
	SetWindowLong(m_hWnd,GWL_STYLE,lStyle);

	//扩展模式
	DWORD dwStyle = GetExtendedStyle();
	dwStyle |= LVS_EX_FULLROWSELECT; //选中某行使其整行高亮
	dwStyle |= LVS_EX_GRIDLINES; //网格线
	SetExtendedStyle(dwStyle); //设置扩展风格
}

void CEditListCtrl::OnLButtonDblClk(UINT nFlags, CPoint point)
{
	// TODO: Add your message handler code here and/or call default
	CListCtrl::OnLButtonDblClk(nFlags, point);

	LVHITTESTINFO info;
	info.pt = point;
	info.flags = LVHT_ONITEMLABEL;

	if(SubItemHitTest(&info) >= 0)
	{
		m_nRow = info.iItem;
		m_nCol = info.iSubItem;

		CRect rect;
		GetSubItemRect(m_nRow,m_nCol,LVIR_LABEL,rect);

		CString strValue;
		strValue = GetItemText(m_nRow,m_nCol);

		_PersistItem* pPersistItem = (_PersistItem*)GetItemData(m_nRow);
		if(NULL == pPersistItem) return ;
		//Edit单元格
		if((0 == m_nCol))
		{
			if(pPersistItem->nFlag & 0x01)
			{
				MB_PROMPT(RES_LOAD_STRING(IDS_ST_MODIFIYPKATTRI_20170502_01));
				return ;
			}

			if(NULL == m_edit)
			{
				//创建Edit控件
				// ES_WANTRETURN 使多行编辑器接收回车键输入并换行。如果不指定该风格,按回车键会选择缺省的命令按钮,这往往会导致对话框的关闭。
				m_edit.Create(WS_CHILD|WS_BORDER|ES_AUTOHSCROLL|ES_WANTRETURN|ES_LEFT,
					CRect(0,0,0,0),this,IDC_CELL_EDIT);
			}
			m_edit.MoveWindow(rect);
			m_edit.SetWindowText(strValue);
			m_edit.ShowWindow(SW_SHOW);
			m_edit.SetSel(0,-1);
			m_edit.SetFocus();
			UpdateWindow();
		}
		//ComboBox单元格
		if((1 == m_nCol))
		{
			if(NULL == m_comboBox)
			{
				//创建Combobox控件
				//CBS_DROPDOWNLIST : 下拉式组合框,但是输入框内不能进行输入
				//WS_CLIPCHILDREN  :  其含义就是,父窗口不对子窗口区域进行绘制。默认情况下父窗口会对子窗口背景是进行绘制的,但是如果父窗口设置了WS_CLIPCHILDREN属性,父亲窗口不在对子窗口背景绘制.
				m_comboBox.Create(WS_CHILD|WS_VISIBLE|CBS_SORT|WS_BORDER|CBS_DROPDOWNLIST|WS_VSCROLL|WS_TABSTOP|CBS_AUTOHSCROLL,
					CRect(0,0,0,0),this,IDC_CELL_COMBOBOX);
			}
			m_comboBox.MoveWindow(rect);

			m_comboBox.ShowWindow(SW_SHOW);
			//TODO comboBox 初始化
			LoadPlmAttri();
			//当前cell的值
			CString strCellValue = GetItemText(m_nRow,m_nCol);
			int nIndex = m_comboBox.FindStringExact(0,strCellValue);
			if(CB_ERR == nIndex)
				m_comboBox.SetCurSel(0); //TODO 设置为当前值的Item
			else
				m_comboBox.SetCurSel(nIndex);		
			
			m_comboBox.SetFocus();
			UpdateWindow();
		}
	}
}


void CEditListCtrl::OnCbnSelchangeCbCellComboBox()
{
	//同步更新处理数据
	_PersistItem* pPersistItem = (_PersistItem*)GetItemData(m_nRow);
	if(NULL == pPersistItem) return ;

	if(1 == m_nCol) //combobox控件
	{
		CString szLable;
		int nindex = m_comboBox.GetCurSel();
		m_comboBox.GetLBText(nindex,szLable);
		ATTRIFIELD* pAttriField = (ATTRIFIELD*)m_comboBox.GetItemData(nindex);
		if(NULL == pAttriField)
			return ;

		//持久化的处理
		if(0 == pAttriField->szComment.CompareNoCase(ATTRIBUTE_PERSISTENCE))
		{
			pPersistItem->szPersistence=pAttriField->mapPersistenceValue[ATTRIBUTE_VALUE];
			SetItemText(m_nRow,m_nCol-1,pPersistItem->szPersistence);
		}

		pPersistItem->szUcProperty = pAttriField->szPLMToXML;
		pPersistItem->szXmlOption = pAttriField->szXMLOpention;
		SetItemText(m_nRow,m_nCol,pAttriField->szDetail);		
		m_comboBox.ShowWindow(SW_HIDE);		
	}
}

//发送失效消息
void CEditListCtrl::SendInvalidateMsg()
{
	//Edit单元格
	if((0 == m_nCol))
	{

		if(NULL == m_edit.m_hWnd) return ;
		BOOL bShow = m_edit.IsWindowVisible();
		if(bShow)
			::SendMessage(m_edit.m_hWnd,WM_KILLFOCUS,(WPARAM)0,(LPARAM)0);

	}
	else if((1 == m_nCol)) //combobox
	{
		if(NULL == m_comboBox.m_hWnd) return ;

		BOOL bShow = m_comboBox.IsWindowVisible();
		if(bShow)
			::SendMessage(m_comboBox.m_hWnd,WM_KILLFOCUS,(WPARAM)0,(LPARAM)0);
	}
}

void CEditListCtrl::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
	SendInvalidateMsg();

	CListCtrl::OnHScroll(nSBCode, nPos, pScrollBar);
}

void CEditListCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
	SendInvalidateMsg();

	CListCtrl::OnVScroll(nSBCode, nPos, pScrollBar);
}



CEditListCtrl 类是一个控件类在一个dialog容器中动态创建:

	RECT listRect;   
	GetDlgItem(IDC_ST_LISTGROUP)->GetWindowRect(&listRect);  //获取List控件所在位位置,用Group占位
	ScreenToClient(&listRect);

	m_list.Create(WS_CHILD|WS_BORDER|LVS_SINGLESEL|LVS_REPORT,listRect,this,IDC_EDIT_LIST);
	m_list.SetExtendedStyle(LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES|LVS_EX_UNDERLINEHOT);
	m_list.ShowWindow(SW_SHOW);
		RECT rect;
	m_list.GetClientRect(&rect);
	
	m_list.InsertColumn(0,FirstColName,LVCFMT_LEFT,rect.right/2);
	m_list.InsertColumn(1,SecondColName,LVCFMT_LEFT,rect.right/2);    
 

这样就动态的创建了一个listctrl

接下来 我们继续完善 ListCtrl中的Edit 和Combobox的创建

在上面CEditListCtrl 中有两个成员变量 分别是  m_edit 和m_comboBox。 这两个成员变量是我们自顶一个 Edit 和ComboBox

ListEdit.h

#pragma once


// CListEdit

class CListEdit : public CEdit
{
	DECLARE_DYNAMIC(CListEdit)

public:
	CListEdit();
	virtual ~CListEdit();

protected:
	DECLARE_MESSAGE_MAP()
public:
	afx_msg void OnKillFocus(CWnd* pNewWnd);
protected:
	virtual void PreSubclassWindow();
};


ListEdit.cpp

// ListEdit.cpp : implementation file
//

#include "stdafx.h"
#include "CADIPlatform.h"
#include "ListEdit.h"
#include "EditListCtrl.h"


// CListEdit

IMPLEMENT_DYNAMIC(CListEdit, CEdit)

CListEdit::CListEdit()
{

}

CListEdit::~CListEdit()
{
}


BEGIN_MESSAGE_MAP(CListEdit, CEdit)
	ON_WM_KILLFOCUS()
END_MESSAGE_MAP()



// CListEdit message handlers



void CListEdit::OnKillFocus(CWnd* pNewWnd)
{
	CEdit::OnKillFocus(pNewWnd);

	//ShowWindow(SW_HIDE);
	CEditListCtrl* temp = (CEditListCtrl*)GetParent();
	temp->DisposeEdit();

}

void CListEdit::PreSubclassWindow()
{
	// TODO: Add your specialized code here and/or call the base class

	CEdit::PreSubclassWindow();
}

ListComboBox.h

#pragma once


// CListComboBox

class CListComboBox : public CComboBox
{
	DECLARE_DYNAMIC(CListComboBox)

public:
	CListComboBox();
	virtual ~CListComboBox();

protected:
	DECLARE_MESSAGE_MAP()
public:
	afx_msg void OnKillFocus(CWnd* pNewWnd);
	afx_msg void OnCbnDropdown();
};



ListComboBox.cpp

// ListComboBox.cpp : implementation file
//

#include "stdafx.h"
#include "CADIPlatform.h"
#include "ListComboBox.h"
#include "EditListCtrl.h"


// CListComboBox

IMPLEMENT_DYNAMIC(CListComboBox, CComboBox)

CListComboBox::CListComboBox()
{

}

CListComboBox::~CListComboBox()
{
}


BEGIN_MESSAGE_MAP(CListComboBox, CComboBox)
	ON_WM_KILLFOCUS()
	ON_CONTROL_REFLECT(CBN_DROPDOWN, &CListComboBox::OnCbnDropdown)
END_MESSAGE_MAP()



// CListComboBox message handlers

void CListComboBox::OnKillFocus(CWnd* pNewWnd)
{
	CComboBox::OnKillFocus(pNewWnd);
	//ShowWindow(SW_HIDE);

	CEditListCtrl *temp = (CEditListCtrl*)GetParent();
	temp->DisposeEdit(); //调用父窗口的DisposeEdit()函数
}

void CListComboBox::OnCbnDropdown()
{
	CClientDC dc(this);
	int nTotalHeight = 0;
	//获取字体信息
	dc.SelectObject(GetFont());
	//获取当前item的个数
	int nCount = GetCount();
	if(nCount <= 0) return ;
	//获取字体的高度
	CString strLable=_T("");
	GetLBText(GetCurSel(),strLable);
	int nHeight = dc.GetTextExtent(strLable).cy;

	//组合框高度
	CRect rect;
	GetWindowRect(rect);
	int height = rect.Height();

	if(nCount>30)
		nTotalHeight = 30*nHeight + height;
	else
		nTotalHeight = nCount*nHeight + height;

	//设置下拉的高度
	CRect rc;
	GetClientRect(&rc);
	SetWindowPos(NULL,0,0,rc.Width(),rc.Height()+nTotalHeight,SWP_NOZORDER|SWP_NOMOVE|SWP_SHOWWINDOW);
}


在这两个控件中  OnKillFocus 用来让控件失去焦点后的数据同步。

combobox中 CBN_DROPDOWN 消息用来处理计算下拉框的的高度。


到这里简单实例已经完成。 谢谢!

  • 6
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值