zoukankan      html  css  js  c++  java
  • 【转】VC 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;
    }

  • 相关阅读:
    java例程练习(简单的画图程序[鼠标事件处理])
    java例程练习(事件监听机制)
    java例程练习(布局管理器[FlowLayout])
    java例程练习(网络编程[简单UDP通信试验])
    java例程练习(BorderLayou&GridLayout)
    java例程练习(关于内部类的一个非常重要的作用)
    java例程练习(Graphics类[paint()方法])
    java例程练习(TextField)
    Service Broker 常见问题
    ubuntu8.04 和 Fedora 9
  • 原文地址:https://www.cnblogs.com/vic_lu/p/2035439.html
Copyright © 2011-2022 走看看