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

来源:互联网 发布:网络信息安全科普视频 编辑:程序博客网 时间:2024/05/23 19:15


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


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


EditListCtrl.h

[cpp] view plain copy print?
  1. #pragma once  
  2. #include "ListEdit.h"  
  3. #include "ListComboBox.h"  
  4. #include "_PersistAttriMapXML.h"  
  5.   
  6. #define  IDC_CELL_EDIT      0xffe0  
  7. #define  IDC_CELL_COMBOBOX  0xffe1  
  8.   
  9. // CEditListCtrl  
  10.   
  11. class CEditListCtrl : public CListCtrl  
  12. {  
  13.     DECLARE_DYNAMIC(CEditListCtrl)  
  14.   
  15. public:  
  16.     CEditListCtrl();  
  17.     virtual ~CEditListCtrl();  
  18.   
  19. protected:  
  20.     DECLARE_MESSAGE_MAP()  
  21.   
  22. private:  
  23.     CListEdit m_edit;  
  24.     CListComboBox m_comboBox;  
  25.     int m_nRow; //行  
  26.     int m_nCol; //列  
  27.   
  28. public:  
  29.   
  30.     // 当编辑完成后同步数据  
  31.     void DisposeEdit(void);  
  32.   
  33.     //发送失效消息  
  34.     void SendInvalidateMsg();  
  35.   
  36.     // 设置当前窗口的风格  
  37.     void SetStyle(void);  
  38.     afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);  
  39.     afx_msg void OnCbnSelchangeCbCellComboBox();  
  40.   
  41.     afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);  
  42.     afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);  
  43. };  



EditListCtrl.cpp

