VC驿站

 找回密码
 加入驿站

QQ登录

只需一步,快速开始

搜索
查看: 1236|回复: 4

[交流] CListCtrl 编辑子项

[复制链接]
49_avatar_middle
在线会员 发表于 2016-4-11 15:09:09 | 显示全部楼层 |阅读模式
相信很多人用过MFC的新手都知道,MFC虽然封装了一些常用的控件,但不少控件真正使用起来,与个人的要求可能会有一些差别,总有一些功能不是很方便就能实现的,例如CTabCtrl(Tab控件)的颜色(涉及到自绘、头大)/CListCtrl的子项编辑。报表风格的列表控件,在资源里设置了“可就地编辑”的属性,子项虽然能够编辑,但编辑框是出现在第一列的,即不管你选择修改的项是在第几列,编辑框总是出现在相应行的第一列位置,很麻烦,而且经过我的尝试,编辑完后的文本保存,也是需要自己实现的。

为了简便实现,我没有派生子类,而是在资源中添加一个编辑框,通过将编辑框显示隐藏在指定位置,达到可编辑的目的,在编辑框失去焦点时,将文本显示在ListCtrl中。
下面是我的实现方法:
  1.  资源里拖入一个CEdit Box控件,关联control变量m_SubItemEdit,关联value变量CString m_strEditText,在对话框初始化函数OnInitDialog()里将编辑框隐藏起来:           m_SubItemEdit.ShowWindow(SW_HIDE);

2.   在对话框上拖入一个CListCtrl列表控件,设置后属性,风格(报表-report),添加变量m_ListCtrl,在对话框初始化函数里加入列表控件的一些初始化操作,
     在 OninitDialog中初始化列表框:
    m_ListCtrl.SetExtendedStyle( //设置风格
                LVS_EX_FLATSB            //扁平风格滚动条
                | LVS_EX_FULLROWSELECT    //允许整行选中
                | LVS_EX_HEADERDRAGDROP   //允许标题拖拽
                | LVS_EX_ONECLICKACTIVATE //高亮显示
                | LVS_EX_GRIDLINES        //画出网格线
                );
        m_ListCtrl.InsertColumn(0, _T("姓名"), LVCFMT_LEFT, 150, 0);
        m_ListCtrl.InsertColumn(1, _T("联系电话"), LVCFMT_LEFT, 150, 1);
        m_ListCtrl.InsertItem(0, _T(""));
        m_ListCtrl.SetItemText(0, 0, _T("周芷若"));
        m_ListCtrl.SetItemText(0, 1, _T("123456789"));
        m_ListCtrl.InsertItem(1, _T(""));
        m_ListCtrl.SetItemText(1, 0, _T("张无忌"));
        m_ListCtrl.SetItemText(1, 1, _T("987654321"));
        m_SubItemEdit.ShowWindow(SW_HIDE);


    3.  响应CListCtrl控件的NM_DBLCLK(指示用户在控件内双击了鼠标左键),以下是响应函数的处理,实现子项的可编辑化。


void CEditListCtrlDlg::OnNMDblclkList1(NMHDR *pNMHDR, LRESULT *pResult)
{
        //LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
        // TODO:  在此添加控件通知处理程序代码
        //*pResult = 0;


        NM_LISTVIEW *pNMListCtrl = (NM_LISTVIEW *)pNMHDR;
        if (pNMListCtrl->iItem != -1)
        {
                CRect rect, dlgRect;
                //获得当前列的宽度以适应如果用户调整宽度   
                //此处不用获得的子项rect矩形框来设置宽度   
                //是因第一列时返回的宽度是整行的宽度,我也不知道为啥   
                int width = m_ListCtrl.GetColumnWidth(pNMListCtrl->iSubItem);
                m_ListCtrl.GetSubItemRect(pNMListCtrl->iItem, pNMListCtrl->iSubItem, LVIR_BOUNDS, rect);
       
                //所以需要保存列表的索引   
                //以及子项相对应的行列号索引  
                listSelItem[0] = pNMListCtrl->iItem;
                listSelItem[1] = pNMListCtrl->iSubItem;




                //获得listctrl矩形框   
                //获得父对话框的位置以调整CEdit的显示位置,具体见下面代码   
                m_ListCtrl.GetWindowRect(&dlgRect);
                ScreenToClient(&dlgRect);




                int height = rect.Height();
                rect.top += (dlgRect.top + 1);
                rect.left += (dlgRect.left + 1);
                rect.bottom = rect.top + height + 2;
                rect.right = rect.left + width + 2;
                m_SubItemEdit.MoveWindow(&rect);
                m_SubItemEdit.ShowWindow(SW_SHOW);
                m_SubItemEdit.SetFocus();
        }
}


