zoukankan      html  css  js  c++  java
  • VC List Control控件高级使用

    最近使用到了List Control控件。使用中,要求不但能够在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;
    }
    本篇文章来源于 www.87717.com 原文链接:http://www.87717.com/vc/vc_11899_2.html

  • 相关阅读:
    ffmpeg rtmp推流 视频转码
    java日志发展史 log4j slf4j log4j2 jul jcl 日志和各种桥接包的关系
    nginx stream 流转发,可以转发rtmp、mysql访问流,转发rtmp、jdbc请求
    java web http 转https 通过nginx代理访问
    linux 服务器磁盘挂载
    novnc 通过websockify代理 配置多点访问
    linux 文件服务 minio 安装部署配置
    AOP实现原理,手写aop
    java 泛型
    JAVA反射getGenericSuperclass()用法
  • 原文地址:https://www.cnblogs.com/ganmk/p/1788234.html
Copyright © 2011-2022 走看看