CEditableListCtrl类实现代码
EditableListCtrl.h文件
#if!defined(AFX_EDITABLELISTCTRL_H__D931FC67_33E0_4A71_8C4B_2E62FBCA6081__INCLUDED_)
#defineAFX_EDITABLELISTCTRL_H__D931FC67_33E0_4A71_8C4B_2E62FBCA6081__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// EditableListCtrl.h : headerfile
//
/
// CEditableListCtrl window
class CEditableListCtrl : publicCListCtrl
{
// Construction
public:
CEditableListCtrl();
// Attributes
public:
// Operations
public:
// Overrides
//ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CEditableListCtrl)
public:
protected:
virtualvoid PreSubclassWindow();
//}}AFX_VIRTUAL
// Implementation
public:
voidShowEditBox(BOOL isShow, CRect *rc);
virtual~CEditableListCtrl();
//Generated message map functions
public:
voidShowEditBox(BOOL isShow, int iItem, int iSubItem);
//{{AFX_MSG(CEditableListCtrl)
afx_msgvoid OnDblclk(NMHDR* pNMHDR, LRESULT* pResult);
afx_msgvoid OnEditKillFocus();
afx_msgvoid OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
afx_msgvoid OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
afx_msgBOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
private:
intm_CurSelSubItem;//记录当前选择的子项
intm_CurSelItem;//记录当前选择的项
CEditm_Edit;
};
#define UM_LISTEDIT_KILLFOCUS WM_USER+ 1
#define UM_LISTEDIT_DBCLICK WM_USER + 2
/
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ willinsert additional declarations immediately before the previous line.
#endif //!defined(AFX_EDITABLELISTCTRL_H__D931FC67_33E0_4A71_8C4B_2E62FBCA6081__INCLUDED_)
EditableListCtrl.cpp文件
// EditableListCtrl.cpp:implementation of the CEditableListCtrl class.
//
//
#include "stdafx.h"
#include "****.h"
#include"EditableListCtrl.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//
// Construction/Destruction
//
CEditableListCtrl::CEditableListCtrl()
{
m_CurSelSubItem= -1;
m_CurSelItem= -1;
}
CEditableListCtrl::~CEditableListCtrl()
{
}
BEGIN_MESSAGE_MAP(CEditableListCtrl,CListCtrl)
//{{AFX_MSG_MAP(CEditableListCtrl)
ON_NOTIFY_REFLECT(NM_DBLCLK,OnDblclk)
ON_EN_KILLFOCUS(IDC_LISTEDIT,OnEditKillFocus)
ON_WM_HSCROLL()
ON_WM_VSCROLL()
ON_WM_MOUSEWHEEL()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/
// CEditableListCtrl messagehandlers
//显示编辑框
voidCEditableListCtrl::ShowEditBox(BOOL isShow, CRect *rc)
{
ASSERT((isShow&& (rc != NULL)) || !isShow);
if(rc!= NULL)
m_Edit.MoveWindow(rc->left,rc->top, rc->right, rc->bottom, TRUE);
if(isShow)
{
m_Edit.SetFocus();
m_Edit.ShowWindow(SW_SHOW);
}
elseif(!isShow)
m_Edit.ShowWindow(SW_HIDE);
}
//鼠标双击事件处理函数
voidCEditableListCtrl::OnDblclk(NMHDR* pNMHDR, LRESULT* pResult)
{
//TODO: Add your control notification handler code here
LPNMLISTVIEWlpnmlv = (LPNMLISTVIEW)pNMHDR;
if(lpnmlv->iItem>= 0)
{
CRectrc;
CWnd*wnd = GetParent();
m_CurSelItem= lpnmlv->iItem;
m_CurSelSubItem= lpnmlv->iSubItem;
CStringstr = GetItemText(m_CurSelItem, m_CurSelSubItem);
m_Edit.SetWindowText(str);
m_Edit.SetSel(0,-1);
GetSubItemRect(lpnmlv->iItem,lpnmlv->iSubItem, LVIR_LABEL, rc);
rc.bottom= rc.bottom - rc.top;
rc.right= rc.right - rc.left;
ShowEditBox(TRUE,&rc);
wnd->SendMessage(UM_LISTEDIT_DBCLICK,(WPARAM)lpnmlv, 0);
}
*pResult= -1;
}
//重写父类虚函数,初始化CEdit
voidCEditableListCtrl::PreSubclassWindow()
{
//TODO: Add your specialized code here and/or call the base class
RECTrc = {0};
m_Edit.Create(WS_CHILD|WS_TABSTOP | WS_VISIBLE |ES_LEFT, rc,this, IDC_LISTEDIT);
CListCtrl::PreSubclassWindow();
}
//编辑框焦点失去处理函数,需要手动添加函数和消息映射
void CEditableListCtrl::OnEditKillFocus()
{
CStringstr;
CWnd*wnd;
wnd= GetParent();
ShowEditBox(FALSE,NULL);
m_Edit.GetWindowText(str);
SetItemText(m_CurSelItem,m_CurSelSubItem, str.GetBuffer(0));
::SendMessage(wnd->m_hWnd,UM_LISTEDIT_KILLFOCUS,
m_CurSelItem,m_CurSelSubItem);
m_CurSelItem= -1;
m_CurSelSubItem= -1;
m_Edit.SetWindowText("");
}
voidCEditableListCtrl::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
//TODO: Add your message handler code here and/or call default
SetFocus();
CListCtrl::OnHScroll(nSBCode,nPos, pScrollBar);
}
voidCEditableListCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
//TODO: Add your message handler code here and/or call default
SetFocus();
CListCtrl::OnVScroll(nSBCode,nPos, pScrollBar);
}
BOOLCEditableListCtrl::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
//TODO: Add your message handler code here and/or call default
SetFocus();
returnCListCtrl::OnMouseWheel(nFlags, zDelta, pt);
}
//直接根据参数设定CEdit显示内容,isShow是否显示,item项,isubitem子项,未使用
voidCEditableListCtrl::ShowEditBox(BOOL isShow, int iItem, int iSubItem)
{
CStringcon;
CRectrc;
if(!isShow)
{
m_Edit.ShowWindow(SW_HIDE);
return;
}
con= GetItemText(iItem, iSubItem);
GetSubItemRect(iItem,iSubItem, LVIR_LABEL, rc);
m_Edit.SetWindowText(con);
m_Edit.SetFocus();
m_Edit.SetSel(0,-1);
m_Edit.MoveWindow(rc.left,rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE);
m_Edit.ShowWindow(SW_SHOW);
}
相关资料(列表控件中指定列可被编辑)
一、引言
列表控件主要用来以各种方式显示一组数据记录供用户进行各种操作,是最常见的控件之一。WindowsXP资源管理器中的“查看”菜单下的 “图标|平铺|列表|详细信息”就是一个非常典型的应用。MFC中的CListCtrl类提供了对列表控件操作的基本方法,包括插入一个新的项目InsertItem、删除一个项目DeleteItem、排序项目SortItems等,但CListCtrl类不支持对项目的直接编辑,只能用SetItem或者SetItemText来输入数据,使用起来非常不方便。下面介绍在VC++6.0中以CListCtrl类为基类构建可直接编辑的列表控件类的方法,并提供一个可运行的实例。
二、实现方法
以在列表控件中实现CEditBox的直接编辑为例,介绍构建可直接编辑的列表控件类CEditListCtrl的方法:
在CEditListCtrl类中设置一个指向编辑框控件的指针m_edit,当列表控件中的一个子项目被两次不连续的单击后,使用m_edit在该子项目处创建一个编辑框,编辑框的大小与子项目的大小一致。当向编辑框中输入数据后,单击列表控件,便可将编辑框中的数据写回对应的子项目,同时释放m_edit所占用的空间。
当列表控件中的项目通过滚动条滚动时,某一子项目恰好处于编辑状态,则此时该子项目所对应的编辑框也要跟着滚动。为此,在CEditListCtrl类中添加WM_HSCROLL和 WM_VSCROLL消息处理函数,实现编辑框控件和其所对应的子项目的同步滚动。
在使用列表控件显示数据时,往往只需要编辑部分列中的数据,有些列的数据则不需要进行编辑。为此,在CEditListCtrl类中添加一个数据成员BOOL *m_isedit,m_isedit是一个数组,用于标志某一列是否可以进行直接编辑,若m_isedit[i]为TRUE,则第i列可以进行直接编辑,否则,反之。CEditListCtrl类中新增的成员函数SetEditColomn用于设置m_isedit的值。
以上方法也可用于在列表控件中实现ComboBox、DropdownList、CheckBox、PushButton等的直接编辑。
三、CEditListCtrl类的定义和实现
在VC++6.0中创建一个基于对话框的工程,点击菜单“插入->类”,在弹出的对话框中设置基类为CLlistCtrl,派生类为CEditListCtrl。在CEditListCtrl类中定义四个数据成员:
CEdit * m_edit;//指向编辑框,初值为NULL
BOOL * m_isedit;//允许进行编辑的列,初值为NULL
int m_item;//当前编辑的行号,初值为-1
int m_subitem;//当前编辑的列号,初值为-1
定义一个常量ID_LISTEDIT作为m_edit所指向的编辑框的ID号。在CEditListCtrl中添加NM_CLICK的消息处理函数,实现代码如下:
voidCEditListCtrl::OnClick(NMHDR* pNMHDR,LRESULT* pResult)
{
if(!m_isedit) return;
NM_LISTVIEW* pNMListView=(NM_LISTVIEW*)pNMHDR;
if(!m_edit)
{
m_subitem=pNMListView->iSubItem;
if(pNMListView->iItem!=m_item)//双击判断
{
m_item=pNMListView->iItem;//标志被单击的项目
return;
}
}
if(!m_isedit[m_subitem])//若当前列不允许直接编辑,则返回
return;
RECT m_itemrect,m_r;
GetItemRect(m_item,&m_itemrect,2);
GetItemRect(0 ,&m_r,2);
intm_height=m_itemrect.bottom-m_itemrect.top ;
intx=m_r.left,y=m_r.top,cx,cy;//(x,y,cx,cy)为编辑框显示的位置
for(int i=0;i< m_item;i++)
y+=m_height;
cy=y+m_height;
for(i=0;i<m_subitem;i++)
x+=GetColumnWidth(i);
cx=x+GetColumnWidth(i);
if(m_edit)//若编辑框已存在。
{
CString s1;
s1.Format ("%d %d%d%d",x,y,cx,cy);
m_edit->MoveWindow(x,y,cx-x,cy-y);//移动到当前子项目的位置。
Invalidate();//刷新屏幕。
return;
}
//若编辑框不存在,则创建编辑框,并在当前子项目处显示编辑框。
CRect rect(x,y,cx,cy);
m_edit=new CEdit();
m_edit->Create(WS_CHILD|WS_VISIBLE|WS_BORDER,rect,this,ID_LISTEDIT);
CStringstr=GetItemText(pNMListView->iItem,pNMListView->iSubItem);
m_edit->UpdateData(0);
m_edit->SetWindowText(str);
DWORD dwSel=m_edit->GetSel();
m_edit->SetSel(HIWORD(dwSel),-1);
m_edit->ShowWindow(SW_SHOW);//显示编辑框。
m_edit->SetFocus ();
*pResult = 0;
}
在CEditListCtrl中添加NM_SETFOCUS的消息处理函数,实现代码如下:
void CEditListCtrl::OnSetfocus(NMHDR*pNMHDR,LRESULT* pResult)
{
if(m_edit)
{//将编辑框中的数据写回对应的子项目中
UpdateData( );
CString str;
m_edit->GetWindowText(str);
SetItemText(m_item,m_subitem,str);
delete m_edit;
m_edit=NULL;
}
*pResult = 0;
}
添加WM_HSCROLL和 WM_VSCROLL的消息处理函数,实现代码如下:
voidCEditListCtrl::OnHScroll(UINT nSBCode,UINT nPos, CScrollBar* pScrollBar)
{//水平滚动时,移动已显示的编辑框。
CListCtrl::OnHScroll(nSBCode,nPos,pScrollBar);
LRESULT* pResult=new LRESULT;
if(m_edit)OnClick((NMHDR*)this,pResult) ;
}
voidCEditListCtrl::OnVScroll(UINT nSBCode,UINT nPos, CScrollBar* pScrollBar)
{//垂直滚动时,移动已显示的编辑框。
CListCtrl::OnVScroll(nSBCode,nPos,pScrollBar);
LRESULT* pResult=new LRESULT;
if(m_edit)
{
RECT m_itemrect,m_headrect;
GetItemRect(m_item,&m_itemrect,2);
GetHeaderCtrl()->GetWindowRect(&m_headrect);
if(m_itemrect.top<m_headrect.bottom-m_headrect.top)
{
RECT m_rect;
m_edit->GetWindowRect(&m_rect);
m_edit->MoveWindow(m_rect.left,-(m_rect.bottom-m_rect.top),m_rect.right,0);
}
else
{
OnClick((NMHDR*)this,pResult);
}
}
}
添加SetEditColomn函数,实现代码如下:
voidCEditListCtrl::SetEditColomn(intcol,BOOL edit)
{//设置允许直接进行编辑的列
if(!m_isedit)
{
intlen=GetHeaderCtrl()->GetItemCount();
m_isedit=new BOOL[len];
for(int i=0;i<len;i++)//初始化m_isedit。
m_isedit[i]=FALSE;
}
m_isedit[col]=edit;
}
重载DestroyWindow()函数,实现代码如下:
BOOLCEditListCtrl::DestroyWindow()
{
delete [] m_isedit;
returnCListCtrl::DestroyWindow();
}
四、CEditListCtrl类的测试
在上述工程的主对话框中添加一个ListCtrl控件,设置控件的显示方式为LVS_REPORT方式,给该控件定义一个CEditListCtrl类型的对象m_list,再在对话框的初始化函数中添加初始化代码:
m_list.InsertColumn (0,"学号", LVCFMT_LEFT,50);
m_list.InsertColumn (1,"姓名", LVCFMT_LEFT,90);
m_list.InsertColumn (2,"年龄", LVCFMT_LEFT,50);
m_list.InsertItem(0,"1");
m_list.SetItemText (0,1,"王明");
m_list.SetItemText(0,2,"23");
m_list.InsertItem(1,"2");
m_list.SetItemText (1,1,"赵可");
m_list.SetItemText(1,2,"20");
m_list.SetExtendedStyle(LVS_EX_FULLROWSELECT);
m_list.SetEditColomn (0,TRUE);//允许第0列可直接编辑
m_list.SetEditColomn (1,TRUE); //允许第1列可直接编辑
m_list.SetEditColomn (2,TRUE); //允许第2列可直接编辑
本文中的编码在Window2000中调试通过,运行结果:当两次不连续地单击列表控件中的一个子项目后,该子项目便呈现编辑状态,如下图所示。向编辑框中输入数据后单击列表控件,便完成对子项目的编辑。
c �):[email protected] ��z 0); font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-align: -webkit-auto; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); ">}
m_isedit[col]=edit;
}
重载DestroyWindow()函数,实现代码如下:
BOOL CEditListCtrl::DestroyWindow()
{
delete [] m_isedit;
return CListCtrl::DestroyWindow();
}
四、CEditListCtrl类的测试
在上述工程的主对话框中添加一个ListCtrl控件,设置控件的显示方式为LVS_REPORT方式,给该控件定义一个CEditListCtrl类型的对象m_list,再在对话框的初始化函数中添加初始化代码:
m_list.InsertColumn (0,"学号", LVCFMT_LEFT,50);
m_list.InsertColumn (1,"姓名", LVCFMT_LEFT,90);
m_list.InsertColumn (2,"年龄", LVCFMT_LEFT,50);
m_list.InsertItem (0,"1");
m_list.SetItemText (0,1,"王明");
m_list.SetItemText (0,2,"23");
m_list.InsertItem (1,"2");
m_list.SetItemText (1,1,"赵可");
m_list.SetItemText (1,2,"20");
m_list.SetExtendedStyle(LVS_EX_FULLROWSELECT);
m_list.SetEditColomn (0,TRUE);//允许第0列可直接编辑
m_list.SetEditColomn (1,TRUE); //允许第1列可直接编辑
m_list.SetEditColomn (2,TRUE); //允许第2列可直接编辑
本文中的编码在Window2000中调试通过,运行结果:当两次不连续地单击列表控件中的一个子项目后,该子项目便呈现编辑状态,如下图所示。向编辑框中输入数据后单击列表控件,便完成对子项目的编辑。