MFC List Control 控件添加单元格编辑,实现可编辑重写


  在实现随机生成四则运算的个人项目中,目前已经完成基本功能,想要把程序变成一个Windows界面的程序。原本以为学习过MFC,应该很快就能完成。但是由于以前用的都是VC6.0,这次用了VS2010,稍微有点不适应,而且也有一段时间没用,悲催地发现自己已经很不熟练了(╮(╯▽╰)╭基本上自己以前写的MFC应用程序都是看网上傻瓜教程,扯远了~~~)。经过分析发现,用MFC实现显示四则运算表达式然后接受用户输入答案,单纯地用List Control好像不能实现,所以又在网上搜索了实现可编辑List-Control的教程,自己跟着实现了一遍。

  首先,创建的是基于对话框的MFC应用程序,对话框为FourArithOperDlg,在FourArithOperDlg.h中添加如下变量和函数:

1     int e_Item;//刚编辑的行
2     int e_SubItem;//刚编辑的列
3     CEdit m_Edit;//生成单元编辑框
4     bool haveeditcreate;//标志编辑框已经被创建
5     void createEdit(NM_LISTVIEW  *pEditCtrl, CEdit *createdit, int &Item, int &SubItem, bool &havecreat);//创建单元格编辑框函数  
6     void distroyEdit(CListCtrl *list, CEdit* distroyedit, int &Item, int &SubItem);//销毁单元格编辑框对象 

  在对话框的初始函数中添加初始化代码如下:这里的列表框第一行显示表达式,第二行显示答案。

1      CRect rect;
2      m_expression.GetClientRect(&rect);
3      m_expression.SetExtendedStyle(m_expression.GetExtendedStyle() | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
4      m_expression.InsertColumn(0,_T("运算表达式"), LVCFMT_CENTER, rect.Width()/2,0);
5      m_expression.InsertColumn(1,_T("结果"), LVCFMT_CENTER, rect.Width()/2,1);
6      m_expression.InsertItem(0,_T("1+1"));
7      m_expression.SetItemText(0,1,_T("2"));
8      haveeditcreate = false;    

  为列表框添加单击响应函数,NM_CLICK,这里只是让第二列,也就是显示答案的那一列单击产生编辑框。

 1   NM_LISTVIEW  * pEditCtrl = (NM_LISTVIEW *)pNMHDR;
 2     printf("行:%d,列:%d\n",pEditCtrl->iItem,pEditCtrl->iSubItem);
 3     if (pEditCtrl->iItem == -1)//点击到非工作区
 4     {
 5         if (haveeditcreate == true)//如果之前创建了编辑框就销毁掉
 6         {
 7             distroyEdit(&m_expression,&m_Edit,e_Item,e_SubItem);//销毁单元格编辑对象
 8             haveeditcreate = false;
 9         }
10     } 
11     else if(pEditCtrl->iSubItem == 1)//如果选择第二列
12     {
13         if (haveeditcreate == true)
14         {
15             if (!(e_Item == pEditCtrl->iItem && e_SubItem == pEditCtrl->iSubItem))//如果点中的单元格不是之前创建的
16             {
17                 distroyEdit(&m_expression,&m_Edit,e_Item,e_SubItem);
18                 haveeditcreate = false;
19                 createEdit(pEditCtrl,&m_Edit,e_Item,e_SubItem,haveeditcreate);
20             } 
21             else //点中的单元格是之前创建的
22             {
23                 m_Edit.SetFocus();//设置为焦点
24             }
25         } 
26         else
27         {
28             e_Item = pEditCtrl->iItem;
29             e_SubItem = pEditCtrl->iSubItem;
30             createEdit(pEditCtrl,&m_Edit,e_Item,e_SubItem,haveeditcreate);//创建编辑框
31         }
32     }

   接下来就是创建与销毁单元格编辑框的实现了。

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

 

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

   然后,解决单元格编辑框中回车键的处理,在教程中说可以重载对话框类的OnOK函数来避免。所以在对话框类中添加声明

 1 afx_msg void OnOk(); 

  在对话框cpp文件中函数内为空。

1 void CFourArithOperDlg::OnOk()
2 {}

  但是此时,在编辑框中修改数据,然后点击其他的单元格,编辑框还停留在上一个单元格中,所以在对话框类声明中添加动态生成编辑框失去焦点响应函数

 1 afx_msg void OnKillFocusEdit(); 

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

 1 ON_EN_KILLFOCUS(IDC_EDIT_CREATEID,&CFourArithOperDlg::OnKillFocusEdit) 

  处理函数:

1 void CFourArithOperDlg::OnKillFocusEdit()
2 {
3     if (haveeditcreate == true)
4     {
5         distroyEdit(&m_expression,&m_Edit,e_Item,e_SubItem);
6         haveeditcreate = false;
7     }
8 }

   现在,基本完成了对话框的第二列可以编辑的功能了,效果图:

  通过这个可编辑列表框的实现教程,熟悉了在VS中创建简单的MFC应用程序的过程。

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM