这篇文章提供了一个子类化列表控件中编辑控件的方法。与其他使用LVM_GETEDITCONTROL进行子类化不同,我使用一种更简捷的方法。步骤如下:
变量
public:
CSubEdit m_editWnd;
int m_item;
int m_subitem;
CSubeditListView::CSubeditListView()
{
m_subitem = 0;
}
监视鼠标点击动作
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);
}
调用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;
}
定位编辑控件
void CSubEdit::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)
{
lpwndpos->x=m_x;
CEdit::OnWindowPosChanging(lpwndpos);
}
调用paint函数
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();
}
调用OnSize函数,使列表控件大小改变时不能进行编辑工作
void CSubeditListView::OnSize(UINT nType, int cx, int cy)
{
//stop editing if resizing
if( GetFocus() != this ) SetFocus();
CListView::OnSize(nType, cx, cy);
}
调用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;
}