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!
- Vars
public:
CSubEdit m_editWnd;
int m_item;
int m_subitem;CSubeditListView::CSubeditListView()
{
m_subitem = 0;
}
- 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);
}
- 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;}
- Positioning the editcontrol
void CSubEdit::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)
{
lpwndpos->x=m_x;CEdit::OnWindowPosChanging(lpwndpos);
}
- 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();
}
- Handle resizing
void CSubeditListView::OnSize(UINT nType, int cx, int cy)
{
//stop editing if resizing
if( GetFocus() != this ) SetFocus();CListView::OnSize(nType, cx, cy);
}
- 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;}