[cpp] view plain copy print?
  1. // EditListCtrl.cpp : implementation file  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5. #include "CADIPlatform.h"  
  6. #include "EditListCtrl.h"  
  7. #include "CodeDBHelper.h"  
  8. #include "PersistXmlParser.h"  
  9.   
  10. // CEditListCtrl  
  11.   
  12. IMPLEMENT_DYNAMIC(CEditListCtrl, CListCtrl)  
  13.   
  14. CEditListCtrl::CEditListCtrl()  
  15. {  
  16.   
  17. }  
  18.   
  19. CEditListCtrl::~CEditListCtrl()  
  20. {  
  21. }  
  22.   
  23.   
  24. BEGIN_MESSAGE_MAP(CEditListCtrl, CListCtrl)  
  25.     ON_WM_LBUTTONDBLCLK()  
  26.     ON_CBN_SELCHANGE(IDC_CELL_COMBOBOX, &CEditListCtrl::OnCbnSelchangeCbCellComboBox)  
  27.     ON_WM_HSCROLL()  
  28.     ON_WM_VSCROLL()  
  29. END_MESSAGE_MAP()  
  30.   
  31.   
  32.   
  33. // CEditListCtrl message handlers  
  34.   
  35. // 当编辑完成后同步数据  
  36. void CEditListCtrl::DisposeEdit(void)  
  37. {  
  38.     int nIndex = GetSelectionMark();  
  39.     //同步更新处理数据  
  40.     CString sLable;  
  41.     _PersistItem* pPersistItem = (_PersistItem*)GetItemData(m_nRow);  
  42.     if(NULL == pPersistItem) return ;  
  43.   
  44.     if(0 == m_nCol) //edit控件  
  45.     {  
  46.         CString szLable;  
  47.         m_edit.GetWindowText(szLable);  
  48.         SetItemText(m_nRow,m_nCol,szLable);  
  49.         pPersistItem->szPersistence = szLable;  
  50.   
  51.         m_edit.ShowWindow(SW_HIDE);  
  52.     }  
  53.     else if((1 == m_nCol) || (2 == m_nCol))  
  54.     {  
  55.         m_comboBox.ShowWindow(SW_HIDE);  
  56.     }  
  57.   
  58. }  
  59.   
  60. // 设置当前窗口的风格  
  61. void CEditListCtrl::SetStyle(void)  
  62. {  
  63.     LONG lStyle;  
  64.     lStyle = GetWindowLong(m_hWnd,GWL_STYLE);  
  65.     lStyle &= ~LVS_TYPEMASK; //清除显示方式  
  66.     lStyle |= LVS_REPORT; //list模式  
  67.     lStyle |= LVS_SINGLESEL; //单选  
  68.     SetWindowLong(m_hWnd,GWL_STYLE,lStyle);  
  69.   
  70.     //扩展模式  
  71.     DWORD dwStyle = GetExtendedStyle();  
  72.     dwStyle |= LVS_EX_FULLROWSELECT; //选中某行使其整行高亮  
  73.     dwStyle |= LVS_EX_GRIDLINES; //网格线  
  74.     SetExtendedStyle(dwStyle); //设置扩展风格  
  75. }  
  76.   
  77. void CEditListCtrl::OnLButtonDblClk(UINT nFlags, CPoint point)  
  78. {  
  79.     // TODO: Add your message handler code here and/or call default  
  80.     CListCtrl::OnLButtonDblClk(nFlags, point);  
  81.   
  82.     LVHITTESTINFO info;  
  83.     info.pt = point;  
  84.     info.flags = LVHT_ONITEMLABEL;  
  85.   
  86.     if(SubItemHitTest(&info) >= 0)  
  87.     {  
  88.         m_nRow = info.iItem;  
  89.         m_nCol = info.iSubItem;  
  90.   
  91.         CRect rect;  
  92.         GetSubItemRect(m_nRow,m_nCol,LVIR_LABEL,rect);  
  93.   
  94.         CString strValue;  
  95.         strValue = GetItemText(m_nRow,m_nCol);  
  96.   
  97.         _PersistItem* pPersistItem = (_PersistItem*)GetItemData(m_nRow);  
  98.         if(NULL == pPersistItem) return ;  
  99.         //Edit单元格  
  100.         if((0 == m_nCol))  
  101.         {  
  102.             if(pPersistItem->nFlag & 0x01)  
  103.             {  
  104.                 MB_PROMPT(RES_LOAD_STRING(IDS_ST_MODIFIYPKATTRI_20170502_01));  
  105.                 return ;  
  106.             }  
  107.   
  108.             if(NULL == m_edit)  
  109.             {  
  110.                 //创建Edit控件  
  111.                 // ES_WANTRETURN 使多行编辑器接收回车键输入并换行。如果不指定该风格,按回车键会选择缺省的命令按钮,这往往会导致对话框的关闭。  
  112.                 m_edit.Create(WS_CHILD|WS_BORDER|ES_AUTOHSCROLL|ES_WANTRETURN|ES_LEFT,  
  113.                     CRect(0,0,0,0),this,IDC_CELL_EDIT);  
  114.             }  
  115.             m_edit.MoveWindow(rect);  
  116.             m_edit.SetWindowText(strValue);  
  117.             m_edit.ShowWindow(SW_SHOW);  
  118.             m_edit.SetSel(0,-1);  
  119.             m_edit.SetFocus();  
  120.             UpdateWindow();  
  121.         }  
  122.         //ComboBox单元格  
  123.         if((1 == m_nCol))  
  124.         {  
  125.             if(NULL == m_comboBox)  
  126.             {  
  127.                 //创建Combobox控件  
  128.                 //CBS_DROPDOWNLIST : 下拉式组合框,但是输入框内不能进行输入  
  129.                 //WS_CLIPCHILDREN  :  其含义就是,父窗口不对子窗口区域进行绘制。默认情况下父窗口会对子窗口背景是进行绘制的,但是如果父窗口设置了WS_CLIPCHILDREN属性,父亲窗口不在对子窗口背景绘制.  
  130.                 m_comboBox.Create(WS_CHILD|WS_VISIBLE|CBS_SORT|WS_BORDER|CBS_DROPDOWNLIST|WS_VSCROLL|WS_TABSTOP|CBS_AUTOHSCROLL,  
  131.                     CRect(0,0,0,0),this,IDC_CELL_COMBOBOX);  
  132.             }  
  133.             m_comboBox.MoveWindow(rect);  
  134.   
  135.             m_comboBox.ShowWindow(SW_SHOW);  
  136.             //TODO comboBox 初始化  
  137.             LoadPlmAttri();  
  138.             //当前cell的值  
  139.             CString strCellValue = GetItemText(m_nRow,m_nCol);  
  140.             int nIndex = m_comboBox.FindStringExact(0,strCellValue);  
  141.             if(CB_ERR == nIndex)  
  142.                 m_comboBox.SetCurSel(0); //TODO 设置为当前值的Item  
  143.             else  
  144.                 m_comboBox.SetCurSel(nIndex);         
  145.               
  146.             m_comboBox.SetFocus();  
  147.             UpdateWindow();  
  148.         }  
  149.     }  
  150. }  
  151.   
  152.   
  153. void CEditListCtrl::OnCbnSelchangeCbCellComboBox()  
  154. {  
  155.     //同步更新处理数据  
  156.     _PersistItem* pPersistItem = (_PersistItem*)GetItemData(m_nRow);  
  157.     if(NULL == pPersistItem) return ;  
  158.   
  159.     if(1 == m_nCol) //combobox控件  
  160.     {  
  161.         CString szLable;  
  162.         int nindex = m_comboBox.GetCurSel();  
  163.         m_comboBox.GetLBText(nindex,szLable);  
  164.         ATTRIFIELD* pAttriField = (ATTRIFIELD*)m_comboBox.GetItemData(nindex);  
  165.         if(NULL == pAttriField)  
  166.             return ;  
  167.   
  168.         //持久化的处理  
  169.         if(0 == pAttriField->szComment.CompareNoCase(ATTRIBUTE_PERSISTENCE))  
  170.         {  
  171.             pPersistItem->szPersistence=pAttriField->mapPersistenceValue[ATTRIBUTE_VALUE];  
  172.             SetItemText(m_nRow,m_nCol-1,pPersistItem->szPersistence);  
  173.         }  
  174.   
  175.         pPersistItem->szUcProperty = pAttriField->szPLMToXML;  
  176.         pPersistItem->szXmlOption = pAttriField->szXMLOpention;  
  177.         SetItemText(m_nRow,m_nCol,pAttriField->szDetail);          
  178.         m_comboBox.ShowWindow(SW_HIDE);       
  179.     }  
  180. }  
  181.   
  182. //发送失效消息  
  183. void CEditListCtrl::SendInvalidateMsg()  
  184. {  
  185.     //Edit单元格  
  186.     if((0 == m_nCol))  
  187.     {  
  188.   
  189.         if(NULL == m_edit.m_hWnd) return ;  
  190.         BOOL bShow = m_edit.IsWindowVisible();  
  191.         if(bShow)  
  192.             ::SendMessage(m_edit.m_hWnd,WM_KILLFOCUS,(WPARAM)0,(LPARAM)0);  
  193.   
  194.     }  
  195.     else if((1 == m_nCol)) //combobox  
  196.     {  
  197.         if(NULL == m_comboBox.m_hWnd) return ;  
  198.   
  199.         BOOL bShow = m_comboBox.IsWindowVisible();  
  200.         if(bShow)  
  201.             ::SendMessage(m_comboBox.m_hWnd,WM_KILLFOCUS,(WPARAM)0,(LPARAM)0);  
  202.     }  
  203. }  
  204.   
  205. void CEditListCtrl::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)  
  206. {  
  207.     SendInvalidateMsg();  
  208.   
  209.     CListCtrl::OnHScroll(nSBCode, nPos, pScrollBar);  
  210. }  
  211.   
  212. void CEditListCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)  
  213. {  
  214.     SendInvalidateMsg();  
  215.   
  216.     CListCtrl::OnVScroll(nSBCode, nPos, pScrollBar);  
  217. }  




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

