Simplified Subitem Editing

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

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read