[转]可编辑子项的CListCtrl类
来源:互联网 发布:php memcache 扩展 编辑:程序博客网 时间:2024/06/08 18:50
Technorati 标签: VC,ListCtrl
原文地址:http://www.vckbase.com/document/viewdoc/?id=1853
可编辑子项的CListCtrl类
作者:Nobita
关键词:可编辑子项 CListCtrl
摘 要:本文对CListCtrl控件进行了一个扩展,使它即可以编辑主项(Item),又可以编辑子项(SubItem),并尽量符合CListCtrl的操作习惯。
一、说明
大家都知道在MFC中通过给CListCtrl设置LVS_EDITLABELS属性,并且在程序中响应控件的LVN_ENDLABELEDIT消息可以修改列表控件每一行的第一项,也就是主项(Item)。代码如下:
void CEditListCtrlSampleDlg::OnEndlabeleditList1(NMHDR* pNMHDR, LRESULT* pResult) {LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;// TODO: Add your control notification handler code here*pResult = TRUE; //TRUE值表示可以修改主项,FALSE值表示不修改主项}但是让人郁闷的是,微软留了一手,CListCtrl不支持直接修改子项(SubItem)。无奈之下只好自力更生,对CListCtrl进行扩展。>_
二、原理
通过在浩如烟海的互联网上查找资料(当然包括了大名鼎鼎的VCKBASE),发现现有的实现大都是对子项鼠标单击一次就可以编辑。但本人对CListCtrl的单击一次高亮文本,再单击一次才开始编辑的操作模式感觉比较喜欢,所以就有了这篇文章的诞生。
要想实现高亮文本也就是对文本进行着色处理,这可以通过对NM_CUSTOMDRAW消息进行处理实现,但是类向导中没有这个消息映射只能进行手工添加。
要想编辑文本则可以通过EditLabel(int nItem)成员函数以及对LVN_BEGINLABELEDIT和LVN_ENDLABELEDIT的消息处理实现。
三、实现
本文最终实现的CEditListCtrl扩展类在尽量符合CListCtrl操作步骤的情况下实现对主项及子项的可编辑。
成员变量说明:
int m_iItem; //主项标识符
int m_iSubItem; //子项标识符
BOOL m_bFocus; //是否绘制项文本焦点框
BOOL m_bHighLight; //是否高亮项文本
CItemEdit m_edtItemEdit; //用于子类化EditLabel函数返回的CEdit*指针
列表控件中所有项文本的绘制以及特效(焦点框、高亮)都在NM_CUSTOMDRAW消息处理中实现:
void CEditListCtrl::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult)
{
NMLVCUSTOMDRAW* pNMLVCustomDraw = (NMLVCUSTOMDRAW*)pNMHDR;
// Take the default processing unless we set this to something else below.
*pResult = CDRF_DODEFAULT;
// First thing - check the draw stage. If it's the control's prepaint
// stage, then tell Windows we want messages for every item.
if (pNMLVCustomDraw->nmcd.dwDrawStage == CDDS_PREPAINT)
{
*pResult = CDRF_NOTIFYITEMDRAW;
}
else if (pNMLVCustomDraw->nmcd.dwDrawStage == CDDS_ITEMPREPAINT)
{
// This is the notification message for an item. We'll request
// notifications before each subitem's prepaint stage.
*pResult = CDRF_NOTIFYSUBITEMDRAW;
}
else if (pNMLVCustomDraw->nmcd.dwDrawStage == (CDDS_ITEMPREPAINT | CDDS_SUBITEM))
{
//当前要绘制的主项标识符和子项标识符
int iItem = (int)pNMLVCustomDraw->nmcd.dwItemSpec;
int iSubItem = pNMLVCustomDraw->iSubItem;
CDC* pDC = CDC::FromHandle(pNMLVCustomDraw->nmcd.hdc);
CString strItemText = GetItemText(iItem, iSubItem);
CRect rcItem, rcText;
GetSubItemRect(iItem, iSubItem, LVIR_LABEL, rcItem);
rcText = rcItem;
CSize size = pDC->GetTextExtent(strItemText);
if(strItemText == _T(""))
{
size.cx = 41;
}
//设置文本高亮矩形
rcText.left += 4;
rcText.right = rcText.left + size.cx + 6;
if(rcText.right > rcItem.right)
{
rcText.right = rcItem.right;
}
COLORREF crOldTextColor = pDC->GetTextColor();
//绘制项焦点/高亮效果
if(m_bFocus)
{
if((m_iItem == iItem) && (m_iSubItem == iSubItem))
{
if(m_bHighLight)
{
pDC->SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
pDC->FillSolidRect(&rcText, ::GetSysColor(COLOR_HIGHLIGHT));
}
pDC->DrawFocusRect(&rcText);
}
}
//绘制项文本
rcItem.left += 6;
pDC->DrawText(strItemText, &rcItem, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS | DT_NOCLIP);
pDC->SetTextColor(crOldTextColor);
*pResult = CDRF_SKIPDEFAULT;// We've painted everything.
}
}
void CEditListCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
m_bFocus = TRUE;
LVHITTESTINFO lvhit;
lvhit.pt = point;
int item = SubItemHitTest(&lvhit);
//if (over a item/subitem)
if (item != -1 && (lvhit.flags & LVHT_ONITEM))
{
CListCtrl::OnLButtonDown(nFlags, point);
if(m_bHighLight && m_iItem == lvhit.iItem && m_iSubItem == lvhit.iSubItem)
{
//第二次单击
EditLabel(m_iItem);
return;
}
else
{
//第一次单击
m_iItem = lvhit.iItem;
m_iSubItem = lvhit.iSubItem;
m_bHighLight = TRUE;
}
}
else
{
if(m_edtItemEdit.m_hWnd == NULL)
{
//未出现文本编辑框时
m_bHighLight = FALSE;
}
CListCtrl::OnLButtonDown(nFlags, point);
}
Invalidate(); //强制重绘控件
}
void CEditListCtrl::OnBeginlabeledit(NMHDR* pNMHDR, LRESULT* pResult)
{
LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
if (m_iSubItem >= 0)
{
ASSERT(m_iItem == pDispInfo->item.iItem);
CRect rcSubItem;
GetSubItemRect( pDispInfo->item.iItem, m_iSubItem, LVIR_BOUNDS, rcSubItem);
//get edit control and subclass
HWND hWnd= (HWND)SendMessage(LVM_GETEDITCONTROL);
ASSERT(hWnd != NULL);
VERIFY(m_edtItemEdit.SubclassWindow(hWnd));
//move edit control text 4 pixel to the right of org label,
//as Windows does it...编辑框定位
m_edtItemEdit.m_iXPos = rcSubItem.left + 4;
m_edtItemEdit.SetWindowText(GetItemText(pDispInfo->item.iItem, m_iSubItem));
}
*pResult = 0;
}
void CEditListCtrl::OnEndlabeledit(NMHDR* pNMHDR, LRESULT* pResult)
{
LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
LV_ITEM *plvItem = &pDispInfo->item;
if (m_iSubItem >= 0)
{
if (plvItem->pszText != NULL )
{
SetItemText(plvItem->iItem,m_iSubItem, plvItem->pszText);
}
VERIFY(m_edtItemEdit.UnsubclassWindow()!=NULL);
*pResult = 0;
}
//编辑文本时对控件父窗口操作(如单击其它控件)引发"OnEndlabeledit"时刷新控件
CRect rect;
GetWindowRect(&rect);
CPoint point;
::GetCursorPos(&point);
if(!rect.PtInRect(point))
{
m_iItem = -1;
m_iSubItem = -1;
m_bFocus = FALSE;
m_bHighLight = FALSE;
}
}
四、参考资料
1. Simplified Subitem Editing
http://www.codeguru.com/cpp/controls/listview/editingitemsandsubitem/article.php/c4175/
2. 可设置单元格颜色的ClistCtrl类
http://www.vckbase.com/document/viewdoc/?id=891
- 可编辑子项的CListCtrl类
- 可编辑子项的CListCtrl类
- 可编辑子项的CListCtrl类
- 可编辑子项的CListCtrl类
- 可编辑子项的CListCtrl类
- 可编辑子项的CListCtrl类
- 可编辑子项的CListCtrl类
- 可编辑子项的CListCtrl类
- [转]可编辑子项的CListCtrl类
- CListCtrl 报表风格,可编辑子项的完美实现
- 可编辑子项的CListCtrl类(失去焦点时,CEdit消息被屏蔽的问题)
- 可编辑的CListCtrl
- 可编辑的CListCtrl
- CListCtrl 编辑子项
- MFC--CListCtrl的两个扩展:可设置单元格(子项)颜色属性、可编辑单元格(子项)
- 使CListCtrl可编辑(转)
- MFC 基于CListCtrl类的可编辑列表类
- 可编辑单元格的CListCtrl控件
- mysql 搜索 正则匹配 计算
- gcc 几个常用选项
- Javascript 处理 Ctrl+s 和 Tab 按键响应事件
- FCKeditor(2.6)自定义工具栏
- Face book API,Twitter API 及其调用
- [转]可编辑子项的CListCtrl类
- 生活
- Javascript 在 HTML 页面光标处输入字符
- JAVA企业应用的反思--编写自己的容器--名字叫《蜗居》
- [转]导出CListCtrl控件到Excel文件
- GDB使用方法
- IE 8 下载控件出错
- 又是他们 我的英语
- 办了护照和洪澳通行证