MFC List Control控件添加单元格编辑和单元格下拉列表项以适用于数据库相关操作

作为现代的软件,往往是连着数据库的,而连着和用户方便地操作之间,还有着界面这道坎。MFC是Windows上比较好开发用户界面的框架,然而其自带的控件中没有对于数据库表格支持较好的控件,而使用网上提到的 DataGrid 等控件在本人的win8.1+VS2013平台上老出现找不到控件或者头文件的问题,搞的烦死人。最后想到 List Control 控件只要稍作修改,加上单元格编辑和单元格下拉列表,其实就能和数据库进行良好的对接,一百度,果然有人已经做了这件事,实在是太让人感动了!

       下面将介绍一下如何实现上面提到的这两个功能,由于是参考别人的,如果想看原文:请点击这里。至于跟原文最大的不同,我想是我把流程操作尽我所能写的详细,并最大化的简化代码,最后顺带加上一些本人觉得能给数据库操作带来方便的功能的实现方法上去。

OK,下面我们先来看单元格编辑框的添加吧。其实实现的原理很简单,就是在点击到列表相应单元格的时候,在相应的位置生成一个跟单元格大小相当的编辑框并贴在列表框单元格上面而已。

实现如下:

在对话框类声明中添加如下变量和函数:

int e_Item;    //刚编辑的行  
int e_SubItem; //刚编辑的列  

CEdit m_Edit;  //生成单元编辑框对象
bool haveeditcreate;//标志编辑框已经被创建
void createEdit(NM_LISTVIEW  *pEditCtrl, CEdit *createdit, int &Item, int &SubItem, bool &havecreat);//创建单元格编辑框函数
void distroyEdit(CListCtrl *list, CEdit* distroyedit, int &Item, int &SubItem);//销毁单元格编辑框对象

CComboBox m_comBox;//生产单元格下拉列表对象
bool haveccomboboxcreate;//标志下拉列表框已经被创建
void createCcombobox(NM_LISTVIEW  *pEditCtrl, CComboBox *createccomboboxobj, int &Item, int &SubItem, bool &havecreat);//创建单元格下拉列表框函数
void distroyCcombobox(CListCtrl *list, CComboBox* distroyccomboboxobj, int &Item, int &SubItem);//销毁单元格下拉列表框

在对话框的初始化函数OnInitDialog()中添加初始化代码如下:

haveeditcreate = false;//初始化标志位,表示还没有创建编辑框
haveccomboboxcreate = false;//初始化标志位,表示还没有创建下拉列表框
RECT  m_rect;
m_list.GetClientRect(&m_rect); //获取list的客户区,方便调节每一列的宽度
m_list.SetExtendedStyle(LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT); //设置list风格,LVS_EX_GRIDLINES为网格线(只适用与report风格的listctrl)
																	  //LVS_EX_FULLROWSELECT为选中某行使整行高亮(只适用与report风格的listctrl)
m_list.InsertColumn(0, _T("学号"), LVCFMT_LEFT, m_rect.right / 4);
m_list.InsertColumn(1, _T("姓名"), LVCFMT_LEFT, m_rect.right / 4);
m_list.InsertColumn(2, _T("性别"), LVCFMT_LEFT, m_rect.right / 4);
m_list.InsertColumn(3, _T("班级"), LVCFMT_LEFT, m_rect.right / 4);

m_list.InsertItem(0, _T("09090901"));//添加第一个学生数据
m_list.SetItemText(0, 1, _T("小李"));
m_list.SetItemText(0, 2, _T("男"));
m_list.SetItemText(0, 3, _T("计科0901"));

m_list.InsertItem(1, _T("09090902"));//添加第二个学生数据
m_list.SetItemText(1, 1, _T("小王"));
m_list.SetItemText(1, 2, _T("男"));
m_list.SetItemText(1, 3, _T("计科0902"));

为列表框添加单击响应函数:

