(要求不但能够在List Control中显示数据,而且能够动态修改选中的Item中的内容,其功能类似与在程序中插入一张可以随意修改的表(Table)。虽然整个过程很简单,却体现了MFC编程的灵活性。通过实现高级List Control控件,也可以从更深层次理解MFC界面编程。
下面将实现步骤总结如下:
这里我们来实现一个自己的类CEditTable,该类继承与CListCtrl。
先说一下我们的思路:CListCtrl类给提供了现实数据的基本操作,但要像Word中编辑表格一样编辑ClistCtrl中的内容,首先必须获取要编辑的Item的位置,然后用新输入的内容代替原来Item中的内容。基本思路很简单,就是先触发输入操作,然后新建一个CEdit编辑框对象,从CEdit编辑框中获取新的内容,以新内容替换指定Item中的内容,回车结束,销毁CEdit编辑框对象。下面来一步步实现。
1.  从CEdit控件继承一个CItemEdit类,作为CListCtrl的成员,用来接收输入内容。
2.  重载CEdit的消息翻译函数BOOL PreTranslateMessage(MSG* pMsg); 在函数中拦截ESC键和RETURN键按下的消息,解释为WM_KILLFOCUS消息(ESC和ENTER分别表示取消输入和输入结束)
BOOL CItemEdit::PreTranslateMessage(MSG* pMsg)
{
    //拦截ESC键和RETURN键按下的消息,解释为WM_KILLFOCUS消息,这里也可以根据需要设置其它键作为输入结束或取消输入的标志
    if( pMsg->message==WM_KEYDOWN )
    {
        if( pMsg->wParam==13 )        //回车键

pMsg->message = WM_KILLFOCUS;
        else if( pMsg->wParam==27 )    //ESC键
        {

m_bInputValid = FALSE;    //此时的编辑结果无效
            pMsg->message = WM_KILLFOCUS;
        }
    }

return CEdit::PreTranslateMessage(pMsg);
}
3. 重载OnKillFocus函数
void CItemEdit::OnKillFocus(CWnd* pNewWnd)
{
    // 得到父窗口,并通知父窗口结束编辑过程
    lj_CListCtrl *parent = (lj_CListCtrl *)GetParent();
    if( parent )
        parent->MyEndEdit( m_bInputValid );

m_bInputValid = TRUE;
  
    CEdit::OnKillFocus(pNewWnd);
}
4.   从CListCtrl类继承新的CEditTable类
5.   在CEditTable中分别添加编辑控件成员 CItemEdit  m_edit; 便是行和列的坐标变量
              int m_nItem;   //被编辑表项的行号
             int m_nSubItem; //列号

6.   在CEditTable中重载鼠标左键按下消息的回调函数 void OnLButtonDown(UINT nFlags, CPoint point);

应用中要通过点击鼠标左键开始编辑Table中的某一项。
void CEditTable::OnLButtonDown(UINT nFlags, CPoint point)
{
    POSITION pos;
    BOOL bSelected = FALSE;

// 检查是否有Item正被编辑
    if( m_bEditing ==TRUE)
        goto defalt_session;

// 检查是否有Item被选中,没有时不进入编辑

pos = GetFirstSelectedItemPosition();
    if( pos )
    {
        // 得到被点击的Item
        LVHITTESTINFO testinfo;
        testinfo.pt.x = point.x;

testinfo.pt.y = point.y;            //点击时的鼠标位置
        testinfo.flags = LVHT_ONITEMLABEL;    //点击的必须是标题
        if( SubItemHitTest(&testinfo)<0 )
            goto defalt_session;            //没有点在有效区域,不进入编辑
        m_nItem = testinfo.iItem;            //被点击表项的行号
        m_nSubItem = testinfo.iSubItem;    //被点击表项的列号

//if(m_nSubItem == 0)
        //{
            //goto defalt_session;            //选中第一列,不编辑

//}

// 检查该表项是否被选中,没被选中不进入编辑
        while( pos )
            if( m_nItem==GetNextSelectedItem(pos) )

{
                bSelected = TRUE;
                break;
            }
        if( bSelected==FALSE )
            goto defalt_session;            //没有点在有效区域,不编辑

// 开始编辑
        m_bEditing = BeginEdit();
        return;

}

defalt_session:
    CListCtrl::OnLButtonDown(nFlags, point);
}
7.   添加开始编辑函数BOOL BeginEdit();  完成新建CEdit对象、获取Edit输入文字等功能
BOOL CEditTable::BeginEdit()
{
    // 得到被编辑表项的区域
    CRect rect;
    if( GetSubItemRect(m_nItem, m_nSubItem, LVIR_LABEL, rect)==FALSE )
        return FALSE;

// 创建编辑控件
    int style =     WS_CHILD |
                    WS_CLIPSIBLINGS |
                    WS_EX_TOOLWINDOW |

WS_BORDER;
    if( m_edit.Create(style, rect, this, ID_MYEDIT)==FALSE )
        return FALSE;

// 取被编辑表项的文字
    CString txtItem = GetItemText( m_nItem, m_nSubItem );

// 取出的文字填写到编辑控件
    m_edit.SetWindowText( txtItem );
    m_edit.SetFocus();
    m_edit.SetSel( 0, -1 );
    m_edit.ShowWindow( SW_SHOW );

return TRUE;

}
8.     添加结束编辑函数 void EndEdit( BOOL bValidate );  主要完成替换Item内容、销毁编辑框等功能。
void CEditTable::EndEdit( BOOL bValidate )
{
    // 编辑结果是有效的,重设被编辑表项的文字

if( bValidate )
    {
        CString txtItem;
        m_edit.GetWindowText( txtItem );
        SetItemText(m_nItem, m_nSubItem, txtItem);
    }

// 销毁编辑窗口
    m_edit.DestroyWindow();
    m_bEditing = FALSE;
}

论坛中搜索一下,你们会发现不少类似(的)提问:我们如何编辑list control(的)条目?如何直接编辑list control...等等;list control可用来做数据库表(的)视图,十分有用.
但报表风格(的)list control只能编辑第一列,其余(的)该死(的)微软没为vc做到.它们怕VB卖不出.于是C++程序员只好DIY.主要思想是在list control中动态创建一个控件,动态移动该控件到相应位置.这些技巧早有人讨论过了,本文也是基于如上思想(的),但注重于可扩充性与使用(的)方便.
List control 这头主要是重载OnLButtonDown技巧,计算出被点中(的)条目.这里重要(的)函数是SubItemHitTest和GetSubItemRect,看msdn上有相关说明. 用户点中后,就要负责显示控件了:如果之前选中了其他们,就要验证之前(的)改动是否成功.不成功就要回到原来(的)(地)方,成功就应用修改并移到新位置.看代码:
static     const UINT IDCHAILD=3000;
void CValidateList::OnLButtonDown(UINT nFlags, CPoint point)
{
     CListCtrl::OnLButtonDown(nFlags, point);
    LVHITTESTINFO hi;
    hi.pt = point;
    if(SubItemHitTest(&hi) != -1 )//没有点中条目就不管
    {if(m_col==-1||//-1 还没被选过
           true==(m_col+m_validate)->Validate (m_row))
       {
m_row = hi.iItem, m_col= hi.iSubItem;//m_row,m_col成
//员分别跟踪选中(的)行列
}
((m_col+m_validate))->Move (_GetRect(),m_row);
    }
}
 
WinBlast* CValidateList::SetValidate( WinBlast*in)//设置验证(的)
//控件群,in对应第一列,in+1第二列……
{
    WinBlast*ret=m_validate;
    m_validate=in;
    int counts=GetHeaderCtrl()->GetItemCount();;
    RECT rect;
     memset(&rect,0,sizeof(rect));
    for(int i=0;i<counts;++i)
         (in+i)->Create (this,rect,IDCHAILD+i,i);
    m_col=-1;//没有被选中(的)
    return ret;
}
 
 
RECT CValidateList::_GetRect()//内部使用,(得)到相应显示位置
{
    CRect ret;
GetSubItemRect(m_row,m_col,LVIR_BOUNDS,ret);
return ret;
}
 
void CValidateList::NoSelect()//置未选中状态
{
m_col=-1;//没有被选中(的)
}
看到了WinBlast*ret=m_validate吧.WinBlast是用来修改和验证数据(的)控件看它们(的)实现:
class WinBlast 
{
    int m_col;//跟踪列,为什么要这个?因为你们可以让一种控件对
//不同列用不同(的)验证策略
CWnd* m_win;//你们(的)控件窗口
    CListCtrl *m_parent;//用它们获(得)文本
public:
    WinBlast(){m_win=NULL;}
    ~WinBlast(){m_win->DestroyWindow();delete m_win;}
 
virtual    bool Create( CWnd* pParentWnd,
       const RECT& rect, UINT nID,
       int col)
    {
        m_col=col;m_parent=(CListCtrl *)pParentWnd;
        m_win=new CEdit;
            return  ((CEdit*)m_win)->
           Create(ES_NOHIDESEL,rect,pParentWnd,nID); 
       }
    void Move(const RECT &rect,int row)//最重要(的)函数但前面
//两个动作是必作(的),SetText为虚,你们在那做你们喜欢(的)
    {
        m_win->ShowWindow(SW_SHOW);
        m_win->MoveWindow(&rect);
        SetText(row);
    }
    virtual bool Validate(int row)//验证,虚函数.这里永远返回true
    {
        m_win->ShowWindow(SW_HIDE);
        CString set;
        m_win->GetWindowText(set);
        m_parent->SetItemText(row,m_col,set);
        return true;
    }
    virtual void SetText(int row)
    {
        m_win->SetWindowText(m_parent->GetItemText(row,m_col));

list control 应用(转载)相关推荐

  1. MAC电脑外设键盘如何更改command为control键MAC电脑外设键盘如何更改command为control键...

    MAC电脑外设键盘如何更改command为control键 转载于:https://www.cnblogs.com/zhujiabin/p/4828019.html

  2. 配置Java远程监控授权(Java Mission Control)

    配置Java远程监控授权(Java Mission Control) 转载URL:  http://www.icoolxue.com/blog/show/9 最近公司做的项目有比较严重的内存溢出问题, ...

  3. 编写 Shell 脚本的最佳实践

    转自:http://kb.cnblogs.com/page/574767/ 前言 由于工作需要,最近重新开始拾掇shell脚本.虽然绝大部分命令自己平时也经常使用,但是在写成脚本的时候总觉得写的很难看 ...

  4. [linux]Linux挂载光盘,解压光盘内的tar安装包,并安装软件(Install VMware Tools in a Linux Guest)...

    挂载光盘,解压光盘内的tar安装包,并安装(Install VMware Tools in a Linux Guest) 下面是vmware帮助文档里在linux下安装vmware tools的步骤, ...

  5. 卷积神经网络要点解析

    参照: [stanford CS231n]Convolutional Neural Networks (CNNs / ConvNets) [karpathy]ConvNetJS CIFAR-10 de ...

  6. 问题集锦(30-35)

    Problem 30 关于C和C++混合编程问题? Ans: 如果C++程序要调用已经被编译后的C函数,该怎么办?假设某个C函数的声明如下: void foo(int x, int y); 该函数被C ...

  7. ascx页面获取标签的通用方法

    function GetInput1(tagname)     {         var input= document.getElementsByTagName("input" ...

  8. Oracle数据库实用脚本

    以下是Maclean.Liu所编写或收集的Oracle数据库实用脚本的列表,在这里分享一下: Script:收集Enterprise Manager Grid Control/Agent/Databa ...

  9. Modal提示框插件的使用

    之前有记录过类似美化alert(),confirm()和prompt功能的插件xcConfirm,其优点是比较轻量级,能够快速接入,对于简单的提示效果明显,但其缺点就是自定义起来不方便,所以就记录一款 ...

  10. 如何在page_load方法判断是服务器端控件引发的page_load方法

    动态获取单击的服务器端控件的id值 private string getPostBackControlName() { Control control=null; string ctrlname = ...

最新文章

  1. 交叉熵损失函数在多分类深度学习中的应用 转
  2. 第十三周项目三-形状类族中的纯虚函数
  3. 深度学习(二十)基于Overfeat的物体检测-2014 ICLR-未完待续
  4. stl源码剖析_《STL源码剖析》学习笔记——空间配置器
  5. 每天一道LeetCode-----合并两个/多个有序链表为一个新链表
  6. TikZ绘图示例——尺规作图: 椭圆的近似画法
  7. python 图片拼接成固定行列
  8. c++ 中文 base64加密_这次有点骚了,破解安卓某 APP 低层加密
  9. Landsat9卫星简介
  10. IntelliJ IDEA使用技巧(二)——添加jar包
  11. Matlab函数——crandn
  12. 健康管理师可以从事哪些工作
  13. 程序员出差如何高效工作?
  14. Entity Framework Code First 学习日记(4)
  15. pyd文件逆向(二)
  16. lisp方格网法计算土方量_方格网法计算土方量教材及例题
  17. 鸿蒙系统1004无标题,win10 10041更新提示错误怎么处理
  18. 关于找不到www.jetbrains.com的服务器IP地址
  19. 基于颜色特征的图像检索(一)
  20. 中国计算机学会2022年度CCF会士名单公布 阿里云李飞飞等9位当选

热门文章

  1. 练习1.account表 添加一条记录
  2. 一图总结:软件测试原则|策略|模型|生命周期
  3. unity 开发射击打靶vr_【好玩微信小游戏大全】香肠派对:点开既玩的射击小游戏!正版授权...
  4. Python 猜数字游戏
  5. mysql导出数据dump_MYSQL使用mysqldump导出表的部分数据
  6. php 生成器 封装,php生成器
  7. eclipse使用python_【转】使用Python的IDE:Eclipse+PyDev
  8. labview与单片机正弦信号_LabVIEW小白入门——低通滤波器
  9. 卸载jlink驱动出现Could not open INSTALL.LOG file错误解决方案
  10. git在远程关联和push时出现问题