MFC列表框控件的动态编辑

在我们进行mfc 编程时,我们需要用到列表框显示各层或各物体的参数设置,同时也希望能编辑其参数。我以前在网上查找,用了CComboListCtrl,这需要3个cpp 和 h 文件,用起来还不容易。

最近看到一个文章 https://blog.csdn.net/qingyang8513/article/details/50986455 ,这个直接用 listctrl 和 一个Edit 控件,很简单。所以我也测试一下,并记录在此。

运行效果如下,点击一处列表框里内容即可编辑,但我剪辑图时剪辑不到编辑状态。

我的运行环境是vc2010,下面开始讲解过程:

重点内容:

      1)List Control控件NM_DCLICK消息响应事件;

      2)Edit Control的KillFocus消息响应;

      3)Edit Control的动态显示及隐藏;

      4)List Control获取指定行和列的编号,并获取指定行和列的内容及修改赋值。

操作:

1、创建基于对话框的MFC应用程序,删除原有的静态文本;

2、添加一个List Control控件和一个Edit Control控件,并分别关联控制变量m_ListTem和m_EditTest(List Control控件适当调整大小,Edit Control大小不用调整);

3、初始化对话框函数OnInitDialog中实现List Control控件和Edit Control控件的初始化,    InitList();    UpdateList();

代码如下:

BOOL CListCtrlTestDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon

	// TODO: Add extra initialization here
	InitList();
	UpdateList();

	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CListCtrlTestDlg::InitList(void)
{
	Clayer layer={"zhang",1.3,15.6,88};
	m_layer.push_back(layer);
	Clayer  layer1={"Li",22.3,25.6,288};
	m_layer.push_back(layer1);
	Clayer layer2={"Wang",32.33,35.6,388};
	m_layer.push_back(layer2);

	m_EditTest.ShowWindow(SW_HIDE);
	CRect rect;
	m_ListTem.GetClientRect(&rect);
	int iLength = rect.Width();
	m_ListTem.SetExtendedStyle(m_ListTem.GetExtendedStyle() | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
	m_ListTem.InsertColumn(0, _T("编号"), LVCFMT_CENTER, 40);
	m_ListTem.InsertColumn(1, _T("名字"), LVCFMT_CENTER, 80);
	m_ListTem.InsertColumn(2, _T("x"), LVCFMT_CENTER, (iLength - 120)/3);
	m_ListTem.InsertColumn(3, _T("y"), LVCFMT_CENTER, (iLength - 120)/3);
	m_ListTem.InsertColumn(4, _T("旋转角度"), LVCFMT_CENTER, (iLength - 120)/3);


}

void CListCtrlTestDlg::UpdateList(void)
{

	CString index,x,y,z,name,count,rotate,blocks;
	while(m_ListTem.GetItemCount()>0)
		m_ListTem.DeleteItem(0);
	for(int i=0;i<m_layer.size();i++)
	{
	
		index.Format("%d",i);
		Clayer& layer=m_layer[i];
		name=layer.name;
		x.Format("%.2f",layer.x);
		y.Format("%.2f",layer.y);
		count.Format("%d",layer.count);


		m_ListTem.InsertItem(i,index);

		m_ListTem.SetItemText(i,1,name);
		m_ListTem.SetItemText(i,2,x);
		m_ListTem.SetItemText(i,3,y);
		m_ListTem.SetItemText(i,4,count);
	}
}

在h 文件中定义层参数结构,并定义层参数向量m_layer.

typedef struct {CString name;float x;float y;int count;} Clayer;

std::vector<Clayer> m_layer;

有上面,上面代码才不报错。这里完成了初始显示,应该可以得到开头的效果,但不能编辑。

动态编辑的核心

4、对话框头文件中添加int型变量m_Row和m_Col,用于保存双击时选中的行和列号,并初始化为-1(未选中状态);

5、为List Control控件添加NM_DBLCLK消息响应,并添加代码如下:

void CListCtrlTestDlg::OnDblclkList2(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
	// TODO: Add your control notification handler code here
		CRect rc;
	CString strTemp;
	NM_LISTVIEW *pNMListView = (NM_LISTVIEW *)pNMHDR;
	m_Row = pNMListView->iItem;
	m_Col = pNMListView->iSubItem;
 
	if (pNMListView->iItem == -1)	//选择空白处
		return;
 
	if (m_Col != 0)	// 选择子项
	{
		m_ListTem.GetSubItemRect(m_Row, m_Col, LVIR_LABEL, rc);
		m_EditTest.SetParent(&m_ListTem);
		m_EditTest.MoveWindow(rc);
		m_EditTest.SetWindowText(m_ListTem.GetItemText(m_Row, m_Col));
		m_EditTest.ShowWindow(SW_SHOW);
		m_EditTest.SetFocus();//设置Edit焦点
		m_EditTest.ShowCaret();//显示光标
		m_EditTest.SetSel(0, -1);//全选
	}

	*pResult = 0;
}

6、为Edit Control控件添加EN_KILLFOCUS消息响应,并添加代码如下:

void CListCtrlTestDlg::OnKillfocusEdit1()
{
	// TODO: Add your control notification handler code here
	CString str;
	m_EditTest.GetWindowText(str);
	m_ListTem.SetItemText(m_Row, m_Col, str);
    //这里其实应该保存编辑结果,简化了,实际程序要有改变参数
	m_EditTest.ShowWindow(SW_HIDE);
}

现在可以编译运行并测试程序了,应该就是我们开头的结果。

改进

输入完数据后,一般希望回车,就生效,可实际情况是要离开才生效,有点操作不方便。

编辑框怎么相应回车呢?

类精灵CListCtrlTestDlg里转到 Virtual function,点击添加 PreTranslateMessage

编辑PreTranslateMessage函数如下:

BOOL CListCtrlTestDlg::PreTranslateMessage(MSG* pMsg)
{
	 if (WM_KEYDOWN ==pMsg->message && VK_RETURN == pMsg->wParam)
	 {
		 if (m_EditTest.IsWindowVisible())
		{
			m_EditTest.ShowWindow(SW_HIDE);
			return TRUE;
		}
	 }
	return CDialogEx::PreTranslateMessage(pMsg);
}

这段代码的含义是:在按下回车键时, 如果编辑框是可见的,就让编辑框不显示。编辑框不显示就触发EN_KILLFOCUS消息。达到回车就保存的目的。

发布了131 篇原创文章 · 获赞 112 · 访问量 19万+

猜你喜欢

转载自blog.csdn.net/leon_zeng0/article/details/100696108