Virtual Developer Workshop: Containerized Development with Docker

Click here for a larger image.

Environment: VC6 SP5

This article suggests a way to subclass the listviews edit control, but unlike the article "Editing listview Subitems Using LVM_GETEDITCONTROL," it uses a much simpler and hopefully better method. Give it a try!

  1. Vars
      CSubEdit m_editWnd;
      int m_item;
      int m_subitem;
      m_subitem = 0;
  2. Detect subitem mouse clicks
    void CSubeditListView::OnLButtonDown(UINT nFlags, CPoint point)
      LVHITTESTINFO  lvhit;
      lvhit.pt = point;
      int item = GetListCtrl().SubItemHitTest(&lvhit);
      //if (over a subitem)
      if (item != -1 && lvhit.iSubItem && (lvhit.flags & 
                        LVHT_ONITEM ))
        //mouse click outside the editbox in an already
        //editing cell cancels editing
        if (m_subitem == lvhit.iSubItem && item == m_item)
          CListView::OnLButtonDown(nFlags, point);
          CListView::OnLButtonDown(nFlags, point);
          m_subitem = lvhit.iSubItem;
          m_item = item;
        CListView::OnLButtonDown(nFlags, point);
  3. Handle OnBeginLabelEdit
    void CSubeditListView::OnBeginLabelEdit(NMHDR* pNMHDR,
        LRESULT* pResult)
      //if (subitem selected for editing)
      if (m_subitem)
        ASSERT(m_item == pDispInfo->item.iItem);
        CRect  subrect;
        GetListCtrl().GetSubItemRect( pDispInfo->item.iItem,
            LVIR_BOUNDS , subrect );
        //get edit control and subclass
        HWND hWnd=(HWND)SendMessage(LVM_GETEDITCONTROL);
        //move edit control text 1 pixel to the right of org label,
        //as Windows does it...
        m_editWnd.m_x=subrect.left + 6; 
        //hide subitem text so it don't show if we delete some
        //text in the edit control
        //OnPaint handles other issues also regarding this
        CRect  rect;
            LVIR_LABEL ,rect);
        CDC* hDc = GetDC();
      //return: editing permitted
      *pResult = 0;
  4. Positioning the editcontrol
    void CSubEdit::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)
  5. Handle painting
    void CSubeditListView::OnPaint()
      //if (subitem editing)
      if (m_subitem)
        CRect  rect;
        CRect  editrect;
        //block text redraw of the subitems text (underneath the
        //if we didn't do this and deleted some text in the edit
        //control, the subitems original label would show
        if (editrect.right < rect.right)
          rect.left = editrect.right ;
        //block filling redraw of leftmost item (caused by FillRect)
        GetListCtrl().GetItemRect(m_item,rect,LVIR_LABEL );
  6. Handle resizing
    void CSubeditListView::OnSize(UINT nType, int cx, int cy)
      //stop editing if resizing
      if( GetFocus() != this ) SetFocus();
      CListView::OnSize(nType, cx, cy);
  7. Handle OnEndLabelEdit
    void CSubeditListView::OnEndLabelEdit(NMHDR* pNMHDR,
                                          LRESULT* pResult)
      LV_DISPINFO *plvDispInfo = (LV_DISPINFO *)pNMHDR;
      LV_ITEM  *plvItem = &plvDispInfo->item;
      //if (end of sub-editing) do cleanup
      if (m_subitem)
        //plvItem->pszText is NULL if editing canceled
        if (plvItem->pszText != NULL )
        m_subitem = 0;
        //always revert to org label (Windows thinks we are editing
        //the leftmost item)
        *pResult = 0;
        //return: update label on leftmost item
        *pResult = 1;