4.到了这里,应该就可以实现双击编辑控件了,但只是编辑而已,没有实现保存,要实现保存,还得对CEDIT失去焦点消息进行相应,以下是响应函数,因为我还做了CEdit控件对于回车键实现保存编辑的功能
void CEditListCtrlDlg::SetListItemText(void)
{
        UpdateData(TRUE);
                //此处的cstrItemTextEdit是CEdit控件的字符串关联变量   
                m_ListCtrl.SetItemText(listSelItem[0], listSelItem[1], m_strEditText);
                //重置编辑框文本   
                m_SubItemEdit.SetWindowText(_T(""));
                //隐藏编辑框   
                m_SubItemEdit.ShowWindow(SW_HIDE);
        //强制刷新列表控件(否则视觉上有感觉有点不爽,可以试试^_^)   
           m_ListCtrl.Invalidate();
}
5.   响应CEdit控件的EN_KILLFOCUS函数
void CEditListCtrlDlg::OnEnKillfocusEdit1()
{
        // TODO:  在此添加控件通知处理程序代码
        SetListItemText();
}


6.处理回车键的响应,所以直接重载对话框的PreTranslateMessage函数,然后在函数里做处理
BOOL CEditListCtrlDlg::PreTranslateMessage(MSG* pMsg)
{
        // TODO:  在此添加专用代码和/或调用基类
        if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN)
        {
                if (GetFocus()->GetDlgCtrlID() == IDC_EDIT1)
                {
                        //使列表控件获得焦点,则CEdit会自动失去焦点,触发EN_KILLFOCUS消息   
                                m_ListCtrl.SetFocus();
                }
                return TRUE;
        }
        return CDialogEx::PreTranslateMessage(pMsg);
}





运行效果

运行效果

EditListCtrl.zip

139.85 KB, 下载次数: 13, 下载积分: 驿站币 -1





上一篇:最近要进行 NOIP 竞赛 写的一个小软件
下一篇:一服务器多客户端的数据传输
01_avatar_middle
online_vip 发表于 2016-4-12 17:59:11 | 显示全部楼层
刚今天才看到你的帖子,自己找资料搞了2天,早点看到就不用浪费时间了,和你差不多,有一点要注意,就是tab顺序,要是你的llistctrl序号小于要覆盖的edit的编辑框,就会造成双击后不显示edit框框,要移动下才出来

        我的 if(pNMListView->iItem!=-1&&pNMListView->iSubItem ==4)
         这句比你的多个判断条件,能控制那些列能修改

m_edit.SetFocus();//使编辑框取得焦点
m_edit.CreateSolidCaret(1,13);//创建一个光标
m_edit.ShowCaret();//显示光标
m_edit.SetSel(-1);//使光标移到最后面

加上这个双击后直接把光标移到最后了
49_avatar_middle
ico_lz  楼主| 发表于 2016-4-13 18:05:43 | 显示全部楼层
fangshexian 发表于 2016-4-12 17:59
刚今天才看到你的帖子,自己找资料搞了2天,早点看到就不用浪费时间了,和你差不多,有一点要注意,就是tab ...

以后多交流啊  
22_avatar_middle
在线会员 发表于 2016-4-14 17:49:20 | 显示全部楼层
自己实现起来比较麻烦,这种东西去CodeProject上找现成的就好,搜索关键字:ListCtrlEx或者GridCtrl。
当你用来用去发现还是不够灵活,这个时候你用一下QT,你恍然大悟,啊,原来QT做界面是这么吊!
26_avatar_middle
在线会员 发表于 2016-7-14 11:28:26 来自手机 | 显示全部楼层
我就笑笑不说话1468465817.23
您需要登录后才可以回帖 登录 | 加入驿站 qq_login

本版积分规则

关闭

站长提醒上一条 /2 下一条

QQ|小黑屋|手机版|VC驿站 ( 辽ICP备09019393号tongdun|网站地图wx_jqr

GMT+8, 2019-3-25 13:01

Powered by Discuz! X3.4

© 2009-2019 cctry.com

快速回复 返回顶部 返回列表