该类继承自MFC的CListCtrl类;
实现列可选,多单元格可选,单击选中单元格并能双击编辑,同时也可以设定某一列是否能进行编辑等等。
功能强大,欢迎使用。
<p><span style="font-family: Arial, Helvetica, sans-serif;">头文件:</span></p><p>CEditListCtrl.h</p>
class CEditListCtrl : public CListCtrl { // Construction public: CEditListCtrl(); // Attributes public: CEdit* m_edit;//指向编辑框 BOOL m_panduan1; UINT Idfrom; BOOL * m_isedit;//数组 表明可编辑列号 // CEdit* m_edit;//指向编辑框 int m_subitem; int m_item; int m_old_item;//在LButtonDown中用来保存起点行数 int m_old_subitem;//在LButtonDown中用来保存起点列数 int m_now_item; int m_now_subitem; // BOOL DestroyWindow(); using CListCtrl::DestroyWindow;//重载函数 BOOL DestroyWindow(); void SetEditColomn(int col,BOOL edit); // Operations public: BOOL m_downmove; BOOL m_bCustomDraw; int m_nNumberOfRows; int m_nNumberOfCols; // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CEditListCtrl) //}}AFX_VIRTUAL // Implementation public: virtual ~CEditListCtrl(); // Generated message map functions protected: //{{AFX_MSG(CEditListCtrl) afx_msg void OnDblclk(NMHDR* pNMHDR, LRESULT* pResult); afx_msg void OnClick(NMHDR* pNMHDR, LRESULT* pResult); afx_msg void OnKeydown(NMHDR* pNMHDR, LRESULT* pResult); afx_msg void OnMouseMove(UINT nFlags, CPoint point); afx_msg void OnLButtonUp(UINT nFlags, CPoint point); afx_msg void OnLButtonDown(UINT nFlags, CPoint point); afx_msg void OnSetfocus(NMHDR* pNMHDR, LRESULT* pResult); afx_msg void OnKillfocus(NMHDR* pNMHDR, LRESULT* pResult); afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); afx_msg void OnClose(); //}}AFX_MSG DECLARE_MESSAGE_MAP() private: void invalidate_grid(int row,int col); afx_msg void custom_draw_funtion(NMHDR *pNMHDR, LRESULT *pResult); };
源文件:
CEditListCtrl.cpp
// EditListCtrl.cpp : implementation file // #include "stdafx.h" //#include "CEditListDlg.h" #include "EditListCtrl.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif //////////////////////Doctor.W//////////////////////////// // CEditListCtrl CEditListCtrl::CEditListCtrl() { m_bCustomDraw=TRUE; m_now_subitem=-1; m_now_item=-1; m_old_subitem=-1; m_old_item=-1; m_nNumberOfRows=0; m_nNumberOfCols=0; m_downmove=FALSE; m_item=-1; m_subitem=-1; m_edit=NULL; m_isedit=NULL; } CEditListCtrl::~CEditListCtrl() { if(m_isedit) delete [] m_isedit; if(m_edit) delete m_edit; } BEGIN_MESSAGE_MAP(CEditListCtrl, CListCtrl) //{{AFX_MSG_MAP(CEditListCtrl) ON_NOTIFY_REFLECT(NM_DBLCLK, OnDblclk) ON_NOTIFY_REFLECT(NM_CLICK, OnClick) ON_NOTIFY_REFLECT(LVN_KEYDOWN, OnKeydown) ON_WM_MOUSEMOVE() ON_WM_LBUTTONUP() ON_WM_LBUTTONDOWN() ON_NOTIFY_REFLECT(NM_SETFOCUS, OnSetfocus) ON_NOTIFY_REFLECT(NM_KILLFOCUS, OnKillfocus) ON_WM_HSCROLL() ON_WM_VSCROLL() ON_WM_CLOSE() //}}AFX_MSG_MAP ON_NOTIFY_REFLECT(NM_CUSTOMDRAW,custom_draw_funtion) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CEditListCtrl message handlers void CEditListCtrl::custom_draw_funtion(NMHDR *pNMHDR, LRESULT *pResult) { NMLVCUSTOMDRAW* nmcd=(NMLVCUSTOMDRAW*)pNMHDR; *pResult=CDRF_DODEFAULT; int row; int col; switch(nmcd->nmcd.dwDrawStage) { case CDDS_PREPAINT: if(m_bCustomDraw) *pResult=CDRF_NOTIFYITEMDRAW; // else CDRF_DODEFAULT which stops notyfication messages return; case CDDS_ITEMPREPAINT: *pResult=CDRF_NOTIFYSUBITEMDRAW; return; case CDDS_SUBITEM|CDDS_ITEMPREPAINT: { *pResult=0; row=nmcd->nmcd.dwItemSpec; col=nmcd->iSubItem; CString str=GetItemText(row,col); CRect rect; CDC* pDC=CDC::FromHandle(nmcd->nmcd.hdc); if(col>0) GetSubItemRect(row,col,LVIR_BOUNDS,rect); else GetItemRect(row,&rect,LVIR_LABEL); UINT uCode=DT_LEFT; int olditem,oldsub,nowitem,nowsub; olditem=m_old_item; nowitem=m_now_item; oldsub=m_old_subitem; nowsub=m_now_subitem; if (m_old_item>m_now_item) { olditem=m_now_item; nowitem=m_old_item; } if (m_old_subitem>m_now_subitem) { oldsub=m_now_subitem; nowsub=m_old_subitem; } if( (row>=olditem&&row<=nowitem)&&(col>=oldsub&&col<=nowsub)) { COLORREF kolor=0xffff5f;//0x004e98;//0xffff00;//lanse if(0==col || 1==col || 3==col) { kolor=0xFFA500;//0xc0c0c0; if(GetFocus()==this) kolor=0xFFBBFF;//0xaa00aa; CBrush brush(kolor); pDC->FillRect(&rect,&brush); } else { if(GetFocus()==this) kolor=0xFFA500;//0xff0000;//shenlan; } CBrush brush(kolor); pDC->FillRect(&rect,&brush); } else { if(0==col || 1==col || 3==col) { COLORREF kolor=0xc0c0c0; CBrush brush(kolor); pDC->FillRect(&rect,&brush); } else { COLORREF kolor=0xC1FFC1;//0xfae9d0;//豆沙绿 CBrush brush(kolor); pDC->FillRect(&rect,&brush); } } rect.OffsetRect(5,0); if (col==3) { pDC->DrawText(str,&rect,DT_CENTER); } else pDC->DrawText(str,&rect,uCode); *pResult=CDRF_SKIPDEFAULT; break; } } } void CEditListCtrl::OnClick(NMHDR* pNMHDR, LRESULT* pResult) { NMITEMACTIVATE* nm=(NMITEMACTIVATE*)pNMHDR; m_downmove=FALSE; Invalidate(); 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; } } *pResult = 0; } void CEditListCtrl::OnKeydown(NMHDR* pNMHDR, LRESULT* pResult) { NMLVKEYDOWN* nmkd = (NMLVKEYDOWN*)pNMHDR; switch(nmkd->wVKey) { case VK_LEFT: m_old_subitem--; if(m_old_subitem<0) m_old_subitem=0; invalidate_grid(m_old_item,m_old_subitem+1); Invalidate(); break; case VK_RIGHT: m_old_subitem++; if(m_old_subitem>GetHeaderCtrl()->GetItemCount()-1) m_old_subitem=GetHeaderCtrl()->GetItemCount()-1; invalidate_grid(m_old_item,m_old_subitem-1); Invalidate(); break; case VK_UP: m_old_item--; if(m_old_item<0) m_old_item=0; invalidate_grid(m_old_item+1,m_old_subitem); break; case VK_DOWN: m_old_item++; if(m_old_item>GetItemCount()-1) m_old_item=GetItemCount()-1; invalidate_grid(m_old_item-1,m_old_subitem); break; case VK_PRIOR: invalidate_grid(m_old_item,m_old_subitem); m_old_item=0; break; case VK_NEXT: invalidate_grid(m_old_item,m_old_subitem); m_old_item=GetItemCount()-1; break; case VK_HOME: invalidate_grid(m_old_item,m_old_subitem); m_old_subitem=0; if(GetKeyState(VK_CONTROL)<0) m_old_item=0; SetItemState(m_old_item,LVIS_FOCUSED,LVIS_FOCUSED); *pResult = CDRF_SKIPDEFAULT; invalidate_grid(m_old_item,m_old_subitem); return; break; case VK_END: invalidate_grid(m_old_item,m_old_subitem); m_old_subitem=GetHeaderCtrl()->GetItemCount()-1; if(GetKeyState(VK_CONTROL)<0) m_old_item=GetItemCount()-1; SetItemState(m_old_item,LVIS_FOCUSED,LVIS_FOCUSED); *pResult=CDRF_SKIPDEFAULT; invalidate_grid(m_old_item,m_old_subitem); return; } *pResult = 0; } void CEditListCtrl::invalidate_grid(int row, int col) { CRect r; if(col==0 || col==1 || col==3) GetItemRect(row,&r,LVIR_LABEL); else GetSubItemRect(row,col,LVIR_BOUNDS,r); m_now_item=m_old_item; m_now_subitem=m_old_subitem; InvalidateRect(&r); } void CEditListCtrl::OnMouseMove(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default if (m_downmove) { POINT pt=point; UINT flags; // ClientToScreen(&pt); // CImageList::DragMove(pt); LVHITTESTINFO lvhti; lvhti.pt=point; m_now_item=HitTest(pt,&flags); m_now_subitem=SubItemHitTest(&lvhti); m_now_subitem=lvhti.iSubItem; Invalidate(); } CListCtrl::OnMouseMove(nFlags, point); } void CEditListCtrl::OnLButtonUp(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default m_downmove=FALSE; CListCtrl::OnLButtonUp(nFlags, point); } void CEditListCtrl::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default // invalidate_grid(m_item,m_subitem); m_downmove=TRUE; POINT pt=point; UINT flags; // ClientToScreen(&pt); // CImageList::DragMove(pt); m_old_item=HitTest(pt,&flags); LVHITTESTINFO lvhti; lvhti.pt=point; m_old_subitem=SubItemHitTest(&lvhti); m_old_subitem=lvhti.iSubItem; m_now_item=m_old_item; m_now_subitem=m_old_subitem; if(m_edit) { m_edit->DestroyWindow(); m_edit=NULL; } //m_edit->ShowWindow(SW_HIDE); CListCtrl::OnLButtonDown(nFlags, point); } void CEditListCtrl::OnSetfocus(NMHDR* pNMHDR, LRESULT* pResult) { // TODO: Add your control notification handler code here if(m_edit) {//将编辑框中的数据写回对应的子项目中 UpdateData( ); CString str; m_edit->GetWindowText(str); // MessageBox(str); SetItemText(m_item,m_subitem,str); delete m_edit; m_edit=NULL; } *pResult = 0; } void CEditListCtrl::OnKillfocus(NMHDR* pNMHDR, LRESULT* pResult) { // TODO: Add your control notification handler code here Invalidate(); *pResult = 0; } void CEditListCtrl::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) { // TODO: Add your message handler code here and/or call default //水平滚动时,移动已显示的编辑框 CListCtrl::OnHScroll(nSBCode, nPos, pScrollBar); LRESULT* pResult=new LRESULT; if(m_edit) OnClick((NMHDR*)this,pResult) ; } void CEditListCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) { // TODO: Add your message handler code here and/or call default //垂直滚动时,移动已显示的编辑框。 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) ; } } } void CEditListCtrl::SetEditColomn(int col, BOOL edit) { //设置允许直接进行编辑的列 if(!m_isedit) { int len=GetHeaderCtrl()->GetItemCount(); m_isedit=new BOOL[len]; for(int i=0;i<len;i++)//初始化m_isedit。 m_isedit[i]=FALSE; } m_isedit[col]=edit; } void CEditListCtrl::OnDblclk(NMHDR* pNMHDR, LRESULT* pResult) { // TODO: Add your control notification handler code here int i; 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); int m_height=m_itemrect.bottom -m_itemrect.top ; int x=m_r.left ,y=m_r.top,cx,cy;//(x,y,cx,cy)为编辑框显示的位置 for(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 (_T("%d %d %d %d"),x,y,cx,cy); m_edit->MoveWindow(x-4,y,cx-x-4,cy-y);//移动到当前子项目的位置。 Invalidate();//刷新屏幕。 return; } //若编辑框不存在,则创建编辑框,并在当前子项目处显示编辑框。 CRect rect(x-4,y,cx-4,cy); m_edit=new CEdit(); m_edit->Create (WS_CHILD|WS_VISIBLE|WS_BORDER,rect,this,ID_LISTEDIT); SetWindowLong(m_edit->m_hWnd, GWL_STYLE,GetWindowLong(m_edit->m_hWnd, GWL_STYLE) | ES_NUMBER);//控制只允许输入数字 CString str=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; } BOOL CEditListCtrl::DestroyWindow() { delete [] m_isedit; return CListCtrl::DestroyWindow(); } void CEditListCtrl::OnClose() { // TODO: Add your message handler code here and/or call default if(m_edit) delete m_edit; delete [] m_isedit; CListCtrl::OnClose(); }
ListCtrl的扩展类EditListCtrl
时间: 2024-10-29 06:45:52