Download exe - 10 Kb
Download source - 40 Kb


  • CDialog

    Posted by break; on 08/04/2006 11:13am

    Great stuff, but how to use it in an dialog application with CListCtrl? In my case the message "OnLButtonDown" dont take an efect for my CListCtrl, only for my dialog! thanks break;

  • Better edit box creation timing

    Posted by swedishbricks on 02/17/2006 01:19am

    If you replace the handler for WM_LBUTTONDOWN with a handler for NM_CLICK that looks like this:
    LRESULT CEditListView::OnClick(LPNMHDR nmhdr)
        LPNMITEMACTIVATE    nmia = \ reinterpret_cast(nmhdr);
        LVHITTESTINFO       lvhit;
        lvhit.pt = nmia->ptAction;
        int                 HitItem = SubItemHitTest(&lvhit);
        // If the click was on a subitem text of a selected   
        // item and we are not already editing something
        if (HitItem != -1 && lvhit.iSubItem > 0 && 
            (lvhit.flags & LVHT_ONITEMLABEL) != 0 &&
            GetSelectedCount() > 0 && 
            GetItemState(HitItem, LVIS_SELECTED) != 0 &&
            GetEditControl() == NULL)
            // Remember the subitem that we are working on here
            m_Item = HitItem;
            m_Subitem = lvhit.iSubItem;
        // Let the default handling do it's thing
        // NM_CLICK doesn't care about the return value
        return 0;
    ... you will get the edit box displayed with the same delayed timing for subitems as for the main item.
    -- Matt

  • Problem using CListCtrl

    Posted by Legacy on 12/16/2003 08:00am

    Originally posted by: Shashi Prabhakar

    Your solution is very simple and elegant.  I was wondering what changes you would suggest making to your code to make it work with CListCtrl (instead of CListView).

    My efforts at doing this thus far have run into the following problems:

    a) If I edit the second (of two) columns, the text in the first column disappears. It returns when the edit operation is ended.

    b) Inclusion of the OnPaint method results in the contents of the List control not being displayed (I do not know why). Also, the application seemed to slow down considerably. I must note here that I apparently cannot call CListCtrl::OnPaint directly from the OnPaint handler in my derived class, since MFC expressly forbids this in the comments of the handler. The only way I could see the list control's contents was if I do NOT override the WM_PAINT handler. I have tried other ways of updating the window (Invalidate, UpdateWindow, etc) to no avail.

    c) Removal of the OnPaint method resulted in the problem of seeing original text below the edit control if you erased the text in the edit control (reason is obvious from the code).

    Any help you can offer would be much appreciated,



    • Problem using CListCtrl

      Posted by TPS on 02/18/2015 09:43am

      Is there any solution to the 1st point of problem a) If I edit the second (of two) columns, the text in the first column disappears. It returns when the edit operation is ended.

    • Problem using CListCtrl

      Posted by imbtf on 06/27/2004 04:50pm

      Make sure "CPaintDC dc(this);" is NOT present in your OnPaint(); Also, at the end of OnPaint(), immedtiately before it returns call "DefWindowProc(WM_PAINT, NULL, NULL);" This will remove the problem of the first item not being displayed when editing subitems.

    • CListCtrl

      Posted by hankdane on 06/02/2004 02:32am

      I used the control with a CListCtrl, and it works just fine. I just removed all calls to GetListCtrl(). I also see the text disappearence problem. If I find a solution, I will post it here.

  • beginner's question

    Posted by Legacy on 11/10/2003 08:00am

    Originally posted by: gatsby

    i need help, guys:
    i need to use the editable item and subitem on a dialog based application. what should i do?

    • Use the Control

      Posted by hankdane on 06/02/2004 02:35am

      You can use Gunnar's control from a dialog based application. I did.

  • Bug plus solution

    Posted by Legacy on 07/17/2003 07:00am

    Originally posted by: Sander


    Great stuff. Been having one problem, though.

    When the view is resized or populated so that a vertical scroll bar is necessary, a problem occurs when exiting the application.

    This only happens in debug mode and the call stack at the particular point is very unclear, as "our list view class" is nowhere in it.
    Though, it seems to have to do with the OnSize implementation of this solution.

    I think that this:

    if( GetFocus() != this ) SetFocus();

    ...should be something like this:

    if( "in edit mode" )
    if( GetFocus() != this ) SetFocus();

    However, if you look at how Windows does this normally for you (thus when editing the main item, not a sub item) just leaving this out immitates best the normal behaviour. Ergo; I removed the OnSize method and am happy again.

    Good luck with it.



  • Urgent Help Needed

    Posted by Legacy on 07/09/2003 07:00am

    Originally posted by: Gary

    The list control is wonderful. But, I have one problem. Just as we have CBN_SELCHANGE message in combobox to trap the change of selection event, what event shall I use in this list control? Basically, I want to display related records in a different grid when the selection in list control changes. I could not find the event to do this.
    Please help me.


    - Gary

  • OnLButtonDown?

    Posted by Legacy on 06/02/2003 07:00am

    Originally posted by: real name

    it looks different to system logic (and btw breaks dnd)

  • horizontal scrolling - tip

    Posted by Legacy on 03/12/2003 08:00am

    Originally posted by: marcus gesing

    Here is some example code if you want to make this
    solution work even when the user scrolls the list:

    old: int m_x;
    new: RECT m_rcSubItem;

    old: lpwndpos->x = m_x;
    lpwndpos->x = m_rcSubItem.left;
    lpwndpos->y = m_rcSubItem.top;
    lpwndpos->cx = m_rcSubItem.right;
    lpwndpos->cy = m_rcSubItem.bottom;

    old: m_editWnd.m_x = subrect.left + 6;
    m_editWnd.m_rcSubItem.left = subrect.left + 6;
    m_editWnd.m_rcSubItem.top = subrect.top;
    m_editWnd.m_rcSubItem.bottom = subrect.bottom - subrect.top;

    SIZE sz;
    CString cs(GetListCtrl().GetItemText(pDispInfo->item.iItem,m_subitem));
    ::GetTextExtentPoint32(m_editWnd.GetDC()->m_hDC, cs, cs.GetLength(), &sz);
    m_editWnd.m_rcSubItem.right = (sz.cx < 20 ? 20 : sz.cx); // or another min value

    Another tip:
    Forget about all the painting stuff. Just declare a CString
    member in SubEdit1.h to safe the original subitem text and
    empty this text. If the user cancels the operation just
    restore it from the CString member.

  • ASSERT failure

    Posted by Legacy on 02/07/2003 08:00am

    Originally posted by: Luke Johnston

    When a lot of items are added, say 100, I get an ASSERT failure in wincore.cpp upon exiting the program.

    Any ideas?

  • Thanks and bug

    Posted by Legacy on 01/28/2003 08:00am

    Originally posted by: Sylvain PEYRUQUEOU

    Thank you very much for your code, it was exactly what I need.

    However, I observe a bug when I click on a cell which is being edited. Is there anybody who has the same ?

  • Loading, Please Wait ...

  • You must have javascript enabled in order to post comments.

Leave a Comment
  • Your email address will not be published. All fields are required.

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date