CListCtrl 控件生成之后,无论你单击还是双击它的单元格,都没有任何反应,如果我们需要像EXCEL那样双击一个单元格后即可编辑该单元格的内容,那怎么办呢?一个 方法就是双击单元格之后,在该单元格的地方生成一个编辑框,然后让输入焦点落在该编辑框上,我们即可对该编辑框进行文字编辑,当输入焦点从编辑框上消失时 (通常是用户在编辑框外的地方单击,就像EXCEL当编辑完一个单元格的内容后用户在单元格外的地方单击一下以示确认输入完毕一样。),就理解为编辑完 毕,然后把编辑框的内容设置为该单元格的内容,最后隐藏或销毁编辑框。



1. 从CListCtrl类继承,新建一个自己的列表框类,在这里我取名为CPage2ListCtrl,下面就要在CPage2ListCtrl 类实现双 击单元格编辑功能。上面也已经说道,双击单元格后要显示一个编辑框,我们把那个编辑框看做是CPage2ListCtrl 类的成员。接下来就要为这个编 辑框新建一个从CEdit继承的类,为什么不直接用CEdit类呢,以后就知道为什么的了。这个从CEdit继承的编辑框类我取名为CListEdit。



2.为CPage2ListCtrl类添加成员变量和函数:


public:
  void DisposeEdit();     //这个函数的作用是.....往下看就知道的了。
  CListEdit m_edit;       //这个就是双击单元格后显示的编辑框。
  int row,col;



3.重写CPage2ListCtrl类的PreSubclassWindow()虚函数,这个函数的作用是什么,这里就不说了,我们要在这个函数里设置CPage2ListCtrl类的基本样式和扩展样式,还有创建m_edit成员变量的编辑框。


void CPage2ListCtrl::PreSubclassWindow() 
 {
  // TODO: Add your specialized code here and/or call the base class
  ModifyStyle(LVS_EDITLABELS,0);
  ModifyStyle(0,LVS_REPORT);
  ModifyStyle(0,LVS_SHOWSELALWAYS);
  SetExtendedStyle(LVS_EX_FLATSB  |  LVS_EX_FULLROWSELECT   |  LVS_EX_GRIDLINES);
  m_edit.Create(WS_CHILD|WS_CLIPSIBLINGS|WS_EX_TOOLWINDOW|WS_BORDER,
                         CRect(0,40,10,50),this,1001);
  CListCtrl::PreSubclassWindow();
 }



4.对CPage2ListCtrl类添加消息处理,对双击事件进行响应,消息名称是WM_LBUTTONDBLCLK。


void CPage2ListCtrl::OnLButtonDblClk(UINT nFlags, CPoint point) 
 {
  // TODO: Add your message handler code here and/or call default
  CListCtrl::OnLButtonDblClk(nFlags, point);
  LVHITTESTINFO info;
  info.pt=point;
  info.flags=LVHT_ONITEMLABEL;
  if(SubItemHitTest(&info)>=0)     //SubItemHitTest进行点击测试,目的是确定双击的单元格是第几行第几列。
  {
   row=info.iItem;                          //行索引
  col=info.iSubItem;                    
//做适当的修改,可控制只输入一行,或者只可编辑下一行
 
int nCount i= 0;
 
int j = 0;
 
CString str;
 
for(j = 0; j<20;j++)
 
{
 
str = GetItemText(j,0);
 
if(str.GetLength() == 0)
 
break;
 
else
 
nCount++;
 
}
 
if(nCount == row)//只可编辑空白处第一行
 
return;
 
if(0)//条件自己添加
 
{
 
if(row != 0)
 
return //只可编辑第一行
 
}
   CRect rect;
   GetSubItemRect(row,col,LVIR_LABEL,rect);    //得到该单元格矩形的位置大小信息。
   CString str;
   str = GetItemText(row,col);                               //获取该单元格已存在的文本内容。
   m_edit.MoveWindow(rect);                              //把编辑框移动到该单元格矩形上。
  m_edit.SetWindowText(str);                             //把单元格原本的内容显示到编辑框上。
  m_edit.ShowWindow(SW_SHOW);                  //显示编辑框。
   m_edit.SetSel(0,-1);                                        //全选编辑框的内容。
   m_edit.SetFocus();                                           //设置输入焦点在编辑框上。
      UpdateWindow();
  }
 }



5.当编辑框输入焦点消失时,就认为编辑完毕,然后把编辑框的内容设置到单元格上。编辑框输入焦点消失时会产生WM_KILLFOCUS消息,我们对该消息进行响应,这就是为什么上面要为编辑框新建一个类的原因了。


void CListEdit::OnKillFocus(CWnd* pNewWnd) 
 {
  CEdit::OnKillFocus(pNewWnd);
  CPage2ListCtrl * temp;      
//这里新建了一个CPage2ListCtrl 类型的指针,所以在CListEdit的cpp文件前必须先添加#include "Page2ListCtrl.h"
 temp=(CPage2ListCtrl *)GetParent();  
  temp->DisposeEdit();   //调用父窗口的DisposeEdit()函数。
 // TODO: Add your message handler code here 
 } 
 
void CPage2ListCtrl::DisposeEdit()
 { CString sLabel;
   
//以下代码需添加,消除一些bug
 
int nCount i= 0;
 
 
int j = 0;
 
 
CString str;
 
 
for(j = 0; j<20;j++)
 
 
{
 
 
str = GetItemText(j,0);
 
 
if(str.GetLength() == 0)
 
 
break;
 
 
else
 
 
nCount++;
 
 
}
 
 
if(nCount == row)//只可编辑空白处第一行
 
 
return;
 
 
if(0)//条件自己添加
 
 
{
 
 
if(row != 0)
 
 
return //只可编辑第一行
 
 
}
    this->SetItemText(row,col,sLabel);
   m_edit.ShowWindow(SW_HIDE);
   if(GetItemCount() == row+1)     //如果编辑的这行是最后一行的话,就添加一行,在这里可以设置更多的判断。
    InsertItem(row+1,0);
   return ;
 }