void CNephoVisionDatabaseDlg::OnNMClickListStudentdata(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
	NM_LISTVIEW  *pEditCtrl = (NM_LISTVIEW *)pNMHDR;
	printf("行:%d,列:%d\n", pEditCtrl->iItem, pEditCtrl->iSubItem);
	if (pEditCtrl->iItem==-1)//点击到非工作区
	{
		if (haveeditcreate == true)//如果之前创建了编辑框就销毁掉
		{
			distroyEdit(&m_list, &m_Edit, e_Item, e_SubItem);//销毁单元格编辑框对象
			haveeditcreate = false;
		}
		if (haveccomboboxcreate == true)//如果之前创建了下拉列表框就销毁掉
		{
			distroyCcombobox(&m_list, &m_comBox, e_Item, e_SubItem);
			haveccomboboxcreate = false;
		}
	}
	else if (pEditCtrl->iSubItem != 2)//如果不是性别选项
	{
		if (haveccomboboxcreate == true)//如果之前创建了编辑框就销毁掉
		{
			distroyCcombobox(&m_list, &m_comBox, e_Item, e_SubItem);
			haveccomboboxcreate = false;
		}
		if (haveeditcreate == true)
		{
			if (!(e_Item == pEditCtrl->iItem && e_SubItem == pEditCtrl->iSubItem))//如果点中的单元格不是之前创建好的
			{
				distroyEdit(&m_list, &m_Edit, e_Item, e_SubItem);
				haveeditcreate = false;
				createEdit(pEditCtrl, &m_Edit, e_Item, e_SubItem, haveeditcreate);//创建编辑框
			}
			else//点中的单元格是之前创建好的
			{
				m_Edit.SetFocus();//设置为焦点
			}
		}
		else
		{
			e_Item = pEditCtrl->iItem;//将点中的单元格的行赋值给“刚编辑过的行”以便后期处理
			e_SubItem = pEditCtrl->iSubItem;//将点中的单元格的行赋值给“刚编辑过的行”以便后期处理
			createEdit(pEditCtrl, &m_Edit, e_Item, e_SubItem, haveeditcreate);//创建编辑框
		}
	}
	else//如果是性别选项,在单元格处生成下拉列表项
	{
		if (haveeditcreate == true)//如果之前创建了编辑框就销毁掉
		{
			distroyEdit(&m_list, &m_Edit, e_Item, e_SubItem);
			haveeditcreate = false;
		}
		if (haveccomboboxcreate == true)
		{
			if (!(e_Item == pEditCtrl->iItem && e_SubItem == pEditCtrl->iSubItem))//如果点中的单元格不是之前创建好的
			{
				distroyCcombobox(&m_list, &m_comBox, e_Item, e_SubItem);
				haveccomboboxcreate = false;
				createCcombobox(pEditCtrl, &m_comBox, e_Item, e_SubItem, haveccomboboxcreate);//创建编辑框
				m_comBox.AddString(L"男");
				m_comBox.AddString(L"女");
				m_comBox.ShowDropDown();//自动下拉
			}
			else//点中的单元格是之前创建好的
			{
				m_comBox.SetFocus();//设置为焦点
			}
		}
		else
		{
			e_Item = pEditCtrl->iItem;//将点中的单元格的行赋值给“刚编辑过的行”以便后期处理
			e_SubItem = pEditCtrl->iSubItem;//将点中的单元格的行赋值给“刚编辑过的行”以便后期处理
			createCcombobox(pEditCtrl, &m_comBox, e_Item, e_SubItem, haveccomboboxcreate);//创建编辑框
			m_comBox.AddString(L"男");
			m_comBox.AddString(L"女");
			m_comBox.ShowDropDown();//自动下拉
		}
	}
	*pResult = 0;
}

写创建与销毁单元格编辑框和下拉列表框函数的实现:

