之前写过一篇(list Control实现单元格编辑)文章,那篇文章不是很完善执行的时候有时会出错,这篇文章经过完善后还加入了Combo Box功能!
这里我就只是晒一下我的代码;
头文件:
// ListControlTestDlg.h : 头文件 // #pragma once #include "afxcmn.h" #include "MyClstctrl.h" #include "afxwin.h" #define IDC_EDIT 0xffff // CListControlTestDlg 对话框 class CListControlTestDlg : public CDialog { // 构造 public: CListControlTestDlg(CWnd* pParent = NULL); // 标准构造函数 // 对话框数据 enum { IDD = IDD_LISTCONTROLTEST_DIALOG }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 // 实现 protected: HICON m_hIcon; // 生成的消息映射函数 virtual BOOL OnInitDialog(); afx_msg void OnPaint(); afx_msg HCURSOR OnQueryDragIcon(); DECLARE_MESSAGE_MAP() public: afx_msg void OnNMRClickList1(NMHDR *pNMHDR, LRESULT *pResult); CListCtrl m_list; afx_msg void OnNMDblclkList1(NMHDR *pNMHDR, LRESULT *pResult); afx_msg void OnNMClickList1(NMHDR *pNMHDR, LRESULT *pResult); CEdit m_Edit; int m_Item; //要Edit行 int m_SubItem; //要Edit列 int rowCount; //总行数 int m_ComItem; // 要加入Combo Box 的行 int m_ComSubItem; //要加入Combo Box的列 为了区别才这样定义,下面的两个bool类型也一样 bool needSave; //用于保存标志,如果有过编写则为TURE,当下次编辑时会在原来的位置输入原来输入的内容 bool ComneedSave; afx_msg void OnLvnItemchangedList1(NMHDR *pNMHDR, LRESULT *pResult); CComboBox m_comBox; };
Cpp文件:
void CListControlTestDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); DDX_Control(pDX, IDC_LIST1, m_list); //关联控件 }
BEGIN_MESSAGE_MAP(CListControlTestDlg, CDialog) ON_WM_PAINT() ON_WM_QUERYDRAGICON() //}}AFX_MSG_MAP //关联函数处理消息 ON_NOTIFY(NM_RCLICK, IDC_LIST1, &CListControlTestDlg::OnNMRClickList1) //关联处理点击右键函数 ON_NOTIFY(NM_DBLCLK, IDC_LIST1, &CListControlTestDlg::OnNMDblclkList1) //关联处理双击左键函数 ON_NOTIFY(NM_CLICK, IDC_LIST1, &CListControlTestDlg::OnNMClickList1) //关联处理单击左键函数 ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST1, &CListControlTestDlg::OnLvnItemchangedList1) END_MESSAGE_MAP()
在OnInitDialog()函数内做一些初始化处理
BOOL CListControlTestDlg::OnInitDialog() { CDialog::OnInitDialog(); // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动 // 执行此操作 SetIcon(m_hIcon, TRUE); // 设置大图标 SetIcon(m_hIcon, FALSE); // 设置小图标 // TODO: 在此添加额外的初始化代码 RECT m_rect; m_list.GetClientRect(&m_rect); //获取list的客户区 m_list.SetExtendedStyle(LVS_EX_GRIDLINES|LVS_EX_FULLROWSELECT); //设置list风格 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")); rowCount = m_list.GetItemCount(); //获取行数 needSave = false; //初始化为FLASE; ComneedSave = false; return TRUE; // 除非将焦点设置到控件,否则返回 TRUE }
这里我就只是将单击左键时的函数实现代码上传上来,里面实现了Edit和Combo Box 控件功能
void CListControlTestDlg::OnNMClickList1(NMHDR *pNMHDR, LRESULT *pResult) { LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR); // TODO: 在此添加控件通知处理程序代码 //我这里有两种办法可以实现 NM_LISTVIEW *pEditCtrl = (NM_LISTVIEW *)pNMHDR; CRect EditRect; CRect ComRect; //CPoint point; //GetCursorPos(&point); //m_list.ScreenToClient(&point); //LVHITTESTINFO info; //info.pt = point; //info.flags = LVHT_ABOVE //m_Item = m_list.SubItemHitTest(&info); if (pEditCtrl->iItem == -1) { //当点击其他区域时,显示内容 if (needSave) { //needSave == TURE CString EditStr; m_Edit.GetWindowText(EditStr); //获取输入的内容 m_list.SetItemText(m_Item,m_SubItem,EditStr); //m_Item,m_SubItem这两个变量的值是原来的单元格的值 m_Edit.ShowWindow(SW_HIDE); } if (ComneedSave) { CString strCom; m_comBox.GetWindowText(strCom); m_list.SetItemText(m_ComItem,m_ComSubItem,strCom); m_comBox.ShowWindow(SW_HIDE); } /* if (m_Edit.m_hWnd != NULL) { m_Edit.ShowWindow(SW_HIDE); } if (m_comBox.m_hWnd != NULL) { m_comBox.ShowWindow(SW_HIDE); } */ return; } //m_SubItem = info.iSubItem; //在1,2,4列实现编辑 if (pEditCtrl->iItem < rowCount && pEditCtrl->iSubItem != 2) { if (m_comBox.m_hWnd != NULL) { CString strCom; m_comBox.GetWindowText(strCom); m_list.SetItemText(m_ComItem,m_ComSubItem,strCom);//ComBoBox保存之前数据 m_comBox.ShowWindow(SW_HIDE); } if (needSave) { //needSave == TURE CString EditStr; m_Edit.GetWindowText(EditStr); //获取输入的内容 m_list.SetItemText(m_Item,m_SubItem,EditStr); //m_Item,m_SubItem这两个变量的值是原来的单元格的值 } m_Item = pEditCtrl->iItem; //行数 m_SubItem = pEditCtrl->iSubItem; //列数 m_list.GetSubItemRect(m_Item,m_SubItem,LVIR_LABEL,EditRect); //获取单元格的空间 if (m_Edit.m_hWnd == NULL) { //m_Edit.m_hWnd == NULL说明还没创建 //RECT rect; //rect.left = rect.top = 0; //rect.bottom = 20; //rect.right = 100; needSave = true; m_Edit.Create(ES_AUTOHSCROLL|WS_CHILD|ES_LEFT|ES_WANTRETURN|WS_BORDER, CRect(0,0,0,0),this,IDC_EDIT); //IDC_EDIT已近在头文件中定义,这个很重要,很多时候会忽略, //网上找到的实现编辑办法中这个都没说明 //我定义为#define IDC_EDIT 0xffff m_Edit.ShowWindow(SW_HIDE); //Edit创建完后隐藏 m_Edit.SetFont(this->GetFont(),FALSE);//设置字体 /* CFont tpFont; tpFont.CreateStockObject(DEFAULT_GUI_FONT); m_Edit.SetFont(&tpFont); tpFont.DeleteObject(); */ } m_Edit.SetParent(&m_list); //将list control设置为父窗口,生成的Edit才能正确定位,这个也很重要, EditRect.SetRect(EditRect.left,EditRect.top,EditRect.left+m_list.GetColumnWidth(m_SubItem),EditRect.bottom); //m_list.GetColumnWidth(m_SubItem)获取列的宽度 CString strItem = m_list.GetItemText(m_Item,m_SubItem); m_Edit.MoveWindow(&EditRect); m_Edit.ShowWindow(SW_SHOW); m_Edit.SetWindowText(strItem); m_Edit.SetFocus();//设置为焦点 m_Edit.SetSel(0,-1); //0,-1表示单元格内容全选中 } //在第三列插入Combo Box if (pEditCtrl->iSubItem == 2) { if (m_Edit.m_hWnd != NULL) { CString EditStr; m_Edit.GetWindowText(EditStr); //获取输入的内容 m_list.SetItemText(m_Item,m_SubItem,EditStr); //m_Item,m_SubItem这两个变量的值是原来的单元格的值 m_Edit.ShowWindow(SW_HIDE); } if (ComneedSave) { CString strCom; m_comBox.GetWindowText(strCom); m_list.SetItemText(m_ComItem,m_ComSubItem,strCom); } m_ComItem = pEditCtrl->iItem; //行数 m_ComSubItem = pEditCtrl->iSubItem; //列数 m_list.GetSubItemRect(m_ComItem,m_ComSubItem,LVIR_LABEL,ComRect); if (m_comBox.m_hWnd == NULL) { ComneedSave = true; m_comBox.Create(WS_CHILD|WS_VISIBLE|CBS_SORT|CBS_DROPDOWN|CBS_OEMCONVERT,CRect(0,0,40,40),this,0); //CBS_OEMCONVERT 实现可编辑 //CBS_DROPDOWN 产生一个下拉式框,小图标 //CBS_DROPDOWNLIST 图标代替单元格 m_comBox.AddString(_T("男")); //添加选项 m_comBox.AddString(_T("女")); m_comBox.SetFont(this->GetFont(),FALSE); // m_comBox.ShowWindow(SW_HIDE); } CString ComstrItem; m_comBox.SetParent(&m_list); ComstrItem = m_list.GetItemText(m_ComItem,m_ComSubItem); ComRect.SetRect(ComRect.left,ComRect.top,ComRect.left+m_list.GetColumnWidth(m_ComSubItem),ComRect.bottom); m_comBox.MoveWindow(&ComRect); m_comBox.ShowWindow(SW_SHOW); m_comBox.SetWindowText(ComstrItem); //当显示Combo Box控件时里面的内容为原来的内容,不然是空白的 m_comBox.SetFocus(); //设置焦点 } *pResult = 0; }