MFC 重载CListCtrl实现可编辑功能

  1. 头文件

  2. #if !defined(AFX_MYLISTCTRLEDIT_H__7FDA9396_E298_4F10_B778_EB8ADFD82F9A__INCLUDED_)
    #define AFX_MYLISTCTRLEDIT_H__7FDA9396_E298_4F10_B778_EB8ADFD82F9A__INCLUDED_
    #if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000
    // MyListCtrl.h : header file
    //
    //#define IDC_MY_LIST_EDITBOX 0xffff
    #define MLSM_ITEMCHANGED (WM_USER + 200)
    /////////////////////////////////////////////////////////////////////////////
    // CMyListCtrl window
    #include "afxcmn.h"
    class CMyListCtrlEdit : public CListCtrl //可编辑
    {
    // Construction
    public:
     CMyListCtrlEdit(){};
    // Attributes
    public:
     int m_Flag;
    // Operations
    public:
    
    
     // ClassWizard generated virtual function overrides
     //{{AFX_VIRTUAL(CMyListCtrl)
     public:
     virtual BOOL PreTranslateMessage(MSG* pMsg);
     //}}AFX_VIRTUAL
    // Implementation
    public:
     virtual
      ~CMyListCtrlEdit(){};
     CEdit m_EditItem;
     // Generated message map functions
    protected:
     
     int m_Row;
     int m_Col;
     
     //{{AFX_MSG(CMyListCtrl)
     afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
     afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
     //afx_msg void OnNMKillfocusEdit(NMHDR *pNMHDR, LRESULT *pResult);
     afx_msg void OnKillfocusEdit();
     //afx_msg void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct);//行高
     //afx_msg void CMyListCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); 
     //}}AFX_MSG
     DECLARE_MESSAGE_MAP()
    };
    /////////////////////////////////////////////////////////////////////////////
    //{{AFX_INSERT_LOCATION}}
    // Microsoft Visual C++ will insert additional declarations immediately before the previous line.
    #endif
  3. 实现函数

  4. #include "stdafx.h"
    #include "MyListCtrlEdit.h"
    BEGIN_MESSAGE_MAP(CMyListCtrlEdit, CListCtrl)
     ON_WM_LBUTTONDBLCLK()
     ON_WM_LBUTTONDOWN()
     ON_WM_MEASUREITEM()
     ON_EN_KILLFOCUS(IDC_MY_LIST_EDITBOX, OnKillfocusEdit)
     //ON_NOTIFY(TVN_SELCHANGED, IDC_MY_LIST_EDITBOX, &CMyListCtrl::OnNMKillfocusEdit)
    END_MESSAGE_MAP()
    
    /*************************************************************************
    在鼠标左键双击事件中,主要的任务是需要判断被双击的单元格,
    如果单元格有效,则需要进入编辑模式,并显示文本框用来响应用户的输入,代码如下:
    ****************************************************/
    
    void CMyListCtrlEdit::OnLButtonDblClk(UINT nFlags, CPoint point)
    {
     // TODO: Add your message handler code here and/or call default
     /*LVHITTESTINFO hi;
     hi.pt = point;
     if(SubItemHitTest(&hi) != -1 )
     {
      if (hi.iSubItem == 0 || hi.iSubItem == 1)
       goto exit_label;
      m_Row = hi.iItem;
      m_Col = hi.iSubItem;
      if(m_Row == 1 && m_Col == 2)
      {
       m_Flag = 1;
       goto exit_label;
      }
      else
       m_Flag = 0;
      if(m_EditItem.m_hWnd == NULL)
      {
       RECT rect;
       rect.left = rect.top = 0;
       rect.bottom = 20;
       rect.right = 100;
       m_EditItem.Create(WS_CHILD | ES_LEFT | WS_BORDER | ES_AUTOHSCROLL | ES_WANTRETURN | ES_MULTILINE, rect, this, IDC_MY_LIST_EDITBOX);
       m_EditItem.SetFont(this->GetFont(), FALSE);
      }
      CRect rect;
      GetSubItemRect(hi.iItem, hi.iSubItem, LVIR_BOUNDS, rect);
      m_EditItem.SetWindowText(this->GetItemText(hi.iItem, hi.iSubItem));
      m_EditItem.MoveWindow(&rect, TRUE);
      m_EditItem.ShowWindow(1);
     }
    exit_label:*/
     CListCtrl::OnLButtonDblClk(nFlags, point);
    }
    
    /**************************************************************/
    /*在鼠标单击事件中,我们需要判断用户单击的是不是其他的单元格,
    如果是,表示用户希望退出编辑模式了,此时,需要保存编辑之后的文本:
    如果单元格有效,则需要进入编辑模式,并显示文本框用来响应用户的输入*/
    /*************************************************************/
    void CMyListCtrlEdit::OnLButtonDown(UINT nFlags, CPoint point)
    {
     // TODO: Add your message handler code here and/or call default
     CListCtrl::OnLButtonDown(nFlags, point);
     
     LVHITTESTINFO hi;
     hi.pt = point;
     if(SubItemHitTest(&hi) != -1 )
     {
      if (hi.iSubItem == 0 )
       //goto exit_label;
       return;
      m_Row = hi.iItem;
      m_Col = hi.iSubItem;
      if(m_EditItem.m_hWnd == NULL)
      {
       RECT rect;
       rect.left = rect.top = 0;
       rect.bottom = 20;
       rect.right = 100;
       m_EditItem.Create(WS_CHILD | ES_LEFT | WS_BORDER | ES_AUTOHSCROLL | ES_WANTRETURN | ES_MULTILINE, rect, this, IDC_MY_LIST_EDITBOX);
       m_EditItem.SetFont(this->GetFont(), FALSE);
      }
      CRect rect;
      GetSubItemRect(hi.iItem, hi.iSubItem, LVIR_BOUNDS, rect);
      m_EditItem.SetWindowText(this->GetItemText(hi.iItem, hi.iSubItem));
      m_EditItem.MoveWindow(&rect, TRUE);
      m_EditItem.ShowWindow(1);
      m_EditItem.SetSel(0, 100);
      m_EditItem.SetFocus();
     }
    //exit_label: 
     //m_Col = m_Row = -1;
     
    }
    /***********************************************************
    在PreTranslateMessage函数中,需要截获按键时间中的回车键和ESC键,并保存或取消编辑:
    **********************************************************/
    
    BOOL CMyListCtrlEdit::PreTranslateMessage(MSG* pMsg)
    {
     // TODO: Add your specialized code here and/or call the base class
     BOOL bHandledMsg = FALSE;
     if(pMsg->hwnd == m_EditItem.m_hWnd)
     {
      switch (pMsg->message)
      {
      case WM_KEYDOWN:
       {
        switch (pMsg->wParam)
        {
        case VK_RETURN://回车
         if(m_Row != -1)
         {
          CString ItemText;
          m_EditItem.GetWindowText(ItemText);
          this->SetItemText(m_Row, m_Col, ItemText);
          ::PostMessage(GetParent()->m_hWnd, MLSM_ITEMCHANGED, (WPARAM)MAKELONG(m_Row, m_Col), (LPARAM)this->m_hWnd);
         }
        case VK_ESCAPE://ESC键
         m_EditItem.ShowWindow(0);
         m_Col = m_Row = -1;
         bHandledMsg = TRUE;
         break;
        default:
         break;
        }
       }// case WM_KEYDOWN
       break;
      default:
       break;
      }// switch(pMsg->message)
     }// if(pMsg->hwnd
     return (bHandledMsg ? TRUE : CListCtrl::PreTranslateMessage(pMsg));          
    }
    void CMyListCtrlEdit::OnKillfocusEdit()
    {
     if(m_EditItem.m_hWnd != NULL)
     {
      m_EditItem.ShowWindow(0);
      if(m_Row != -1 && m_Row != 1)
      {
       CString ItemText;
       m_EditItem.GetWindowText(ItemText);
       this->SetItemText(m_Row, m_Col, ItemText);
       ::PostMessage(GetParent()->m_hWnd, MLSM_ITEMCHANGED, (WPARAM)MAKELONG(m_Row, m_Col), (LPARAM)this->m_hWnd);
      }
     }
     m_Row = m_Col = -1;
     
     m_EditItem.ShowWindow(0);
     //m_EditItem.SetWindowTextA("");
    }

你可能感兴趣的:(list,mfc,编辑)