void CNephoVisionDatabaseDlg::createEdit(NM_LISTVIEW  *pEditCtrl, CEdit *createdit, int &Item, int &SubItem, bool &havecreat)//创建单元格编辑框函数
																				//pEditCtrl为列表对象指针,createdit为编辑框指针对象,
																				//Item为创建单元格在列表中的行,SubItem则为列,havecreat为对象创建标准
{
	Item = pEditCtrl->iItem;//将点中的单元格的行赋值给“刚编辑过的行”以便后期处理
	SubItem = pEditCtrl->iSubItem;//将点中的单元格的行赋值给“刚编辑过的行”以便后期处理
	createdit->Create(ES_AUTOHSCROLL | WS_CHILD | ES_LEFT | ES_WANTRETURN,
		CRect(0, 0, 0, 0), this, IDC_EDIT_CREATEID);//创建编辑框对象,IDC_EDIT_CREATEID为控件ID号3000,在文章开头定义
	havecreat = true;
	createdit->SetFont(this->GetFont(), FALSE);//设置字体,不设置这里的话上面的字会很突兀的感觉
	createdit->SetParent(&m_list);//将list control设置为父窗口,生成的Edit才能正确定位,这个也很重要
	CRect  EditRect;
	m_list.GetSubItemRect(e_Item, e_SubItem, LVIR_LABEL, EditRect);//获取单元格的空间位置信息
	EditRect.SetRect(EditRect.left+1, EditRect.top+1, EditRect.left + m_list.GetColumnWidth(e_SubItem)-1, EditRect.bottom-1);//+1和-1可以让编辑框不至于挡住列表框中的网格线
	CString strItem = m_list.GetItemText(e_Item, e_SubItem);//获得相应单元格字符
	createdit->SetWindowText(strItem);//将单元格字符显示在编辑框上
	createdit->MoveWindow(&EditRect);//将编辑框位置放在相应单元格上
	createdit->ShowWindow(SW_SHOW);//显示编辑框在单元格上面
	createdit->SetFocus();//设置为焦点
	createdit->SetSel(-1);//设置光标在文本框文字的最后
}

void CNephoVisionDatabaseDlg::distroyEdit(CListCtrl *list,CEdit* distroyedit, int &Item, int &SubItem)
{
	CString meditdata;
	distroyedit->GetWindowTextW(meditdata);
	list->SetItemText(Item, SubItem, meditdata);//获得相应单元格字符
	distroyedit->DestroyWindow();//销毁对象,有创建就要有销毁,不然会报错
}

void CNephoVisionDatabaseDlg::createCcombobox(NM_LISTVIEW  *pEditCtrl, CComboBox *createccomboboxobj, int &Item, int &SubItem, bool &havecreat)//创建单元格下拉列表框函数
//pEditCtrl为列表对象指针,createccombobox为下拉列表框指针对象,
//Item为创建单元格在列表中的行,SubItem则为列,havecreat为对象创建标准
{
	Item = pEditCtrl->iItem;//将点中的单元格的行赋值给“刚编辑过的行”以便后期处理
	SubItem = pEditCtrl->iSubItem;//将点中的单元格的行赋值给“刚编辑过的行”以便后期处理
	havecreat = true;
	createccomboboxobj->Create(WS_CHILD | WS_VISIBLE |  CBS_DROPDOWN | CBS_OEMCONVERT, CRect(0, 0, 0, 0), this, IDC_COMBOX_CREATEID);
	createccomboboxobj->SetFont(this->GetFont(), FALSE);//设置字体,不设置这里的话上面的字会很突兀的感觉
	createccomboboxobj->SetParent(&m_list);//将list control设置为父窗口,生成的Ccombobox才能正确定位,这个也很重要
	CRect  EditRect;
	m_list.GetSubItemRect(e_Item, e_SubItem, LVIR_LABEL, EditRect);//获取单元格的空间位置信息
	EditRect.SetRect(EditRect.left + 1, EditRect.top + 1, EditRect.left + m_list.GetColumnWidth(e_SubItem) - 1, EditRect.bottom - 1);//+1和-1可以让编辑框不至于挡住列表框中的网格线
	CString strItem = m_list.GetItemText(e_Item, e_SubItem);//获得相应单元格字符
	createccomboboxobj->SetWindowText(strItem);//将单元格字符显示在编辑框上
	createccomboboxobj->MoveWindow(&EditRect);//将编辑框位置放在相应单元格上
	createccomboboxobj->ShowWindow(SW_SHOW);//显示编辑框在单元格上面
}

