可编辑列表控件
作者:Captainliyun
常常在各个论坛上看到有朋友在问关于ListCtrl要编辑各个ITEM的内容的问题。闲来无事,就写了点代码,实现了一个可以编辑的ListCtrl.
要实现ListCtrl编辑功能,其实也简单,只需要在响应一个开始编辑的消息时(比如:鼠标左键双击控件时)获取当前点击的Item和SubItem的序号,获得它的位置,然后在这个位置显示一个CEdit控件就可以实现编辑功能。以下详细介绍实现:
//响应鼠标双击
void CEditListCtrl::OnLButtonDblClk(UINT nFlags, CPoint point)
{
CRect rcCtrl;
LVHITTESTINFO lvhti;
lvhti.pt = point;
int nItem = CListCtrl::SubItemHitTest(&lvhti);// 测试鼠标当前选中的ITEM和SUBITEM
if(nItem == -1)
return;
int nSubItem = lvhti.iSubItem;
CListCtrl::GetSubItemRect(nItem,nSubItem,LVIR_LABEL,rcCtrl);//获取选中位置的区域
//显示EDIT
ShowEdit(TRUE,nItem,nSubItem,rcCtrl);
CListCtrl::OnLButtonDblClk(nFlags, point);
}
//显示EDIT
void CEditListCtrl::ShowEdit(BOOL bShow,int nItem,int nIndex,CRect rcCtrl)
{
//只需要创建一次EDIT控件,如果控件没有创建,就创建EDIT.如果控件已经创建了,就控制是显示还是隐藏
if(m_edit.m_hWnd == NULL)
{
m_edit.Create(ES_AUTOHSCROLL|WS_CHILD|ES_LEFT|ES_WANTRETURN|WS_BORDER,CRect(0,0,0,0),this,IDC_EDIT);
m_edit.ShowWindow(SW_HIDE);
CFont tpFont;
tpFont.CreateStockObject(DEFAULT_GUI_FONT);
m_edit.SetFont(&tpFont);
tpFont.DeleteObject();
}
if(bShow == TRUE)
{
CString strItem = CListCtrl::GetItemText(nItem,nIndex);
m_edit.MoveWindow(rcCtrl);
m_edit.ShowWindow(SW_SHOW);
m_edit.SetWindowText(strItem);
::SetFocus(m_edit.GetSafeHwnd());
m_edit.SetSel(-1);
m_edit.SetCtrlData(MAKEWPARAM(nIndex,nItem));
}
else
m_edit.ShowWindow(SW_HIDE);
}
}
//编辑停止的时候
/*
本例在实现的时候,子类化了一个EDIT类CListCtrlEdit。
当EDIT控件失去焦点的时候,将发送一个WM_USER_EDIT_END消息到ListCtrl
ListCtrl的响应函数如下
*/
void CEditListCtrl::OnEditEnd(WPARAM wParam,LPARAM lParam)
{
if(wParam == TRUE)
{
CString strText(_T(""));
m_edit.GetWindowText(strText);
DWORD dwData = m_edit.GetCtrlData();
int nItem= dwData>>16;
int nIndex = dwData&0x0000ffff;
CListCtrl::SetItemText(nItem,nIndex,strText);
}
else
{
}
if(lParam == FALSE)
m_edit.ShowWindow(SW_HIDE);
}
其实也没有什么好说的,要实现这样一个功能的控件不算难,主要是在处理EDIT控件和LIST控件交互的时候,可能会有些麻烦,比如:在什么时候应该隐藏EDIT控件等等问题,这个也是我为什么要子类化一个EDIT的原因。
另外,本控件还支持TAB跳转以及Shift+Tab这两个是横向跳转。
使用Ctrl+Tab将实现纵向跳转。实现这两个功能主要是想到在编辑时可以加快速度。:)
谢谢各位,如有什么问题,可以提出改正。