[cpp] view plain copy print?
  1. RECT listRect;     
  2. GetDlgItem(IDC_ST_LISTGROUP)->GetWindowRect(&listRect);  //获取List控件所在位位置,用Group占位  
  3. ScreenToClient(&listRect);  
  4.   
  5. m_list.Create(WS_CHILD|WS_BORDER|LVS_SINGLESEL|LVS_REPORT,listRect,this,IDC_EDIT_LIST);  
  6. m_list.SetExtendedStyle(LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES|LVS_EX_UNDERLINEHOT);  
  7. m_list.ShowWindow(SW_SHOW);  
[cpp] view plain copy print?
  1. <span style="white-space: pre;">    <span style="white-space: pre;">    </span>RECT rect;  
  2. <span style="white-space: pre;">    </span>m_list.GetClientRect(&rect);  
  3. <span style="white-space: pre;">    </span>  
  4. <span style="white-space: pre;">    </span>m_list.InsertColumn(0,</span>FirstColName<span style="white-space: pre;">,LVCFMT_LEFT,rect.right/2);  
  5. <span style="white-space: pre;">    </span>m_list.InsertColumn(1,</span>SecondColName<span style="white-space: pre;">,LVCFMT_LEFT,rect.right/2);</span>      
[cpp] view plain copy print?
  1.   
[cpp] view plain copy print?
  1.   
[cpp] view plain copy print?
  1.   

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

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

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

ListEdit.h

[cpp] view plain copy print?
  1. #pragma once  
  2.   
  3.   
  4. // CListEdit  
  5.   
  6. class CListEdit : public CEdit  
  7. {  
  8.     DECLARE_DYNAMIC(CListEdit)  
  9.   
  10. public:  
  11.     CListEdit();  
  12.     virtual ~CListEdit();  
  13.   
  14. protected:  
  15.     DECLARE_MESSAGE_MAP()  
  16. public:  
  17.     afx_msg void OnKillFocus(CWnd* pNewWnd);  
  18. protected:  
  19.     virtual void PreSubclassWindow();  
  20. };  

ListEdit.cpp