void CNephoVisionDatabaseDlg::distroyCcombobox(CListCtrl *list, CComboBox* distroyccomboboxobj, int &Item, int &SubItem)
{
	CString meditdata;
	distroyccomboboxobj->GetWindowTextW(meditdata);
	list->SetItemText(Item, SubItem, meditdata);//更新相应单元格字符
	distroyccomboboxobj->DestroyWindow();//销毁对象,有创建就要有销毁,不然会报错
}

OK,到此我们已经实现了添加单元格编辑框和单元格下拉列表框的功能了,点击除性别列外的列表单元格看到以下效果:

点击性别列单元格则看到下拉列表效果,如下:

在单元格编辑框中写东西的时候往往喜欢按回车,这个时候如果不加处理的话会发现一个很崩溃的现象,程序直接退出了。这个可以重载对话框类的OnOK()函数来避免。就是在对话框类声明中添加

afx_msg void OnOK();

然后将其定义为什么都不做:

void CNephoVisionDatabaseDlg::OnOK()
{
}

这样就不会有按回车直接退出程序的事情发生了。

此外,如果希望在编辑框获取下拉列表框失去焦点的时候就将数据列表中的相关信息更新,可以响应动态创建的这两个控件的失去焦点消息,方法如下:

在对话框类声明中添加

afx_msg void OnKillfocusEdit();//动态生成编辑框失去焦点响应函数
afx_msg void OnKillfocusCcomboBox();//动态生成下拉列表框失去焦点响应函数

在对话框类实现的消息映射描述中添加

ON_EN_KILLFOCUS(IDC_EDIT_CREATEID, &CNephoVisionDatabaseDlg::OnKillfocusEdit)//添加动态生成编辑框的失去焦点响应函数
ON_CBN_KILLFOCUS(IDC_COMBOX_CREATEID, &CNephoVisionDatabaseDlg::OnKillfocusCcomboBox)

这样这两个控件在失去焦点的时候就会响应分别定义好的函数,我们只需要在相应的函数添加处理代码就可以了:

void CNephoVisionDatabaseDlg::OnKillfocusEdit()
{
	if (haveeditcreate == true)//如果之前创建了编辑框就销毁掉
	{
		distroyEdit(&m_list, &m_Edit, e_Item, e_SubItem);//销毁单元格编辑框对象
		haveeditcreate = false;
	}
	if (haveccomboboxcreate == true)//如果之前创建了下拉列表框就销毁掉
	{
		distroyCcombobox(&m_list, &m_comBox, e_Item, e_SubItem);
		haveccomboboxcreate = false;
	}
}

void CNephoVisionDatabaseDlg::OnKillfocusCcomboBox()
{
	if (haveeditcreate == true)//如果之前创建了编辑框就销毁掉
	{
		distroyEdit(&m_list, &m_Edit, e_Item, e_SubItem);//销毁单元格编辑框对象
		haveeditcreate = false;
	}
	if (haveccomboboxcreate == true)//如果之前创建了下拉列表框就销毁掉
	{
		distroyCcombobox(&m_list, &m_comBox, e_Item, e_SubItem);
		haveccomboboxcreate = false;
	}
}
时间: 2024-10-25 18:51:13

MFC List Control控件添加单元格编辑和单元格下拉列表项以适用于数据库相关操作的相关文章

VC/MFC 在ListCtl 控件中随鼠标移动提示单元格信息

[cpp] view plaincopy BEGIN_MESSAGE_MAP(CTipListCtrl, CListCtrl) //{{AFX_MSG_MAP(CTipListCtrl) ON_WM_MOUSEMOVE() ON_WM_DESTROY() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CTipLis

基于wince的MFC Tab Control控件的使用

