Simplified Subitem Editing

Friday Jan 3rd 2003 by Gunnar Andre Dalsnes
Share:

A way to subclass the listview edit control.



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
    public:
      CSubEdit m_editWnd;
      int m_item;
      int m_subitem;
    
    CSubeditListView::CSubeditListView()
    {
      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);
          }
        else
          {
          CListView::OnLButtonDown(nFlags, point);
    
          m_subitem = lvhit.iSubItem;
          m_item = item;
          GetListCtrl().EditLabel(item);
          }
    
        }
      else
        CListView::OnLButtonDown(nFlags, point);
    }
    
  3. Handle OnBeginLabelEdit
    void CSubeditListView::OnBeginLabelEdit(NMHDR* pNMHDR,
        LRESULT* pResult)
    {
      LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
    
      //if (subitem selected for editing)
      if (m_subitem)
        {
        ASSERT(m_item == pDispInfo->item.iItem);
    
        CRect  subrect;
        GetListCtrl().GetSubItemRect( pDispInfo->item.iItem,
                                      m_subitem,
            LVIR_BOUNDS , subrect );
    
        //get edit control and subclass
        HWND hWnd=(HWND)SendMessage(LVM_GETEDITCONTROL);
        ASSERT(hWnd!=NULL);
        VERIFY(m_editWnd.SubclassWindow(hWnd));
    
        //move edit control text 1 pixel to the right of org label,
        //as Windows does it...
        m_editWnd.m_x=subrect.left + 6; 
        m_editWnd.SetWindowText(GetListCtrl().GetItemText
            (pDispInfo->item.iItem,m_subitem));
    
        //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;
        GetListCtrl().GetSubItemRect(pDispInfo->item.iItem,m_subitem,
            LVIR_LABEL ,rect);
        CDC* hDc = GetDC();
        hDc->FillRect(rect,&CBrush(::GetSysColor(COLOR_WINDOW)));
        ReleaseDC(hDc);
    
        }
    
      //return: editing permitted
      *pResult = 0;
    
    }
    
  4. Positioning the editcontrol
    void CSubEdit::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)
    {
      lpwndpos->x=m_x;
    
      CEdit::OnWindowPosChanging(lpwndpos);
    }
    
  5. Handle painting
    void CSubeditListView::OnPaint()
    {
      //if (subitem editing)
      if (m_subitem)
        {
    
        CRect  rect;
        CRect  editrect;
    
        GetListCtrl().GetSubItemRect(m_item,m_subitem,LVIR_LABEL,
                                     rect);
    
        m_editWnd.GetWindowRect(editrect);
        ScreenToClient(editrect);
    
        //block text redraw of the subitems text (underneath the
        //editcontrol)
        //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 ;
          ValidateRect(rect);
          }
    
        //block filling redraw of leftmost item (caused by FillRect)
        GetListCtrl().GetItemRect(m_item,rect,LVIR_LABEL );
        ValidateRect(rect);
        }
    
      CListView::OnPaint();
    }
    
  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 )
          GetListCtrl().SetItemText(plvItem->iItem,m_subitem,
              plvItem->pszText);
    
        VERIFY(m_editWnd.UnsubclassWindow()!=NULL);
    
        m_subitem = 0;
        //always revert to org label (Windows thinks we are editing
        //the leftmost item)
        *pResult = 0;
        }
      else
        //return: update label on leftmost item
        *pResult = 1;
    
    }
    

Downloads

Download exe - 10 Kb
Download source - 40 Kb
Share:
Home
Mobile Site | Full Site
Copyright 2017 © QuinStreet Inc. All Rights Reserved