[cpp] view plain copy print?
  1. // ListEdit.cpp : implementation file  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5. #include "CADIPlatform.h"  
  6. #include "ListEdit.h"  
  7. #include "EditListCtrl.h"  
  8.   
  9.   
  10. // CListEdit  
  11.   
  12. IMPLEMENT_DYNAMIC(CListEdit, CEdit)  
  13.   
  14. CListEdit::CListEdit()  
  15. {  
  16.   
  17. }  
  18.   
  19. CListEdit::~CListEdit()  
  20. {  
  21. }  
  22.   
  23.   
  24. BEGIN_MESSAGE_MAP(CListEdit, CEdit)  
  25.     ON_WM_KILLFOCUS()  
  26. END_MESSAGE_MAP()  
  27.   
  28.   
  29.   
  30. // CListEdit message handlers  
  31.   
  32.   
  33.   
  34. void CListEdit::OnKillFocus(CWnd* pNewWnd)  
  35. {  
  36.     CEdit::OnKillFocus(pNewWnd);  
  37.   
  38.     //ShowWindow(SW_HIDE);  
  39.     CEditListCtrl* temp = (CEditListCtrl*)GetParent();  
  40.     temp->DisposeEdit();  
  41.   
  42. }  
  43.   
  44. void CListEdit::PreSubclassWindow()  
  45. {  
  46.     // TODO: Add your specialized code here and/or call the base class  
  47.   
  48.     CEdit::PreSubclassWindow();  
  49. }  

ListComboBox.h

[cpp] view plain copy print?
  1. #pragma once  
  2.   
  3.   
  4. // CListComboBox  
  5.   
  6. class CListComboBox : public CComboBox  
  7. {  
  8.     DECLARE_DYNAMIC(CListComboBox)  
  9.   
  10. public:  
  11.     CListComboBox();  
  12.     virtual ~CListComboBox();  
  13.   
  14. protected:  
  15.     DECLARE_MESSAGE_MAP()  
  16. public:  
  17.     afx_msg void OnKillFocus(CWnd* pNewWnd);  
  18.     afx_msg void OnCbnDropdown();  
  19. };  

ListComboBox.cpp

[cpp] view plain copy print?
  1. // ListComboBox.cpp : implementation file  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5. #include "CADIPlatform.h"  
  6. #include "ListComboBox.h"  
  7. #include "EditListCtrl.h"  
  8.   
  9.   
  10. // CListComboBox  
  11.   
  12. IMPLEMENT_DYNAMIC(CListComboBox, CComboBox)  
  13.   
  14. CListComboBox::CListComboBox()  
  15. {  
  16.   
  17. }  
  18.   
  19. CListComboBox::~CListComboBox()  
  20. {  
  21. }  
  22.   
  23.   
  24. BEGIN_MESSAGE_MAP(CListComboBox, CComboBox)  
  25.     ON_WM_KILLFOCUS()  
  26.     ON_CONTROL_REFLECT(CBN_DROPDOWN, &CListComboBox::OnCbnDropdown)  
  27. END_MESSAGE_MAP()  
  28.   
  29.   
  30.   
  31. // CListComboBox message handlers  
  32.   
  33. void CListComboBox::OnKillFocus(CWnd* pNewWnd)  
  34. {  
  35.     CComboBox::OnKillFocus(pNewWnd);  
  36.     //ShowWindow(SW_HIDE);  
  37.   
  38.     CEditListCtrl *temp = (CEditListCtrl*)GetParent();  
  39.     temp->DisposeEdit(); //调用父窗口的DisposeEdit()函数  
  40. }  
  41.   
  42. void CListComboBox::OnCbnDropdown()  
  43. {  
  44.     CClientDC dc(this);  
  45.     int nTotalHeight = 0;  
  46.     //获取字体信息  
  47.     dc.SelectObject(GetFont());  
  48.     //获取当前item的个数  
  49.     int nCount = GetCount();  
  50.     if(nCount <= 0) return ;  
  51.     //获取字体的高度  
  52.     CString strLable=_T("");  
  53.     GetLBText(GetCurSel(),strLable);  
  54.     int nHeight = dc.GetTextExtent(strLable).cy;  
  55.   
  56.     //组合框高度  
  57.     CRect rect;  
  58.     GetWindowRect(rect);  
  59.     int height = rect.Height();  
  60.   
  61.     if(nCount>30)  
  62.         nTotalHeight = 30*nHeight + height;  
  63.     else  
  64.         nTotalHeight = nCount*nHeight + height;  
  65.   
  66.     //设置下拉的高度  
  67.     CRect rc;  
  68.     GetClientRect(&rc);  
  69.     SetWindowPos(NULL,0,0,rc.Width(),rc.Height()+nTotalHeight,SWP_NOZORDER|SWP_NOMOVE|SWP_SHOWWINDOW);  
  70. }  


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

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


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