1,先建立一个对话框MFC应用程序,然后在工具箱里面把Tab Control控件放到对话框中的合适位置上. 再在对话框类中,声明一个CTabCtrl变量: CTabCtrl m_tab; 变量m_tab用来与对话框中的Tab Control控件交互,为此要在DoDataExchange函数中加入DDX_Control语句: 1 //{{AFX_DATA_MAP(CTABDlg) 2 DDX_Control(pDX, IDC_TAB, m_tab); 3 //}}AFX_DATA_MAP IDC_

为树形控件添加弹出式菜单,并跟踪所选择的项

[cpp] view plaincopy <span style="font-size:24px;color:#ff0000;">为树形控件添加弹出式菜单,并跟踪所选择的项</span> [cpp] view plaincopy 动态弹出式菜单 [cpp] view plaincopy //获取当前右键的位置 CPoint pt; GetCursorPos(&pt); m_tree.ScreenToClient(&pt); //判断右键的位置处是

C++ MFC Tab Control控件的详细使用

1. 新建一个MFC工程, 取名MyTab, 选择Dialog based, 然后Finish.?2. 删除对话框上默认添加的三个控件. 添加Tab Control控件并在Property属性中设置ID为IDC_TABTEST 在More Styles里勾上Bottom. 调速尺寸使其布满整个对话框, 我这边Tab Control的尺寸最后为164X203. 在ClassWizard为其添加变量, 变量名为m_tab. 类型为CTabCtrl.?3. 在对话框的初始化函数OnInitDialog

C++ 关于MFC List Control 控件的使用事项 原创

1\在开发项目时,使用到了 listcontrol 控件,就一些问题,做一下备注,以备以后使用 (1)  给list项目 删除所有的项目  DeleteAllItems(); (2) 给list项目 添加一个列 .InsertColumn(0, _T("编号")); (3)给list a项目 设置列的宽度 .SetColumnWidth(0, 50); (4) 在添加项目之前 可以使用 .SetRedraw(false); 来禁止 重画,这样可以提高效率.当添加完成后,可以 使用 .S

mfc Picture Control 控件属性

知识点: Picture Control 控件属性 CStatic类 图片控件 图片控件使用 一.图片控件属性 Picture Control 属性: Type:Frame //框架 Type:Etched Horz水平蚀刻线条 Type:Etched Vert垂真蚀刻线条 Type:Rectangle实心矩形 Type:Bitmap位图 Type:Icon 图标 Type:Enhanced Metafile 增强图元 支持wmf格式图片 Type:Owner Draw 自绘图 Color:颜色

MFC中给控件添加变量,DoDataExchange中

DoDataExchange函数其实是一项数据动态绑定技术.比如你在写动态按钮过程中须对按钮添加变量时,怎么添加?控件类已经写好了,其变量是已经固定的.你要添加新的变量就要用到DoDataExchange函数. 你要在对话框的构造函数里面初始化一个变量,再用DoDataExchange函数将它绑定到你的动态按扭中,比如:DDX_Check(pDX, IDC_CHECK1, m_Lesson1);这就是将m_Lesson1(这是一个外部变量,其定义在对话框的构造函数里)绑定到IDC_CHECK1中

mfc 动态为控件添加事件1

知识点: 认识窗口过程 GetWindowLong SetWindowLong 为动态控件绑定事件 一.获取窗口过程 二.设置新窗口过程 1.书写一个新窗口过程函数 窗口过程格式 LRESULT CALLBACK WindowProc( HWND hwnd, // 窗口句柄 UINT uMsg, // 消息事件 WPARAM wParam, // 消息参数1 LPARAM lParam //消息参数2 ); CallWindowProc 把消息事件传递给以前的窗口过程 LRESULT CallW

mfc 动态为控件添加事件2

重载窗口过程 为动态控件绑定事件 一.重载窗口过程处理函数 CWnd::WindowProc virtual LRESULT WindowProc( UINT message, WPARAM wParam, LPARAM lParam ); LRESULT CALLBACK WindowProc( HWND hwnd, // handle to window UINT uMsg, // message identifier WPARAM wParam, // first message para