#include "..\stdafx.h" #include "..\resource.h" #include "earthwormdef.h" #include // MFC support for Windows Common Controls #include "WDGrid.h" #include "TListQuene.h" #include "TDualPtrList.h" namespace { int ACmpLabel(const char* sLabel1, const char* sLabel2) { TAString s1(sLabel1), s2(sLabel2); TAString sName1(s1.Length()), sName2(s2.Length()); TAString sDigit1(s1.Length()), sDigit2(s2.Length()); long len1 = s1.Length(); for (long i = 0; i= '0'&&c <= '9') {//数字 sDigit1 << c; } else {//字符 sName1 << c; if (c<0) {//汉字占两位 sName1 << s1[++i]; } } } long len2 = s2.Length(); for (i = 0; i= '0'&&c <= '9') {//数字 sDigit2 << c; } else//字符 { sName2 << c; if (c<0) {//汉字占两位 sName2 << s2[++i]; } } } int iRet = strcmp(sName1, sName2); if (iRet<0) { return -1; } else if (iRet>0) { return 1; } else { int num1 = atoi(sDigit1), num2 = atoi(sDigit2); if (num1num2) { return 1; } else { return 0; } } } int UCmpLabel(const wchar_t* sLabel1, const wchar_t* sLabel2) { TUString s1(sLabel1), s2(sLabel2); TUString sName1(s1.Length()), sName2(s2.Length()); TUString sDigit1(s1.Length()), sDigit2(s2.Length()); long len1 = s1.Length(); for (long i = 0; i= '0'&&c <= '9') {//数字 sDigit1 << c; } else//字符 { sName1 << c; if (c<0) {//汉字占两位 sName1 << s1[++i]; } } } long len2 = s2.Length(); for (i = 0; i= '0'&&c <= '9') {//数字 sDigit2 << c; } else//字符 { sName2 << c; if (c<0) {//汉字占两位 sName2 << s2[++i]; } } } int iRet = wcscmp(sName1, sName2); if (iRet<0) { return -1; } else if (iRet>0) { return 1; } else { int num1 = _wtoi(sDigit1), num2 = _wtoi(sDigit2); if (num1num2) { return 1; } else { return 0; } } } } ///////////////////////////////////////////////////////////////////////////////////////////////// // WDGridRow WDGridRow::WDGridRow(WDGrid &parent):grid(parent),style(0),index(-1),pData(NULL)//ok { for(int i=0;iRefresh(); } void WDGridRow::Select(bool bSel)//ok { if(!grid.IsValidWnd()) return; CDC&dc=grid.GetDC(); CRect rect; GetRect(rect); dc.InvertRect(&rect); } bool WDGridRow::operator <(WDGridRow&row)//ok { if(!IsParentRow()&&row.IsParentRow()) return false; else if(IsParentRow()&&!row.IsParentRow()) return true; if(grid.IsLabelSort()) { if(!grid.keyList.IsEmpty()) { TList&kList=grid.keyList; for(kList.MoveToFirst();!kList.IsOut();kList.MoveToNext()) { long i=kList.GetCurData(); int cmp=CmpLabel((*this)[i].GetText(),row[i]); if(cmp>0) return false; else if(cmp<0) return true; } return false; } TList&kList=grid.colSelList; for(kList.MoveToFirst();!kList.IsOut();kList.MoveToNext()) { long i=kList.GetCurData(); int cmp=CmpLabel((*this)[i].GetText(),row[i]); if(cmp>0) return false; else if(cmp<0) return true; } } else { if(!grid.keyList.IsEmpty()) { TList&kList=grid.keyList; for(kList.MoveToFirst();!kList.IsOut();kList.MoveToNext()) { long i=kList.GetCurData(); int cmp=(*this)[i].GetText()-row[i]; if(cmp>0) return false; else if(cmp<0) return true; } return false; } TList&kList=grid.colSelList; for(kList.MoveToFirst();!kList.IsOut();kList.MoveToNext()) { long i=kList.GetCurData(); int cmp=(*this)[i].GetText()-row[i]; if(cmp>0) return false; else if(cmp<0) return true; } } return false; } bool WDGridRow::operator >(WDGridRow&row)//ok { if(!IsParentRow()&&row.IsParentRow()) return true; else if(IsParentRow()&&!row.IsParentRow()) return false; if(grid.IsLabelSort()) { if(!grid.keyList.IsEmpty()) { TList&kList=grid.keyList; for(kList.MoveToFirst();!kList.IsOut();kList.MoveToNext()) { long i=kList.GetCurData(); int cmp=CmpLabel((*this)[i].GetText(),row[i]); if(cmp<0) return false; else if(cmp>0) return true; } return false; } TList&kList=grid.colSelList; for(kList.MoveToFirst();!kList.IsOut();kList.MoveToNext()) { long i=kList.GetCurData(); int cmp=CmpLabel((*this)[i].GetText(),row[i]); if(cmp<0) return false; else if(cmp>0) return true; } } else { if(!grid.keyList.IsEmpty()) { TList&kList=grid.keyList; for(kList.MoveToFirst();!kList.IsOut();kList.MoveToNext()) { long i=kList.GetCurData(); int cmp=(*this)[i].GetText()-row[i]; if(cmp<0) return false; else if(cmp>0) return true; } return false; } TList&kList=grid.colSelList; for(kList.MoveToFirst();!kList.IsOut();kList.MoveToNext()) { long i=kList.GetCurData(); int cmp=(*this)[i].GetText()-row[i]; if(cmp<0) return false; else if(cmp>0) return true; } } return false; } ////////////////////////////////////////////////////////////////////////////////////////////// WDGridTreeRow::WDGridTreeRow(WDGrid&grid):WDGridRow(grid),pParent(NULL)//ok { } WDGridTreeRow::WDGridTreeRow(WDGridTreeRow*parent):WDGridRow(parent->grid),pParent(parent)//ok { } WDGridTreeRow& WDGridTreeRow::operator =(WDGridTreeRow&row)//ok { WDGridRow::operator =(row); for(long i=0;iInsertCol(i,col); } void WDGridTreeRow::AppendCol(WDGridCol&col)//ok { WDGridRow::AppendCol(col); for(childRow.MoveToFirst();!childRow.IsOut();childRow.MoveToNext()) childRow.GetCurData()->AppendCol(col); } void WDGridTreeRow::DelCol(long i)//ok { WDGridRow::DelCol(i); for(childRow.MoveToFirst();!childRow.IsOut();childRow.MoveToNext()) childRow.GetCurData()->DelCol(i); } void WDGridTreeRow::MoveCol(long from,long to)//ok { WDGridRow::MoveCol(from,to); for(childRow.MoveToFirst();!childRow.IsOut();childRow.MoveToNext()) childRow.GetCurData()->MoveCol(from,to); } WDGridTreeRow* WDGridTreeRow::RootRow()//ok { WDGridTreeRow* p=this; while(p->IsChildRow()) p=p->Parent(); return p; } void WDGridTreeRow::InsertChild(long i,WDGridTreeRow*pRow)//ok {//无限制插入(i正确时) if(pRow==NULL) pRow=new WDGridTreeRow(grid); else pRow->SetIndex(-1); pRow->SetParent(this); childRow.Insert(i,pRow); if(IsVisible()) { if(!IsFold())//子行可见 { grid.InsertRow(GetGlobalChildIndex(i),pRow); if(!pRow->IsFold()) pRow->UnFold(); } else if(GetChildNum()==1) Refresh();//显示父方块标志 } } void WDGridTreeRow::DelChild(long i)//ok {//无限制删除(i正确时) bool bChildVisible=IsChildVisible(); if(bChildVisible)//子行可见 { childRow[i]->Fold();//将后代从GRID中取回 grid.SelectRow(childRow[i]->GetIndex(),false); grid.rowList[childRow[i]->GetIndex()]=NULL; grid.DelRow(childRow[i]->GetIndex()); } childRow.Del(i); if(!bChildVisible&&IsVisible()&&childRow.IsEmpty())//子行已空 Refresh();//不再显示父方块标志 } void WDGridTreeRow::Fold()//ok {//无限制调用 if(!IsParentRow())//无子行 { SetUnFoldFlag(false); return; } long oldCur=grid.GetCur(); if(IsChildVisible()) for(long i=1;iSetIndex(-1);//设不可见标志 grid.SelectRow(nextRow,false); grid.rowList[nextRow]=NULL; grid.DelRow(nextRow); } grid.MoveTo(oldCur); SetUnFoldFlag(false); } void WDGridTreeRow::UnFold()//ok {//无限制调用 if(!IsParentRow())//无子行 { SetUnFoldFlag(); return; } long oldCur=grid.GetCur(); if(IsVisible()&&!IsChildVisible()) { //将子行插入GRID for(childRow.MoveToFirst();!childRow.IsOut();childRow.MoveToNext()) grid.InsertRow(GetIndex()+childRow.GetCur()+1,childRow.GetCurData()); //恢复后代的历史展开状态 for(childRow.MoveToFirst();!childRow.IsOut();childRow.MoveToNext()) if(!childRow.GetCurData()->IsFold()) childRow.GetCurData()->UnFold(); } grid.MoveTo(oldCur); SetUnFoldFlag(); } void WDGridTreeRow::UnFoldAll()//ok { UnFold(); for(childRow.MoveToFirst();!childRow.IsOut();childRow.MoveToNext()) childRow.GetCurData()->UnFoldAll(); } void WDGridTreeRow::FoldAll()//ok { Fold(); for(childRow.MoveToFirst();!childRow.IsOut();childRow.MoveToNext()) childRow.GetCurData()->FoldAll(); } void WDGridTreeRow::ArrangeChild(bool bIncrease)//ok { if(!IsParentRow()) return; childRow.Arrange(bIncrease); for(childRow.MoveToFirst();!childRow.IsOut();childRow.MoveToNext()) childRow.GetCurData()->ArrangeChild(bIncrease); } long WDGridTreeRow::GetParentNum()//ok { return IsChildRow()?pParent->GetParentNum()+1:0; } void WDGridTreeRow::ClearChild()//ok { if(!IsParentRow()) return; Fold(); childRow.Clear(); } long WDGridTreeRow::GetOffspringNum()//ok { long oldCur=childRow.GetCur(); long num=GetChildNum(); for(childRow.MoveToFirst();!childRow.IsOut();childRow.MoveToNext()) num+=childRow.GetCurData()->GetOffspringNum(); childRow.MoveTo(oldCur); return num; } long WDGridTreeRow::GetRowNum()//ok { long oldCur=childRow.GetCur(); long num=1; if(!IsFold()) for(childRow.MoveToFirst();!childRow.IsOut();childRow.MoveToNext()) num+=childRow.GetCurData()->GetRowNum(); childRow.MoveTo(oldCur); return num; } long WDGridTreeRow::GetChildIndex(WDGridTreeRow*pRow)//ok { long oldCur=childRow.GetCur(); long res=-1; for(childRow.MoveToFirst();!childRow.IsOut();childRow.MoveToNext()) if(childRow.GetCurData()==pRow) { res=childRow.GetCur(); break; } childRow.MoveTo(oldCur); return res; } long WDGridTreeRow::GetGlobalChildIndex(long i)//ok { long oldCur=childRow.GetCur(); long rowNum=1; for(childRow.MoveToFirst();childRow.GetCur()GetRowNum(); childRow.MoveTo(oldCur); return GetIndex()+rowNum; } void WDGridTreeRow::GetTreeQuad(CRect&rect)//ok { if(!IsParentRow()) return; long oldCur=cellList.GetCur(); cellList[0]->GetRect(rect); cellList.MoveTo(oldCur); rect.top+=2; rect.left+=2; rect.left+=GetParentNum()*(grid.GetRowHeight()-3); rect.right=rect.left+grid.GetRowHeight()-3; rect.bottom-=1; } bool WDGridTreeRow::FindAndSel(const TCHAR*s,long iCol)//ok { for(childRow.MoveToFirst();!childRow.IsOut();childRow.MoveToNext()) { WDGridTreeRow*pRow=childRow.GetCurData(); if(_tcscmp((*pRow)[iCol],s)==0) { WDGridTreeRow*pRow0=pRow->pParent; while(pRow0!=NULL) { pRow0->UnFold(); pRow0=pRow0->pParent; } grid.UnSelect(); grid.SelectRow(pRow->GetIndex(),true); return true; } else if(pRow->FindAndSel(s,iCol)) return true; } return false; } /////////////////////////////////////////////////////////////////////////////////////////////// //WDGridCol WDGridCol::WDGridCol(const TCHAR *n,WDGrid &parent)//ok :grid(parent),name(n),style(0),backColor(RGB(255,255,255)),textColor(RGB(0,0,0)) { brush.CreateSolidBrush(backColor); } void WDGridCol::Select(bool bSel)//ok { if(!grid.IsValidWnd()) return; CDC&dc=grid.GetDC(); CRect rect; GetRect(rect); dc.InvertRect(&rect); } //////////////////////////////////////////////////////////////////////////////////////////////// //WDGridCell WDGridCell::WDGridCell(WDGrid&g,WDGridRow&r,WDGridCol&c):grid(g),row(r),col(c),style(0)//ok { } WDGridCell& WDGridCell::operator =(WDGridCell&cell)//ok { style=cell.style; text=cell.GetText(); return *this; } void WDGridCell::Refresh()//ok { if(!grid.IsValidWnd()) return; if(!grid.OnRefresh(*this)) return; CDC&dc=grid.GetDC(); grid.OnBeforeRefresh(*this); CRect rect; GetRect(rect); rect.bottom++; rect.right++; dc.Rectangle(&rect); GetTextRect(rect); dc.FillSolidRect(&rect,dc.GetBkColor()); if(GetColIndex()==0) { if(row.IsParentRow()) { WDGridTreeRow&treeRow=(WDGridTreeRow&)row; CRect quad; treeRow.GetTreeQuad(quad); rect.left=quad.right; dc.Rectangle(&quad); CPoint pt=quad.CenterPoint(); if(treeRow.IsFold()) { dc.MoveTo(quad.left+2,pt.y); dc.LineTo(quad.right-2,pt.y); dc.MoveTo(pt.x,quad.top+2); dc.LineTo(pt.x,quad.bottom-2); } else { dc.MoveTo(quad.left+2,pt.y); dc.LineTo(quad.right-2,pt.y); if(grid.IsNeedTreeLine()) { dc.MoveTo(pt.x,quad.bottom); dc.LineTo(pt.x,rect.bottom); } } } if(row.IsChildRow()) { WDGridTreeRow&treeRow=(WDGridTreeRow&)row; CRect quad; WDGridTreeRow &parentRow = treeRow.GetParent(); parentRow.GetTreeQuad(quad); if(!treeRow.IsParentRow()) rect.left=quad.right+quad.Width(); if(grid.IsNeedTreeLine()) { CPoint pt=quad.CenterPoint(); dc.MoveTo(pt.x,rect.top); dc.LineTo(pt.x,rect.CenterPoint().y); if(treeRow.IsParentRow()) dc.LineTo(quad.right,rect.CenterPoint().y); else dc.LineTo(quad.right+quad.Width()/2,rect.CenterPoint().y); if(&(parentRow.GetLastChild())!=&treeRow) { dc.MoveTo(pt.x,rect.CenterPoint().y); dc.LineTo(pt.x,rect.bottom); } WDGridTreeRow *pChild=&(treeRow.GetParent()); while(pChild && pChild->IsChildRow()) { WDGridTreeRow*pParent=&(pChild->GetParent()); if(pChild!=&(pParent->GetLastChild())) { pParent->GetTreeQuad(quad); CPoint pt=quad.CenterPoint(); dc.MoveTo(pt.x,rect.top); dc.LineTo(pt.x,rect.bottom); } pChild=pParent; } } } } rect.left+=2;//首字符与左边界间隔2象素。 rect.top+=grid.GetRowSpace();//行与上边界的间隔 int style; if(GetCol().IsCenterAlign()) style=DT_TOP|DT_CENTER|DT_SINGLELINE|DT_EDITCONTROL; else style=DT_TOP|DT_LEFT|DT_SINGLELINE|DT_EDITCONTROL; dc.DrawText((const TCHAR*)text,&rect,style); } void WDGridCell::Select(bool bSel)//ok { if(!grid.IsValidWnd()) return; CDC&dc=grid.GetDC(); CRect rect; GetRect(rect); dc.InvertRect(&rect); } ////////////////////////////////////////////////////////////////////////////////////////////// //WDGrid IMPLEMENT_DYNAMIC(WDGrid, CWnd) WDGrid::WDGrid(bool bTree,long colWidth)//ok :bTreeGrid(bTree),defaultWidth(colWidth),style(0), pDC(NULL),pen(0,1,RGB(168,168,168)),bHScroll(false),bVScroll(false),rowSpace(3), pSelCell(NULL),pCurEdit(NULL),pSelCell2(NULL), pRowSelector(NULL),pColSelector(NULL),pActiveQuad(NULL),m_pAppendRow(NULL), m_iCurCol(-1),m_iCurRow(-1),m_bModified(false) { brush.CreateSolidBrush(RGB(255,255,255)); } WDGrid::~WDGrid()//ok { if(IsTreeGrid()) //将所有根行折叠,使所有子行的析构权由父行行使 for(rowList.MoveToFirst();!rowList.IsOut();rowList.MoveToNext()) { WDGridTreeRow*pTreeRow=(WDGridTreeRow*)rowList.GetCurData(); if(pTreeRow && pTreeRow->IsParentRow()) pTreeRow->Fold(); } if(pActiveQuad!=NULL) DELETE_PTR(pActiveQuad); if(pRowSelector!=NULL) DELETE_PTR(pRowSelector); if(pColSelector!=NULL) DELETE_PTR(pColSelector); if(pDC!=NULL) DELETE_PTR(pDC); if(m_pAppendRow!=NULL) DELETE_PTR(m_pAppendRow); } void WDGrid::Clear()//ok { ClearSel(); if(IsTreeGrid()) //将所有根行折叠,使所有子行的析构权由父行行使 for(rowList.MoveToFirst();!rowList.IsOut();rowList.MoveToNext()) { WDGridTreeRow*pTreeRow=(WDGridTreeRow*)rowList.GetCurData(); if(pTreeRow && pTreeRow->IsParentRow()) pTreeRow->Fold(); } rowList.Clear(); RecalcLayout(); } void WDGrid::InsertRow(long i,WDGridRow*pR)//ok {//插入行的基操作,不能用之直接插入子行 EndEditCell(); WDGridRow*pRow=pR; if(pRow==NULL) { if(IsTreeGrid()) pRow=new WDGridTreeRow(*this); else pRow=new WDGridRow(*this); } pRow->SetIndex(i); rowList.MoveTo(i); rowList.InsertCur(pRow); //新插入行后的行索引需要加1 for(rowList.MoveTo(i+1);!rowList.IsOut();rowList.MoveToNext()) { WDGridRow &row=*rowList.GetCurData(); row.SetIndex(row.GetIndex()+1); } //保持原先行选定内容 for(rowSelList.MoveToLast();!rowSelList.IsOut();rowSelList.MoveToPre()) { if(rowSelList.GetCurData()>=i) rowSelList.SetCurData(rowSelList.GetCurData()+1); else break; } RecalcLayout(); } void WDGrid::AppendRow(WDGridRow*pR)//ok { EndEditCell(); WDGridRow*pRow=pR; if(pRow==NULL) { if(IsTreeGrid()) pRow=new WDGridTreeRow(*this); else pRow=new WDGridRow(*this); } rowList.AddTail(pRow); pRow->SetIndex(rowList.GetCur()); RecalcLayout(); } void WDGrid::DelRow(long i)//ok {//删行基操作,不能用来删除子行或展开根行 EndEditCell(); SelectRow(i,false);//确认当前行未选定 rowList.Del(i); //后行索引需要减1 for(rowList.MoveTo(i);!rowList.IsOut();rowList.MoveToNext()) { WDGridRow &row=*rowList.GetCurData(); row.SetIndex(row.GetIndex()-1); } //保持原先行选定内容 for(rowSelList.MoveToLast();!rowSelList.IsOut();rowSelList.MoveToPre()) { if(rowSelList.GetCurData()>i) rowSelList.SetCurData(rowSelList.GetCurData()-1); else break; } RecalcLayout(); } void WDGrid::MoveRow(long from,long to)//ok { if(from==to||from==to-1) return; rowList.Move(from,to); //重新建立索引 long count=0; for(rowList.MoveToFirst();!rowList.IsOut();rowList.MoveToNext(),count++) rowList.GetCurData()->SetIndex(count); Invalidate(); } void WDGrid::DelRowEx(long i)//ok {//删除一般行或树行 WDGridTreeRow&curRow=(WDGridTreeRow&)GetRow(i); if(!curRow.IsChildRow()&&!curRow.IsParentRow())//不是子行或父行 DelRow(i); else if(curRow.IsChildRow())//子行交由父行删除 { WDGridTreeRow&parentRow=curRow.GetParent(); parentRow.DelChild(parentRow.GetChildIndex(&curRow)); } else//根行折叠后删除 { curRow.Fold(); DelRow(i); } } void WDGrid::InsertCol(long i,WDGridCol*pCol,long width)//ok { EndEditCell(); if(width==0) width=defaultWidth; if(pCol==NULL) pCol=new WDGridCol(NULL,*this); if(IsColEmpty()) pCol->SetLeft(GetLeft()); else if(i==GetColNum()) pCol->SetLeft(GetRight()); else pCol->SetLeft(GetCol(i).GetLeft()); pCol->SetRight(pCol->GetLeft()+width); pCol->SetIndex(i); colList.Insert(i,pCol); //移动后续列位置和索引加1 for(colList.MoveTo(i+1);!colList.IsOut();colList.MoveToNext()) { WDGridCol&col=*colList.GetCurData(); col.Move(width); col.SetIndex(col.GetIndex()+1); } //所有行插入新列,子行的插入由父行执行 for(rowList.MoveToFirst();!rowList.IsOut();rowList.MoveToNext()) if(!rowList.GetCurData()->IsChildRow()) rowList.GetCurData()->InsertCol(i,*pCol); //保持原列选定 for(colSelList.MoveToLast();!colList.IsOut();colList.MoveToPre()) { if(colSelList.GetCurData()>=i) colSelList.SetCurData(colSelList.GetCurData()+1); else break; } RecalcLayout(); } void WDGrid::InsertCol(long i,const TCHAR*name,long width)//ok { InsertCol(i,new WDGridCol(name,*this),width); } void WDGrid::AppendCol(WDGridCol*pCol,long width)//ok { EndEditCell(); if(width==0) width=defaultWidth; if(pCol==NULL) pCol=new WDGridCol(NULL,*this); pCol->SetLeft(GetRight()); pCol->SetRight(pCol->GetLeft()+width); pCol->SetIndex(GetColNum()); colList.AddTail(pCol); //所有行加新列,子行的插入由父行执行 for(rowList.MoveToFirst();!rowList.IsOut();rowList.MoveToNext()) if(!rowList.GetCurData()->IsChildRow()) rowList.GetCurData()->AppendCol(*pCol); RecalcLayout(); } void WDGrid::AppendCol(const TCHAR*name,long width)//ok { AppendCol(new WDGridCol(name,*this),width); } void WDGrid::MoveCol(long from,long to)//ok { if(from==to||from==to-1) return; long cx=colList[from]->GetWidth(); int pos; if(from>to) { colList[from]->SetLeft(pos=colList[to]->GetLeft()); colList[from]->SetRight(pos+cx); for(colList.MoveTo(to);!colList.IsOut()&&colList.GetCur()Move(cx); } else { colList[from]->SetRight(pos=colList[to-1]->GetRight()); colList[from]->SetLeft(pos-cx); for(colList.MoveTo(from+1);!colList.IsOut()&&colList.GetCur()Move(-cx); } //所有行内进行列移动,子行的移动由父行执行 for(rowList.MoveToFirst();!rowList.IsOut();rowList.MoveToNext()) if(!rowList.GetCurData()->IsChildRow()) rowList.GetCurData()->MoveCol(from,to); colList.Move(from,to); long count=0; for(colList.MoveToFirst();!colList.IsOut();colList.MoveToNext(),count++) colList.GetCurData()->SetIndex(count); Invalidate(); } void WDGrid::DelCol(long i)//ok { EndEditCell(); SelectCol(i,false); long width=GetCol(i).GetWidth(); colList.Del(i); for(colList.MoveTo(i);!colList.IsOut();colList.MoveToNext()) { WDGridCol&col=*colList.GetCurData(); col.Move(-width); col.SetIndex(col.GetIndex()-1); } for(rowList.MoveToFirst();!rowList.IsOut();rowList.MoveToNext()) if(!rowList.GetCurData()->IsChildRow()) rowList.GetCurData()->DelCol(i); RecalcLayout(); //保持原列选定 for(colSelList.MoveToLast();!colList.IsOut();colList.MoveToPre()) { if(colSelList.GetCurData()>i) colSelList.SetCurData(colSelList.GetCurData()-1); else break; } } void WDGrid::SetRowNum(long n)//ok { while(GetRowNum()>n) DelRow(GetRowNum()-1); while(GetRowNum()n) DelCol(GetColNum()-1); while(GetColNum()&table)//ok { for(rowSelList.MoveToFirst();!rowSelList.IsOut();rowSelList.MoveToNext()) { MoveTo(rowSelList.GetCurData()); table.AddTail(CurRow()); } } void WDGrid::GetSel(TTable&table)//ok { for(colSelList.MoveToFirst();!colSelList.IsOut();colSelList.MoveToNext()) table.AddTail(colList[colSelList.GetCurData()]); } void WDGrid::Arrange(bool bIncrease)//ok { for(rowList.MoveToFirst();!rowList.IsOut();rowList.MoveToNext()) { WDGridTreeRow&treeRow=(WDGridTreeRow&)(*rowList.GetCurData()); if(treeRow.IsParentRow()) { bool bFold=treeRow.IsFold(); treeRow.Fold(); treeRow.ArrangeChild(bIncrease); if(!bFold) treeRow.SetUnFoldFlag(); } } rowList.Arrange(bIncrease); long i=0; for(rowList.MoveToFirst();!rowList.IsOut();rowList.MoveToNext(),i++) CurRow()->SetIndex(i); for(rowList.MoveToFirst();!rowList.IsOut();rowList.MoveToNext()) if(CurRow()->IsParentRow()&&!CurTreeRow()->IsFold()) CurTreeRow()->UnFold(); OnDataChanged(); Invalidate(); } BOOL WDGrid::Create(const RECT& rect,DWORD wStyle,CWnd* pParent)//ok { const TCHAR* pszClassName = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_SAVEBITS|CS_DBLCLKS, LoadCursor(NULL,IDC_ARROW),HBRUSH(brush.GetSafeHandle())); return CWnd::CreateEx(NULL,pszClassName,NULL,wStyle,rect,pParent,NULL,NULL); } BOOL WDGrid::Create(CWnd*pParent,UINT ID,DWORD wStyle)//ok { CWnd *pStatic=pParent->GetDlgItem(ID); if(pStatic!=NULL) { DWORD dwStyle=pStatic->GetExStyle(); CRect rect; pStatic->GetWindowRect(rect); pParent->ScreenToClient(rect); pStatic->DestroyWindow(); const TCHAR* pszClassName = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_SAVEBITS|CS_DBLCLKS, LoadCursor(NULL,IDC_ARROW),HBRUSH(brush.GetSafeHandle())); return CWnd::CreateEx(0,pszClassName,NULL,wStyle,rect,pParent,ID,NULL); } return FALSE; } void WDGrid::RecalcLayout(BOOL bRedraw)//ok { if(!IsValidWnd()) return; static bool bIn=false; if(bIn) return; bIn=true; bool bOldVScroll=bVScroll; EndEditCell(); CRect rect,rect0; GetClientRect(&rect); GetRect(rect0); int x0=0,y0=0; int cx=GetSystemMetrics(SM_CXVSCROLL); int cy=GetSystemMetrics(SM_CYHSCROLL); if(bVScroll) { rect.right+=cx; y0=GetScrollPos(SB_VERT); } if(bHScroll) { rect.bottom+=cy; x0=GetScrollPos(SB_HORZ); } bHScroll=rect0.Width()>rect.Width(); bVScroll=rect0.Height()>rect.Height(); if(bVScroll&&bHScroll) { rect.right-=cx; rect.bottom-=cy; } else if(!bVScroll&&bHScroll) { rect.bottom-=cy; if(bVScroll=rect0.Height()>rect.Height()) rect.right-=cx; } else if(!bHScroll&&bVScroll) { rect.right-=cx; if(bHScroll=rect0.Width()>rect.Width()) rect.bottom-=cy; } if(bHScroll) { EnableScrollBarCtrl(SB_HORZ); SetScrollRange(SB_HORZ,GetLeft(),rect0.Width()-rect.Width()); if(x0<=rect0.Width()-rect.Width()) SetScrollPos(SB_HORZ,x0); else SetScrollPos(SB_HORZ,rect0.Width()-rect.Width()); } else EnableScrollBarCtrl(SB_HORZ,FALSE); if(bVScroll) { EnableScrollBarCtrl(SB_VERT); SetScrollRange(SB_VERT,GetTop(),rect0.Height()-rect.Height()); if(y0<=rect0.Height()-rect.Height()) SetScrollPos(SB_VERT,y0); else SetScrollPos(SB_VERT,rect0.Height()-rect.Height()); } else EnableScrollBarCtrl(SB_VERT,FALSE); //更新全局CClientDC对象 ClearDC(); PrepareDC(); if(m_pAppendRow!=NULL) DELETE_PTR(m_pAppendRow); m_pAppendRow=IsTreeGrid()?new WDGridTreeRow(*this):new WDGridRow(*this); m_pAppendRow->SetIndex(GetRowNum()); if(bRedraw) Invalidate(); bIn=false; } void WDGrid::PrepareDC(CDC*pD)//ok { if(pD==NULL)//prepare global CClientDC { if(pDC!=NULL)//be ready return; pDC=new CClientDC(this); } else//prepare CPaintDC, global CClientDC object must be destroyed! pDC=pD; pDC->SetROP2(R2_COPYPEN); pDC->SelectObject(&font); pDC->SelectObject(&pen); CPoint pt; GetUpCorner(pt); pDC->SetViewportOrg(pt.x-1,pt.y-1);//不显示左上边界 } void WDGrid::OnBeforeRefresh(WDGridCell&cell)//ok { CDC&dc=GetDC(); WDGridCol&col=cell.GetCol(); dc.SetBkColor(col.GetBackColor()); dc.SetTextColor(col.GetTextColor()); dc.SetBkMode(TRANSPARENT); } long WDGrid::GetColHeaderHeight()//ok { int count=1; for(colList.MoveToFirst();!colList.IsOut();colList.MoveToNext()) { TString text=colList.GetCurData()->GetName(); TListQuenequene; long c=text.Find(_T("\n"),quene)+1; if(c>count) count=c; } return count*GetRowHeight(); } void WDGrid::Invalidate(BOOL bErase)//ok { if(IsValidWnd()) { CWnd::Invalidate(bErase); if(pActiveQuad!=NULL) pActiveQuad->Invalidate(); if(pColSelector!=NULL) pColSelector->Invalidate(); if(pRowSelector!=NULL) pRowSelector->Invalidate(); } } void WDGrid::Refresh()//ok { if(!IsValidWnd()) return; CRect rect; GetClientRect(&rect); long firstRow=0,firstCol=0,lastRow=GetRowNum()-1,lastCol=GetColNum()-1; CPoint pt0(rect.left,rect.top),pt1(rect.right,rect.bottom); PtToCell(pt0,firstRow,firstCol); PtToCell(pt1,lastRow,lastCol); for(rowList.MoveToFirst();!rowList.IsOut();rowList.MoveToNext()) { WDGridRow&row=*rowList.GetCurData(); if(row.GetIndex()>=firstRow&&row.GetIndex()<=lastRow) row.Refresh(); } if(GetRowNum()<=lastRow&&!IsNoAppendButton()) m_pAppendRow->Refresh(); if(IsColSelected()) for(colSelList.MoveToFirst();!colSelList.IsOut();colSelList.MoveToNext()) GetCol(colSelList.GetCurData()).Select(); else if(IsRowSelected()) for(rowSelList.MoveToFirst();!rowSelList.IsOut();rowSelList.MoveToNext()) GetRow(rowSelList.GetCurData()).Select(); } void WDGrid::OnPaint()//ok { ClearDC();//清除可能存在的全局CClientDC对象,避免与CPaintDC对象冲突。 { CPaintDC dc(this); PrepareDC(&dc); Refresh(); } //重建全局CClientDC对象。 pDC=NULL; PrepareDC(); } bool WDGrid::FitLastCol()//ok { if(!IsValidWnd()) return false; if(colList.IsEmpty()) return false; CRect rect,cRect; GetRect(rect); GetClientRect(&cRect); int cx=cRect.Width()-rect.Width(); colList.MoveToLast(); if(cx==0||(cx<0&&cxGetWidth())) return false; colList.GetCurData()->SetRight(colList.GetCurData()->GetRight()+cx); RecalcLayout(); return true; } void WDGrid::UnSelect()//ok { for(colSelList.MoveToFirst();!colSelList.IsOut();colSelList.MoveToNext()) GetCol(colSelList.GetCurData()).Select(false); for(rowSelList.MoveToFirst();!rowSelList.IsOut();rowSelList.MoveToNext()) GetRow(rowSelList.GetCurData()).Select(false); ClearSel(); OnCurChanged(); } void WDGrid::SelectAll()//ok { EndEditCell(); ClearSel(); for(long i=0;iDPtoLP(&pt); GetCol(i).GetRect(rect); rect.top=rect.bottom=pt.y; ShowRect(rect); } GetCol(i).Select(); // lgd 13/09/26 } } else if(colSelList.FindAndDel(i)) GetCol(i).Select(false); OnCurChanged(); } void WDGrid::SelectRow(long i,bool bSel)//ok { if(!IsValidRow(i)) return; if(bSel) { EndEditCell(); if(IsColSelected()) { for(colSelList.MoveToFirst();!colSelList.IsOut();colSelList.MoveToNext()) GetCol(colSelList.GetCurData()).Select(false); colSelList.Clear(); } if(NOT_FOUND==rowSelList.Find(i)) { rowSelList.AddTail(i); rowSelList.Arrange(); //GetRow(i).Select();// lgd 13/09/26 //根据上下线位置上下移动视图,尽量使当前选定行显示 if(IsValidWnd()) { CRect rect; GetClientRect(&rect); CPoint pt=rect.CenterPoint(); pDC->DPtoLP(&pt); GetRow(i).GetRect(rect); rect.left=rect.right=pt.x; ShowRect(rect); } GetRow(i).Select();// lgd 13/09/26 } } else if(rowSelList.FindAndDel(i)) GetRow(i).Select(false); OnCurChanged(); } bool WDGrid::IsSelConnect()//ok { if(IsColSelected()&& colSelList[colSelList.GetLastIndex()]-colSelList[0]+1==colSelList.GetLength()) return true; else if(IsRowSelected()&& rowSelList[rowSelList.GetLastIndex()]-rowSelList[0]+1==rowSelList.GetLength()) return true; return false; } bool WDGrid::IsSelFold()//ok { if(!IsTreeGrid()) return true; for(rowSelList.MoveToFirst();!rowSelList.IsOut();rowSelList.MoveToNext()) { WDGridRow& row=*rowList[rowSelList.GetCurData()]; if(row.IsParentRow()) if(!((WDGridTreeRow&)row).IsFold()) return false; } return true; } WCellCtrl* WDGrid::OnGetCellEdit(WDGridCell&cell)//ok { WDGridCol&col=cell.GetCol(); if(col.IsComboEdit()) return new WCellCombo(cell,true); else if(col.IsComboSel()) return new WCellCombo(cell,false); else if(col.IsRightButton()) return new WCellButtonEdit(cell); else if(col.IsRightSpin()) return new WCellSpinEdit(cell); else return new WCellEdit(cell); } void WDGrid::OnCurChanged() { if(IsEditing()) m_iCurCol=pSelCell->GetColIndex(); else if(GetColSelNum()==1) m_iCurCol=GetSelCol(0).GetIndex(); else m_iCurCol=-1; long iOldCur=m_iCurRow; if(IsEditing()) m_iCurRow=pSelCell->GetRowIndex(); else if(GetRowSelNum()==1) m_iCurRow=GetSelRow(0).GetIndex(); else m_iCurRow=-1; if(pRowSelector) pRowSelector->OnCurRowChanged(); } void WDGrid::SetCurRowIndex(long iRow) { m_iCurRow=iRow; if(pRowSelector) pRowSelector->OnCurRowChanged(); } void WDGrid::BeginEditCell(long i,long j)//ok { if(!IsValidWnd()) return; UnSelect(); EndEditCell(); WDGridCell*pCell=i==GetRowNum()?&((*m_pAppendRow)[j]):&(GetRow(i)[j]); if(pCell->IsReadOnly()) return; bool bModified=false; if(!OnBeforeEdit(*pCell,bModified)) { if(i==GetRowNum()&&bModified)//已经在OnBeforeEdit中修改了cell,并且是AppendRow { if(OnBeforeInsertRow(GetRowNum(),m_pAppendRow)) { rowList.AddTail(m_pAppendRow); OnInsertRow(*m_pAppendRow); OnDataChanged();//<内容改变事件> } m_pAppendRow=NULL; RecalcLayout(); } return; } if(pCurEdit!=NULL) pCurEdit->Destroy();//PostNcDestroy() delete! CRect rect; pCell->GetRect(rect); ShowRect(rect);//if possible ,make cell rect visible. pSelCell=pCell; pSelCell->GetTextRect(rect); if(j==0) { if(pSelCell->row.IsParentRow()) { WDGridTreeRow&treeRow=(WDGridTreeRow&)(pSelCell->row); CRect quad; treeRow.GetTreeQuad(quad); rect.left=quad.right; } else if(pSelCell->row.IsChildRow()) { WDGridTreeRow&treeRow=(WDGridTreeRow&)(pSelCell->row); CRect quad; treeRow.GetParent().GetTreeQuad(quad); rect.left=quad.right+quad.Width(); } } pDC->LPtoDP(&rect); pCurEdit=OnGetCellEdit(*pSelCell); if(pCurEdit!=NULL) { pCurEdit->Create(rect); OnCurChanged(); } else pSelCell=NULL; } void WDGrid::EndEditCell()//ok { static bool bIn=false; if(bIn)//防止重复进入 return; bIn=true; if(IsEditing()) { if(pCurEdit->IsModified()) { CString text; pCurEdit->GetNewText(text); if(OnModified(*pSelCell,text))//<修改事件响应> { pSelCell->SetText(text); pSelCell->Refresh(); if(IsNewRow(pSelCell->GetRowIndex()))//新行 { if(OnBeforeInsertRow(GetRowNum(),m_pAppendRow)) { rowList.AddTail(m_pAppendRow); OnInsertRow(*m_pAppendRow); OnDataChanged();//<内容改变事件> } m_pAppendRow=NULL; } else OnDataChanged();//<内容改变事件> } } pSelCell=NULL;//1! pCurEdit->Hide();//2! if(m_pAppendRow==NULL) RecalcLayout(); } bIn=false; } void WDGrid::CancelEditCell()//ok { if(IsEditing()) { pSelCell=NULL;//1! pCurEdit->Hide();//2! } } void WDGrid::PtToCell(CPoint pt,long &row,long &col)//ok { if(pDC==NULL) return; pDC->DPtoLP(&pt); CRect rect; GetRect(rect); row=(pt.y-GetTop())/GetRowHeight(); col=0; for(colList.MoveToFirst();!colList.IsOut();colList.MoveToNext(),col++) { WDGridCol&col=*colList.GetCurData(); if(pt.x=col.GetLeft()) break; } } void WDGrid::ShowRect(CRect rect)//ok {//左上角优先 if(!IsValidWnd()) return; CRect cRect; GetClientRect(&cRect); pDC->DPtoLP(&cRect); int x0=GetLeft(); if(bHScroll) x0=GetScrollPos(SB_HORZ); int y0=GetTop(); if(bVScroll) y0=GetScrollPos(SB_VERT); int cx=0,cy=0; if(rect.topcRect.Height())//上界在上 cy=rect.top-y0; else if((rect.bottom>cRect.bottom&&rect.Height()<=cRect.Height())||rect.top>cRect.bottom) //下界在下并且高度足够,或全在下 cy=rect.bottom-cRect.bottom+1; if(rect.leftcRect.Width())//左界在左 cx=rect.left-x0; else if((rect.right>cRect.right&&rect.Width()<=cRect.Width())||rect.left>cRect.right) //右界在右并且宽度足够,或全在右 cx=rect.right-cRect.right+1; MoveView(cx,cy); } void WDGrid::ShowAppendRow() { CRect rect; GetClientRect(&rect); CPoint pt=rect.CenterPoint(); pDC->DPtoLP(&pt); m_pAppendRow->GetRect(rect); rect.left=rect.right=pt.x; ShowRect(rect); } bool WDGrid::FindAndSel(const TCHAR*s,long iCol)//ok { if(IsTreeGrid()) { for(MoveToFirst();!IsOut();MoveToNext()) if(_tcscmp((*CurRow())[iCol],s)==0) { UnSelect(); SelectRow(GetCur(),true); return true; } else if(CurTreeRow()->FindAndSel(s,iCol)) return true; } else for(MoveToFirst();!IsOut();MoveToNext()) if(_tcscmp((*CurRow())[iCol],s)==0) { UnSelect(); SelectRow(GetCur(),true); return true; } return false; } void WDGrid::MoveView(int cx,int cy)//ok {//无限制调用 if(!IsValidWnd()) return; CRect rect; GetClientRect(&rect); int x0=GetScrollPos(SB_HORZ); int y0=GetScrollPos(SB_VERT); if(bHScroll) { if(cx+x0GetRight()-rect.Width()) cx=GetRight()-rect.Width()-x0; } if(bVScroll) { if(cy+y0GetBottom()-rect.Height()) cy=GetBottom()-rect.Height()-y0; } if(cx==0&&cy==0) return; SetScrollPos(SB_HORZ,x0+cx); SetScrollPos(SB_VERT,y0+cy); //更新全局CClientDC对象 ClearDC(); PrepareDC(); EndEditCell(); CWnd::ScrollWindow(-cx,-cy,&rect); // lgd 13/09/26 if(IsColSel()) { pColSelector->ScrollWindow(-cx,0); pColSelector->Invalidate(); } if(IsRowSel()) { pRowSelector->ScrollWindow(0,-cy); pRowSelector->Invalidate(); } } BEGIN_MESSAGE_MAP(WDGrid, CWnd) ON_WM_SIZE() ON_MESSAGE (WM_SETFONT, OnSetFont) ON_MESSAGE (WM_SETTEXT, OnSetText) ON_WM_CANCELMODE() ON_WM_GETDLGCODE() ON_WM_PAINT() ON_WM_VSCROLL() ON_WM_HSCROLL() ON_WM_MOUSEWHEEL() ON_WM_CREATE() ON_WM_CTLCOLOR() ON_WM_LBUTTONDBLCLK() ON_WM_LBUTTONDOWN() ON_WM_KEYDOWN() ON_WM_SETCURSOR() ON_WM_ERASEBKGND() ON_WM_KILLFOCUS() ON_WM_SETFOCUS() ON_WM_DESTROY() ON_WM_RBUTTONUP() ON_WM_TIMER() END_MESSAGE_MAP() int WDGrid::OnCreate(LPCREATESTRUCT lpCreateStruct)//ok { if (CWnd::OnCreate(lpCreateStruct) == -1) return -1; CreateFont(); RecalcLayout(); EnableToolTips(); if(IsColSel()) pColSelector=new WColSelector(*this); if(IsRowSel()) pRowSelector=new WRowSelector(*this); if(IsRowSel()&&IsColSel()) pActiveQuad=new WDGActiveQuad(*this); return 0; } void WDGrid::OnTimer(UINT_PTR nIDEvent) { CWnd::OnTimer(nIDEvent); if(nIDEvent==0) { KillTimer(0); if(pSelCell2!=NULL) { long i=pSelCell2->GetRowIndex(),j=pSelCell2->GetColIndex(); pSelCell2=NULL; CancelEditCell(); BeginEditCell(i,j); } } else if(nIDEvent==1) { KillTimer(1); EndEditCell(); } } void WDGrid::AutoEditCell(WDGridCell*pCell) { if(IsCellLocking()) return; if(pCell==NULL&&IsEditing()) pSelCell2=pSelCell; else pSelCell2=pCell; SetTimer(0,0,0); } void WDGrid::AutoCloseCell(int iTime) { SetTimer(1,iTime,0); } void WDGrid::OnSize(UINT nType, int cx, int cy)//ok { CWnd::OnSize(nType, cx, cy); RecalcLayout(false); } void WDGrid::CreateFont (void)//ok { if (font.GetSafeHandle() == 0) { CWnd* pwndParent = GetParent(); if (pwndParent) { LOGFONT logFont; CFont* pfontParent = pwndParent->GetFont(); pfontParent->GetObject (sizeof (logFont),&logFont); logFont.lfWidth = 0; logFont.lfQuality = DEFAULT_QUALITY; font.CreateFontIndirect (&logFont); rowHeight=abs(logFont.lfHeight)+1;//这个象素为与下边界线之间的空隙 } } } LRESULT WDGrid::OnSetText (WPARAM wParam, LPARAM lParam)//ok { Default(); RecalcLayout(); return (0); } LRESULT WDGrid::OnSetFont (WPARAM wParam, LPARAM lParam)//ok { LOGFONT logFont; Default(); HFONT hFont = (HFONT) wParam; CFont* pfontDisplay = CFont::FromHandle (hFont); pfontDisplay->GetObject (sizeof (logFont), &logFont); logFont.lfWidth = 0; logFont.lfQuality = PROOF_QUALITY; font.DeleteObject(); font.CreateFontIndirect(&logFont); rowHeight=abs(logFont.lfHeight)+1;//这个象素为与下边界线之间的空隙 RecalcLayout(); return (0L); } void WDGrid::OnCancelMode (void)//ok { if (GetCapture() == this) ReleaseCapture(); CWnd::OnCancelMode(); } UINT WDGrid::OnGetDlgCode(void)//ok { return (DLGC_WANTALLKEYS);//DLGC_BUTTON;// } void WDGrid::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)//ok { CRect rect; GetClientRect(&rect); int yMin,yMax; GetScrollRange(SB_VERT,&yMin,&yMax); int y0=GetScrollPos(SB_VERT); int y=y0; switch (nSBCode) { case SB_TOP: y = yMin; break; case SB_BOTTOM: y = yMax; break; case SB_LINEUP: y -=GetRowHeight(); break; case SB_LINEDOWN: y +=GetRowHeight(); break; case SB_PAGEUP: y -=rect.Height(); break; case SB_PAGEDOWN: y +=rect.Height(); break; case SB_THUMBTRACK: { SCROLLINFO si; GetScrollInfo(SB_VERT,&si); y = si.nTrackPos; } break; } if(yyMax) y=yMax; MoveView(0,y-y0); CWnd::OnVScroll(nSBCode, nPos, pScrollBar); SetFocus(); } void WDGrid::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)//ok { CRect rect; GetClientRect(&rect); int xMin,xMax; GetScrollRange(SB_HORZ,&xMin,&xMax); int x0=GetScrollPos(SB_HORZ); int x=x0; switch (nSBCode) { case SB_TOP: x = xMin; break; case SB_BOTTOM: x = xMax; break; case SB_LINEUP: x-= defaultWidth; break; case SB_LINEDOWN: x+= defaultWidth; break; case SB_PAGEUP: x-=rect.Width(); break; case SB_PAGEDOWN: x+=rect.Width(); break; case SB_THUMBTRACK: { SCROLLINFO si; GetScrollInfo(SB_HORZ,&si); x = si.nTrackPos; } break; } if(xxMax) x=xMax; MoveView(x-x0,0); CWnd::OnHScroll(nSBCode, nPos, pScrollBar); SetFocus(); } BOOL WDGrid::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)//ok { //if(bVScroll) //{ // int y0=GetScrollPos(SB_VERT); // OnVScroll(SB_THUMBTRACK,(y0-GetRowHeight()*zDelta/120), NULL); //} //return CWnd::OnMouseWheel(nFlags, zDelta, pt); //axc add 2015-05-04 支持垂直滚动条使用鼠标滚轮进行快速变化 if(bVScroll) { int y0=GetScrollPos(SB_VERT); if (zDelta > 0) OnVScroll(SB_LINEUP,(y0-GetRowHeight()*zDelta/120), NULL); else OnVScroll(SB_LINEDOWN,(y0-GetRowHeight()*zDelta/120), NULL); } return CWnd::OnMouseWheel(nFlags, zDelta, pt); } HBRUSH WDGrid::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)//ok { HBRUSH hbr = CWnd::OnCtlColor(pDC, pWnd, nCtlColor); if(pCurEdit!=NULL&&pWnd==pCurEdit->GetWnd()) { WDGridCol&col=GetCol(pSelCell->GetColIndex()); pDC->SetTextColor(col.GetTextColor()); pDC->SetBkColor(col.GetBackColor()); pDC->SelectObject(&col.GetBrush()); return (HBRUSH)(col.GetBrush().GetSafeHandle()); } return hbr; } bool WDGrid::IsMyFocus(const CWnd*pWnd)const//ok { return pWnd==this||IsChild(pWnd); } void WDGrid::OnKillFocus(CWnd*pNewWnd)//ok { CWnd::OnKillFocus(pNewWnd); if(!IsMyFocus(pNewWnd)) ShowActive(false); } void WDGrid::OnSetFocus(CWnd*pOldWnd)//ok { CWnd::OnSetFocus(pOldWnd); ShowActive(); } void WDGrid::OnLButtonDblClk(UINT nFlags, CPoint point)//ok { //if(!IsMyFocus(GetFocus()))removed on 050323 SetFocus(); EndEditCell(); long col,row; PtToCell(point,row,col);//point changed if(row>=0&&col>=0&&colDPtoLP(&point); if(treeRow.IsParentRow()&&treeRow.IsPtInTreeQuad(point)) { UnSelect(); if(treeRow.IsFold()) treeRow.UnFold(); else treeRow.Fold(); } else BeginEditCell(row,col); } else BeginEditCell(row,col); } else if(!IsNoAppendButton()&&row==GetRowNum())//点击AppendRow BeginEditCell(row,col); else UnSelect(); } else UnSelect(); CWnd::OnLButtonDblClk(nFlags, point); } void WDGrid::OnLButtonDown(UINT nFlags, CPoint point)//ok { //if(!IsMyFocus(GetFocus()))removed on 050323 SetFocus(); EndEditCell(); long col,row; PtToCell(point,row,col);//point changed if(row>=0&&col>=0&&colDPtoLP(&point); if(treeRow.IsParentRow()&&treeRow.IsPtInTreeQuad(point)) { UnSelect(); if(treeRow.IsFold()) treeRow.UnFold(); else treeRow.Fold(); } else BeginEditCell(row,col); } else BeginEditCell(row,col); } else if(!IsNoAppendButton()&&row==GetRowNum())//点击AppendRow BeginEditCell(row,col); else UnSelect(); } else UnSelect(); CWnd::OnLButtonDown(nFlags, point); } void WDGrid::OnRButtonUp(UINT nFlags, CPoint point)//ok { CWnd::OnRButtonUp(nFlags, point); SetFocus(); long col,row; PtToCell(point,row,col); if(IsValidRow(row)&&IsValidCol(col)) { ClientToScreen(&point); OnRClickCell(GetCell(row,col),point); } } void WDGrid::FilterDelUnable()//ok { for(rowSelList.MoveToFirst();!rowSelList.IsOut();rowSelList.MoveToNext()) if(GetRow(rowSelList.GetCurData()).IsDelUnable()) rowSelList.DelCur(); Invalidate(); } bool WDGrid::IsSelDelUnable()//ok { for(rowSelList.MoveToFirst();!rowSelList.IsOut();rowSelList.MoveToNext()) if(GetRow(rowSelList.GetCurData()).IsDelUnable()) return true; return false; } void WDGrid::ClipSelect()//ok { pasteList.Clear(); for(long i=0;i rowSel(rowSelList); ClearSel(); for(i=rowSel.GetLastIndex();i>=0;i--) { long cur=rowSel[i]; if(!rowList[cur]->IsTreeRow()) { pasteList.InsertHead(rowList[cur]); SelectRow(cur,false); rowList[cur]=NULL; DelRow(cur); } else { WDGridTreeRow*pNewRow=new WDGridTreeRow(*this); *pNewRow<<(WDGridTreeRow&)GetRow(cur);//需要同时取走扩展数据 DelRowEx(cur); pasteList.InsertHead(pNewRow); } } } void WDGrid::Paste(long i)//ok { UnSelect(); int num=pasteList.GetLength(); for(pasteList.MoveToLast();!pasteList.IsEmpty();) { WDGridRow*pRow=pasteList.FetchCur(); if(i==GetRowNum()) AppendRow(pRow); else if(!GetRow(i).IsChildRow())//不是子行 InsertRow(i,pRow); else//由父行来执行插入 { WDGridTreeRow&curRow=GetTreeRow(i); WDGridTreeRow&parentRow=curRow.GetParent(); parentRow.InsertChild(parentRow.GetChildIndex(&curRow),(WDGridTreeRow*)pRow); } } for(int j=0;jAppendChild(); WDGridRow*pRow=pTreeRow; if(IsTreeGrid()&&GetRow(cur).IsChildRow()) { WDGridTreeRow&curRow=GetTreeRow(cur); WDGridTreeRow&parentRow=curRow.GetParent(); long iChild=parentRow.GetChildIndex(&curRow); WDGridTreeRow*pChild=pTreeRow; if(OnBeforeInsertChild(parentRow,iChild,pChild)) { parentRow.InsertChild(iChild,pChild); SelectRow(cur+1,false); SelectRow(cur); OnInsertRow(GetRow(cur)); OnDataChanged(); return true; } } else if(OnBeforeInsertRow(cur,pRow)) { InsertRow(cur,pRow); SelectRow(cur+1,false); SelectRow(cur); OnInsertRow(GetRow(cur)); OnDataChanged(); return true; } } return false; } bool WDGrid::DoInsertTreeAfter() { if(IsRowFixLength()||!IsTreeGrid()) return false; if(rowSelList.GetLength()==1) { long cur=rowSelList[0]+1; WDGridTreeRow*pTreeRow=new WDGridTreeRow(*this); pTreeRow->AppendChild(); WDGridRow*pRow=pTreeRow; if(IsTreeGrid()&&GetRow(cur-1).IsChildRow()) { WDGridTreeRow&curRow=GetTreeRow(cur-1); WDGridTreeRow&parentRow=curRow.GetParent(); long iChild=parentRow.GetChildIndex(&curRow)+1; WDGridTreeRow*pChild=pTreeRow; if(OnBeforeInsertChild(parentRow,iChild,pChild)) { GetTreeRow(cur-1).Fold(); parentRow.InsertChild(iChild,pChild); SelectRow(cur-1,false); SelectRow(cur); OnInsertRow(GetRow(cur)); OnDataChanged(); return true; } } else if(OnBeforeInsertRow(cur,pRow)) { if(IsTreeGrid()) GetTreeRow(cur-1).Fold(); InsertRow(cur,pRow); SelectRow(cur-1,false); SelectRow(cur); OnInsertRow(GetRow(cur)); OnDataChanged(); return true; } } return false; } bool WDGrid::DoAppendRow(bool bSel) { if(!IsRowFixLength()) { WDGridRow*pRow=NULL; long cur=GetRowNum(); if(OnBeforeInsertRow(cur,pRow)) { UnSelect();//add on 050324 AppendRow(pRow); if(bSel) SelectRow(cur,true); else if(!IsNoAppendButton()) ShowAppendRow(); OnInsertRow(GetRow(cur)); OnDataChanged(); return true; } } return false; } bool WDGrid::DoAppendTree() { if(!IsRowFixLength()&&IsTreeGrid()) { WDGridTreeRow*pTreeRow=new WDGridTreeRow(*this); pTreeRow->AppendChild(); WDGridRow*pRow=pTreeRow; long cur=GetRowNum(); if(OnBeforeInsertRow(cur,pRow)) { AppendRow(pRow); SelectRow(cur,true); OnInsertRow(GetRow(cur)); OnDataChanged(); return true; } } return false; } bool WDGrid::DoAppendChild() { if(IsTreeGrid()&&rowSelList.GetLength()==1&&!IsRowFixLength()) { long cur=rowSelList[0]; WDGridTreeRow&treeRow=(WDGridTreeRow&)GetRow(cur); if(treeRow.IsTreeRow()) { WDGridTreeRow*pRow=NULL; if(OnBeforeInsertChild(treeRow,treeRow.GetChildNum(),pRow)) { treeRow.AppendChild(pRow); SelectRow(cur,false); treeRow.UnFold(); WDGridRow&newRow=treeRow.GetLastChild(); SelectRow(newRow.GetIndex(),true); OnInsertRow(newRow); OnDataChanged(); return true; } } } return false; } bool WDGrid::DoDelete() { if((IsRowSelected()&&!IsRowFixLength())) { FilterDelUnable(); if(OnBeforeDeleteRow()) { TArray rowSel(rowSelList); ClearSel(); for(long i=rowSel.GetLastIndex();i>=0;i--) DelRowEx(rowSel[i]); OnEndDeleteRow(); OnDataChanged(); return true; } } else if((IsColSelected()&&!IsColFixLength())) { if(OnBeforeDeleteCol()) { TArray colSel(colSelList); ClearSel(); for(long i=colSel.GetLastIndex();i>=0;i--) DelCol(colSel[i]); OnEndDeleteCol(); OnDataChanged(); return true; } } return false; } bool WDGrid::DoClip() { if(IsRowFixLength()||!OnBeforeClip()) return false; FilterDelUnable(); ClipSelect(); OnEndClip(); OnDataChanged(); return true; } bool WDGrid::DoCopy() { if(!OnBeforeCopy()) return false; pasteList.Clear(); for(rowSelList.MoveToFirst();!rowSelList.IsOut();rowSelList.MoveToNext()) { WDGridRow*pRow=&GetRow(rowSelList.GetCurData()); if(pRow->IsTreeRow()&&((WDGridTreeRow*)pRow)->IsFold()) { WDGridTreeRow*pNewRow=new WDGridTreeRow(*this); *pNewRow=*((WDGridTreeRow*)pRow); pNewRow->Fold(); pasteList.AddTail(pNewRow); } else { WDGridRow*pNewRow; if(pRow->IsTreeRow()) pNewRow=new WDGridTreeRow(*this); else pNewRow=new WDGridRow(*this); *pNewRow=*pRow; pasteList.AddTail(pNewRow); } } OnEndCopy(); return true; } bool WDGrid::DoPaste() { if(IsRowFixLength()||rowSelList.GetLength()>1||IsNoPaste()||pasteList.IsEmpty()) return false; int i=rowSelList.IsEmpty()?GetRowNum():rowSelList[0]; if(!OnBeforePaste(i)) return false; Paste(i); OnEndPaste(); OnDataChanged(); return true; } bool WDGrid::DoPasteChild() { if(IsRowFixLength()||!IsTreeGrid()||rowSelList.GetLength()!=1||IsNoPaste()||pasteList.IsEmpty()) return false; int i=rowSelList[0]; WDGridTreeRow&treeRow=GetTreeRow(i); if(!OnBeforePasteChild(treeRow)) return false; UnSelect(); treeRow.UnFold(); i+=treeRow.GetRowNum(); int num=pasteList.GetLength(); for(pasteList.MoveToFirst();!pasteList.IsEmpty();pasteList.MoveToNext()) { treeRow.AppendChild((WDGridTreeRow*)pasteList.GetCurData()); pasteList.SetCurData(NULL); pasteList.DelCur(); } for(int j=0;j1) BeginEditCell(pSelCell->GetRowIndex(),(pSelCell->GetColIndex()+1)%GetColNum()); else if(colSelList.GetLength()==1&&GetColNum()>1) { long col=colSelList[0]; SelectCol(col,false); SelectCol((col+1)%GetColNum()); } else if(bHScroll) OnHScroll(SB_LINEDOWN,0,NULL); } break; case VK_LEFT: { if(IsEditing()&&GetColNum()>1) BeginEditCell(pSelCell->GetRowIndex(),(pSelCell->GetColIndex()-1+GetColNum())%GetColNum()); else if(colSelList.GetLength()==1&&GetColNum()>1) { long col=colSelList[0]; SelectCol(col,false); SelectCol((col-1+GetColNum())%GetColNum()); } else if(bHScroll) OnHScroll(SB_LINEUP,0,NULL); } break; case VK_UP: { if(IsEditing()) { if(IsNoAppendButton()) { if(GetRowNum()>1) BeginEditCell((pSelCell->GetRowIndex()-1+GetRowNum())%GetRowNum(),pSelCell->GetColIndex()); } else if(GetRowNum()>0) BeginEditCell((pSelCell->GetRowIndex()+GetRowNum())%(GetRowNum()+1),pSelCell->GetColIndex()); } else if(rowSelList.GetLength()==1&&GetRowNum()>1) { long row=rowSelList[0]; SelectRow(row,false); SelectRow((row-1+GetRowNum())%GetRowNum()); } else if(bVScroll) OnVScroll(SB_LINEUP,0,NULL); } break; case VK_DOWN: if(IsEditing()) { if(IsNoAppendButton()) { if(GetRowNum()>1) BeginEditCell((pSelCell->GetRowIndex()+1)%GetRowNum(),pSelCell->GetColIndex()); } else { if(pSelCell->GetRowIndex()==GetRowNum()) { long oldNum=GetRowNum(),colIndex=pSelCell->GetColIndex(); EndEditCell(); if(GetRowNum()==oldNum) DoAppendRow(false); BeginEditCell(GetRowNum(),colIndex); } else BeginEditCell(pSelCell->GetRowIndex()+1,pSelCell->GetColIndex()); } } else if(rowSelList.GetLength()==1&&GetRowNum()>1) { long row=rowSelList[0]; SelectRow(row,false); SelectRow((row+1)%GetRowNum()); } else if(bVScroll) OnVScroll(SB_LINEDOWN,0,NULL); break; case VK_PRIOR: if(bVScroll) OnVScroll(SB_PAGEUP,0,NULL); break; case VK_NEXT: if(bVScroll) OnVScroll(SB_PAGEDOWN,0,NULL); break; case VK_DELETE: DoDelete(); break; case VK_INSERT://插入行或目录(带有一个子行),或插入列 if(IsRowSelected()) { if(bCtrl) DoInsertTree(); else DoInsertRow(); } else if(IsColSelected()) DoInsertCol(); break; case 78://N,新建行或目录(带有一个子行),或新建列 if(IsColSelected()) DoInsertColAfter(); else if(IsRowSelected()) { if(bCtrl) DoInsertTreeAfter(); else DoInsertRowAfter(); } else { if(bCtrl) DoAppendTree(); else DoAppendRow(); } break; case 84://T,为树行新建一子行 DoAppendChild(); break; case VK_TAB: if(IsEditing()) { if(GetColNum()>1) BeginEditCell(pSelCell->GetRowIndex(),(pSelCell->GetColIndex()+1)%GetColNum()); else EndEditCell(); } break; case VK_RETURN: if(IsEditing()) { if(IsNoAppendButton()) { if(GetRowNum()>1) BeginEditCell((pSelCell->GetRowIndex()+1)%GetRowNum(),pSelCell->GetColIndex()); else EndEditCell(); } else { if(pSelCell->GetRowIndex()==GetRowNum()) { long oldNum=GetRowNum(),colIndex=pSelCell->GetColIndex(); EndEditCell(); if(GetRowNum()==oldNum) DoAppendRow(false); BeginEditCell(GetRowNum(),colIndex); } else BeginEditCell(pSelCell->GetRowIndex()+1,pSelCell->GetColIndex()); } } else if(rowSelList.GetLength()==1&&GetColNum()>0) BeginEditCell(rowSelList[0],0); break; case VK_ESCAPE: if(IsEditing()) { CancelEditCell(); SetFocus(); } else UnSelect(); break; case VK_HOME: { int cx=bHScroll?GetLeft()-GetScrollPos(SB_HORZ):0; int cy=bVScroll?GetTop()-GetScrollPos(SB_VERT):0; MoveView(cx,cy); } break; case 82://"R" if(IsSortEnable()) Arrange(); break; case 85://"U" if(IsSortEnable()) Arrange(false); break; case 65://"A" if(!IsSingleSelRow()||GetRowNum()==1)//可以多选或当前行只有一行 SelectAll(); break; case 88://"X" DoClip(); break; case 86://"V" if(bCtrl) DoPasteChild(); else DoPaste(); break; case 67://"C" DoCopy(); break; } CWnd::OnKeyDown(nChar, nRepCnt, nFlags); } BOOL WDGrid::PreTranslateMessage(MSG* pMsg) { if(pMsg->message==WM_KEYDOWN) { int nVirtKey = (int)pMsg->wParam; // virtual-key code if(IsEditing()) { if(nVirtKey==VK_RETURN|| nVirtKey==VK_ESCAPE|| nVirtKey==VK_PRIOR|| nVirtKey==VK_NEXT|| nVirtKey==VK_TAB|| (nVirtKey==VK_UP&&pCurEdit->IsUpEnd())|| (nVirtKey==VK_DOWN&&pCurEdit->IsDownEnd())|| (nVirtKey==VK_LEFT&&pCurEdit->IsLeftEnd())|| (nVirtKey==VK_RIGHT&&pCurEdit->IsRightEnd())) { OnKeyDown((UINT)nVirtKey,NULL,NULL); return true; } } else if(VK_TAB==nVirtKey&&GetFocus()==this) { GetParent()->SetFocus(); return true; } else if(nVirtKey==VK_RETURN||nVirtKey==VK_ESCAPE) { CWnd *pWnd=GetParent(); if(pWnd->IsKindOf(RUNTIME_CLASS(CDialog))|| pWnd->IsKindOf(RUNTIME_CLASS(CPropertySheet))|| pWnd->IsKindOf(RUNTIME_CLASS(CPropertyPage))) { pWnd->PostMessage(pMsg->message,pMsg->wParam,pMsg->lParam); return true; } } } else if(pMsg->message==WM_COMMAND&&HIWORD(pMsg->wParam)==0)//菜单命令 { switch(LOWORD(pMsg->wParam)) { case ID_WDGRID_INS_ROW: { DoInsertRow(); return true; } case ID_WDGRID_DEL_ROW: { DoDelete(); return true; } case ID_WDGRID_ADD_ROW: { DoAppendRow(); return true; } case ID_WDGRID_SELECT_ALL: { SelectAll(); return true; } case ID_WDGRID_COPY_ROW: { DoCopy(); return true; } case ID_WDGRID_CUT_ROW: { DoClip(); return true; } case ID_WDGRID_PASTE_ROW: { DoPaste(); return true; } case ID_WDGRID_INS_COL: { DoInsertCol(); return true; } case ID_WDGRID_DEL_COL: { DoDelete(); return true; } case ID_WDGRID_ADD_COL: { DoAppendCol(); return true; } } } return CWnd::PreTranslateMessage(pMsg); } BOOL WDGrid::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) { BOOL result=CWnd::OnSetCursor(pWnd, nHitTest, message); return result; } BOOL WDGrid::OnEraseBkgnd(CDC* pDC) { if(bVScroll&&bHScroll) return true; return CWnd::OnEraseBkgnd(pDC); } INT_PTR WDGrid::OnToolHitTest(CPoint point,TOOLINFO*pTI)const { CString sTip; long row,col; ((WDGrid*)this)->PtToCell(point,row,col); if(IsValidRow(row)&&IsValidCol(col)&&OnCellTip(row,col,sTip)) { pTI->hwnd = m_hWnd; pTI->uId =(UINT_PTR)m_hWnd; pTI->uFlags |= TTF_IDISHWND|TTF_NOTBUTTON|TTF_ALWAYSTIP; pTI->lpszText=new TCHAR[20]; wsprintf(pTI->lpszText,sTip); return row*10+col; } return -1; } void WDGrid::OnRClickRow(WDGridRow &row, CPoint point) { if(IsNoDefaultMenu()||IsReadOnly()||IsRowFixLength()) return; CMenu popup; popup.CreatePopupMenu(); if(GetRowSelNum() > 1 && IsRowSelected(row.GetIndex())) { popup.AppendMenu(MF_STRING, ID_WDGRID_DEL_ROW, _T("删除(Del)")); popup.AppendMenu(MF_STRING, ID_WDGRID_ADD_ROW, _T("新建行(N)")); if(!IsNoPaste()) { popup.AppendMenu(MF_STRING, ID_WDGRID_COPY_ROW, _T("复制(C)")); popup.AppendMenu(MF_STRING, ID_WDGRID_CUT_ROW, _T("剪切(X)")); } } else { UnSelect(); SelectRow(row.GetIndex(), true); popup.AppendMenu(MF_STRING, ID_WDGRID_INS_ROW, _T("插入行(Ins)")); if(!row.IsDelUnable()) popup.AppendMenu(MF_STRING, ID_WDGRID_DEL_ROW, _T("删除行(Del)")); popup.AppendMenu(MF_STRING, ID_WDGRID_ADD_ROW, _T("新建行(N)")); if(!IsNoPaste()) { popup.AppendMenu(MF_STRING, ID_WDGRID_COPY_ROW, _T("复制(C)")); popup.AppendMenu(MF_STRING, ID_WDGRID_CUT_ROW, _T("剪切(X)")); if(GetRowSelNum() == 1 && pasteList.GetDataNum() > 0) popup.AppendMenu(MF_STRING, ID_WDGRID_PASTE_ROW, _T("粘贴(V)")); } } popup.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this); } void WDGrid::OnRClickCol(WDGridCol &col, CPoint point) { if(IsNoDefaultMenu()||IsReadOnly()||IsColFixLength()) return; CMenu popup; popup.CreatePopupMenu(); if(GetColSelNum() > 1 && IsColSelected(col.GetIndex())) { popup.AppendMenu(MF_STRING, ID_WDGRID_DEL_COL, _T("删除(Del)")); popup.AppendMenu(MF_STRING, ID_WDGRID_ADD_COL, _T("新建列(N)")); } else { UnSelect(); SelectCol(col.GetIndex(), true); popup.AppendMenu(MF_STRING, ID_WDGRID_INS_COL, _T("插入列(Ins)")); popup.AppendMenu(MF_STRING, ID_WDGRID_DEL_COL, _T("删除列(Del)")); popup.AppendMenu(MF_STRING, ID_WDGRID_ADD_COL, _T("新建列(N)")); } popup.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this); } void WDGrid::OnRClickQuad(CPoint point) { if(IsNoDefaultMenu()||IsReadOnly()||IsRowFixLength()) return; CMenu popup; popup.CreatePopupMenu(); if(!IsRowSelected()) { UnSelect(); popup.AppendMenu(MF_STRING, ID_WDGRID_ADD_ROW, _T("新建行(N)")); if(pasteList.GetDataNum() > 0) popup.AppendMenu(MF_STRING, ID_WDGRID_PASTE_ROW, _T("粘贴(V)")); } else { popup.AppendMenu(MF_STRING, ID_WDGRID_DEL_ROW, _T("删除(Del)")); popup.AppendMenu(MF_STRING, ID_WDGRID_ADD_ROW, _T("新建行(N)")); popup.AppendMenu(MF_STRING, ID_WDGRID_COPY_ROW, _T("复制(C)")); popup.AppendMenu(MF_STRING, ID_WDGRID_CUT_ROW, _T("剪切(X)")); if(GetRowSelNum() == 1 && pasteList.GetDataNum() > 0) popup.AppendMenu(MF_STRING, ID_WDGRID_PASTE_ROW, _T("粘贴(V)")); } if(!IsEmpty()) popup.AppendMenu(MF_STRING, ID_WDGRID_SELECT_ALL, _T("全选(A)")); popup.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this); } ////////////////////////////////////////////////////////////////////////////////////////////// bool WCellCtrl::IsMyFocus(CWnd*pNewWnd) { return pNewWnd==GetWnd()||GetWnd()->IsChild(pNewWnd); } void WCellCtrl::Destroy() { GetWnd()->DestroyWindow(); } void WCellCtrl::Hide() { GetWnd()->ShowWindow(SW_HIDE); GetWnd()->EnableWindow(FALSE); } //WCellEdit BEGIN_MESSAGE_MAP(WCellEdit, CEdit) ON_WM_KILLFOCUS() ON_WM_SETFOCUS() END_MESSAGE_MAP() WCellEdit::WCellEdit(WDGridCell&c):WCellCtrl(c) { } CWnd* WCellEdit::GetWnd() { return this; } void WCellEdit::Create(CRect&rect) { WDGrid&grid=cell.GetGrid(); int style=WS_VISIBLE|WS_CHILD|WS_CLIPCHILDREN | WS_CLIPSIBLINGS|ES_AUTOHSCROLL|ES_MULTILINE; if(cell.GetCol().IsCenterAlign()) style|=ES_CENTER; CEdit::Create(style,CRect(0,0,0,0),&grid,101); SetFont(&grid.GetFont()); rect.left+=2;//首字符与左边界间隔2象素。 SetWindowPos(NULL,rect.left,rect.top,rect.Width(),rect.Height(),SWP_SHOWWINDOW); GetClientRect(&rect); rect.top+=grid.GetRowSpace(); SetRect(&rect); SetWindowText(cell.GetText()); SetSel(0,-1); SetFocus(); } bool WCellEdit::IsModified() { return GetModify()==TRUE; } void WCellEdit::SetModified(bool bM) { if(bM) CEdit::SetModify(); else CEdit::SetModify(FALSE); } void WCellEdit::SetNewText(const TCHAR*text) { SetWindowText(text); } void WCellEdit::GetNewText(CString&text) { GetWindowText(text); } bool WCellEdit::IsLeftEnd() { int s,e; GetSel(s,e); return e==0; } bool WCellEdit::IsRightEnd() { int s,e; GetSel(s,e); return e==LineLength(); } bool WCellEdit::IsUpEnd() { return true; } bool WCellEdit::IsDownEnd() { return true; } void WCellEdit::PostNcDestroy() { delete this; } void WCellEdit::OnKillFocus(CWnd*pNewWnd) { WDGrid&grid=cell.GetGrid(); if(IsMyFocus(pNewWnd)) return; CEdit::OnKillFocus(pNewWnd); if(!grid.IsMyFocus(pNewWnd)) grid.ShowActive(false); grid.EndEditCell(); } void WCellEdit::OnSetFocus(CWnd*pOldWnd) { WDGrid&grid=cell.GetGrid(); CEdit::OnSetFocus(pOldWnd); grid.ShowActive(); } //////////////////////////////////////////////////////////////////////////////////////// void WCellButton::SetCellEdit(WCellCtrl *pEdit) { pCellEdit=pEdit; } bool WCellButton::Create() { CWnd*pParent=pCellEdit->GetWnd(); CRect rect; pParent->GetClientRect(&rect); if(rect.Height()>rect.Width()) return false; rect.left=rect.Width()-rect.Height(); if(CButton::Create(_T(""),WS_CHILD|WS_VISIBLE|WS_BORDER,rect,pParent,105)) { EnableToolTips(); return true; } return false; } INT_PTR WCellButton::OnToolHitTest(CPoint point,TOOLINFO*pTI)const { CString sTip; WDGridCell &cell=pCellEdit->GetCell(); if(cell.GetGrid().OnCellButtonTip(cell.GetRowIndex(),cell.GetColIndex(),sTip)) { pTI->hwnd = m_hWnd; pTI->uId =(UINT_PTR)m_hWnd; pTI->uFlags |= TTF_IDISHWND|TTF_NOTBUTTON|TTF_ALWAYSTIP|TTF_CENTERTIP; pTI->lpszText=new TCHAR[20]; wsprintf(pTI->lpszText,sTip); return cell.GetRowIndex(); } return -1; } BEGIN_MESSAGE_MAP(WCellButton, CButton) ON_CONTROL_REFLECT(BN_CLICKED, OnBnClicked) END_MESSAGE_MAP() void WCellButton::OnBnClicked() { WDGridCell& cell=pCellEdit->GetCell(); WDGrid&grid=cell.GetGrid(); CString text; pCellEdit->GetNewText(text); if(grid.OnCellButtonDown(cell,text)) { pCellEdit->SetNewText(text); pCellEdit->SetModified(); } Invalidate(); pCellEdit->GetWnd()->SetFocus(); } WCellButtonEdit::WCellButtonEdit(WDGridCell&c):WCellEdit(c) { button.SetCellEdit(this); } void WCellButtonEdit::Create(CRect&rect) { int h=rect.Height(); WCellEdit::Create(rect); if(rect.Width()>h)//防止按钮遮挡 { rect.right-=h; SetRect(&rect); } button.Create(); } ////////////////////////////////////////////////////////////////////////////////////////////// void WCellSpin::SetCellEdit(WCellCtrl*pEdit) { pCellEdit=pEdit; } bool WCellSpin::Create() { CWnd*pParent=pCellEdit->GetWnd(); CRect rect; pParent->GetClientRect(&rect); if(rect.Height()>rect.Width()) return false; rect.left=rect.Width()-rect.Height(); return CSpinButtonCtrl::Create(WS_CHILD|WS_VISIBLE,rect,pParent,105)==TRUE; } WCellSpinEdit::WCellSpinEdit(WDGridCell&c):WCellEdit(c) { spin.SetCellEdit(this); } void WCellSpinEdit::Create(CRect&rect) { int h=rect.Height(); WCellEdit::Create(rect); if(rect.Width()>h)//防止按钮遮挡  { rect.right-=h; SetRect(&rect); } spin.Create(); WDGrid&grid=cell.GetGrid(); spin.SetRange32(0,100000); grid.OnCellSpinInit(cell,spin); int s,e; spin.GetRange32(s,e); int cur=_ttoi(cell); if(cur>=s&&cur<=e) spin.SetPos(cur); else spin.SetPos(s); } BEGIN_MESSAGE_MAP(WCellSpinEdit,WCellEdit) ON_WM_VSCROLL() ON_CONTROL_REFLECT(EN_CHANGE, OnEnChange) END_MESSAGE_MAP() void WCellSpinEdit::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) { WCellEdit::OnVScroll(nSBCode, nPos, pScrollBar); CString temp; temp.Format(_T("%d"),nPos); SetNewText(temp); SetModified(); SetSel(0,-1); } void WCellSpinEdit::OnEnChange() { if(spin.GetSafeHwnd()==NULL) return; CString temp; GetNewText(temp); int cur=_ttoi(temp); int s,e; spin.GetRange32(s,e); if(cur>=s&&cur<=e) spin.SetPos(cur); } ////////////////////////////////////////////////////////////////////////////////////////////// //WCellCombo BEGIN_MESSAGE_MAP(WCellCombo, CComboBox) ON_CONTROL_REFLECT(CBN_KILLFOCUS, OnCbnKillfocus) ON_CONTROL_REFLECT(CBN_SETFOCUS, OnCbnSetfocus) ON_CONTROL_REFLECT(CBN_EDITCHANGE, OnCbnEditchange) ON_CONTROL_REFLECT(CBN_SELCHANGE, OnCbnSelchange) END_MESSAGE_MAP() WCellCombo::WCellCombo(WDGridCell&c,bool bE):WCellCtrl(c),bEditable(bE) { } void WCellCombo::Create(CRect&rect) { WDGrid&grid=cell.GetGrid(); bModified=false; CRect rect1(rect.left-1,rect.top-1,rect.left+rect.Width(),rect.top-1+12*rect.Height()); if(bEditable) CComboBox::Create(WS_VISIBLE|WS_CHILD|WS_VSCROLL|CBS_DROPDOWN,rect1,&grid,101); else CComboBox::Create(WS_VISIBLE|WS_CHILD|WS_VSCROLL|CBS_AUTOHSCROLL|CBS_DROPDOWNLIST,rect1,&grid,101); SetItemHeight(-1,grid.GetRowHeight()-4); grid.OnCellComboString(cell,*this); SetFont(&grid.GetFont()); if(!bEditable) SetCurSel(FindString(-1,cell.GetText())); SetWindowText(cell.GetText()); SetFocus(); } void WCellCombo::GetNewText(CString&text) { GetWindowText(text); } bool WCellCombo::IsModified() { return bModified; } CWnd* WCellCombo::GetWnd() { return this; } bool WCellCombo::IsLeftEnd() { if(!bEditable) return true; DWORD sel=GetEditSel(); return HIWORD(sel)==0; } bool WCellCombo::IsRightEnd() { if(!bEditable) return true; DWORD sel=GetEditSel(); CString s; GetWindowText(s); return HIWORD(sel)==s.GetLength(); } bool WCellCombo::IsUpEnd() { return false; } bool WCellCombo::IsDownEnd() { return false; } void WCellCombo::PostNcDestroy() { delete this; } void WCellCombo::OnCbnKillfocus() { WDGrid&grid=cell.GetGrid(); if(!grid.IsMyFocus(GetFocus())) grid.ShowActive(false); grid.EndEditCell(); } void WCellCombo::OnCbnSetfocus() { cell.GetGrid().ShowActive(); } void WCellCombo::OnCbnEditchange() { bModified=true; } void WCellCombo::OnCbnSelchange() { bModified=true; } /////////////////////////////////////////////////////////////////////////////////////////////// //WDGActiveQuad BEGIN_MESSAGE_MAP(WDGActiveQuad, CWnd) ON_WM_PAINT() ON_WM_LBUTTONDOWN() ON_WM_LBUTTONDBLCLK() ON_WM_RBUTTONUP() END_MESSAGE_MAP() WDGActiveQuad::WDGActiveQuad(WDGrid&g):grid(g),bActive(false) { CWnd::Create(NULL,NULL,WS_VISIBLE|WS_CHILD, CRect(0,0,grid.GetRowHeight(),grid.GetColHeaderHeight()),&grid,102); EnableToolTips(); } INT_PTR WDGActiveQuad::OnToolHitTest(CPoint point,TOOLINFO*pTI)const { CString sTip; if(grid.OnActiveQuadTip(sTip)) { pTI->hwnd = m_hWnd; pTI->uId =(UINT_PTR)m_hWnd; pTI->uFlags |= TTF_IDISHWND|TTF_NOTBUTTON|TTF_ALWAYSTIP|TTF_CENTERTIP; pTI->lpszText=new TCHAR[20]; wsprintf(pTI->lpszText,sTip); return 0; } return -1; } void WDGActiveQuad::OnPaint() { CPaintDC dc(this); CRect rect; GetClientRect(&rect); if(grid.IsFlatButton()) dc.Draw3dRect(&rect,RGB(240,240,240),RGB(80,80,80)); else dc.DrawFrameControl(&rect,DFCS_BUTTON3STATE,0); rect.left+=1; rect.top+=1; rect.right-=2; rect.bottom-=2; dc.FillSolidRect(&rect,GetSysColor(bActive?COLOR_ACTIVECAPTION:COLOR_3DFACE)); } void WDGActiveQuad::OnLButtonDblClk(UINT nFlags,CPoint point) { grid.SetFocus(); bActive=true; Invalidate(); grid.SelectAll(); CWnd::OnLButtonDblClk(nFlags,point); } void WDGActiveQuad::OnRButtonUp(UINT nFlags, CPoint point) { CWnd::OnRButtonUp(nFlags,point); grid.SetFocus(); ClientToScreen(&point); grid.OnRClickQuad(point); } void WDGActiveQuad::OnLButtonDown(UINT nFlags,CPoint point) { grid.SetFocus(); bActive=true; Invalidate(); CWnd::OnLButtonDown(nFlags,point); } ////////////////////////////////////////////////////////////////////////////////////////////// //WColSelector WColSelector::WColSelector(WDGrid&g):grid(g),bDragCol(false),bDragEdge(false) { brush.CreateSolidBrush(GetSysColor(COLOR_3DFACE)); const TCHAR* pszClassName = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_SAVEBITS|CS_DBLCLKS, LoadCursor(NULL,IDC_ARROW),HBRUSH(brush.GetSafeHandle())); CRect rect(0,0,10000,grid.GetColHeaderHeight()); if(grid.IsRowSel()) rect.left=grid.GetRowHeight(); CWnd::Create(pszClassName,NULL,WS_VISIBLE|WS_CHILD,rect,&grid,103); EnableToolTips(); } BEGIN_MESSAGE_MAP(WColSelector, CWnd) ON_WM_PAINT() ON_WM_LBUTTONDOWN() ON_WM_MOUSEMOVE() ON_WM_SETCURSOR() ON_WM_LBUTTONUP() ON_WM_RBUTTONUP() END_MESSAGE_MAP() INT_PTR WColSelector::OnToolHitTest(CPoint point,TOOLINFO*pTI)const { CString sTip; long col=PtToCol(point); if(grid.IsValidCol(col)&&grid.OnColTip(col,sTip)) { pTI->hwnd = m_hWnd; pTI->uId =(UINT_PTR)m_hWnd; pTI->uFlags |= TTF_IDISHWND|TTF_NOTBUTTON|TTF_ALWAYSTIP; pTI->lpszText=new TCHAR[20]; wsprintf(pTI->lpszText,sTip); return col; } return -1; } void WColSelector::OnPaint() { //其坐标系横向与grid重合 CPaintDC dc(this); // device context for painting CPoint pt; grid.GetUpCorner(pt); if(grid.IsRowSel()) dc.SetViewportOrg(pt.x-grid.GetRowHeight(),0);//对齐。 else dc.SetViewportOrg(pt.x,0);//对齐。 long colNum=grid.GetColNum(); for(long i=0;i&selList=grid.colSelList; if(selList.GetLength()==1) { if(selList[0]>col) for(long i=selList[0]-1;i>=col;i--) grid.SelectCol(i); else for(long i=selList[0]+1;i<=col;i++) grid.SelectCol(i); } } else if(bCtrl) grid.SelectCol(col); else { grid.UnSelect(); grid.SelectCol(col); } } } } CWnd::OnLButtonDown(nFlags, point); } void WColSelector::OnRButtonUp(UINT nFlags, CPoint point) { CWnd::OnRButtonUp(nFlags,point); grid.SetFocus(); long col; col=PtToCol(point); if(grid.IsValidCol(col)) { ClientToScreen(&point); if(!grid.IsColSelected(col)) { grid.UnSelect(); grid.SelectCol(col); } grid.OnRClickCol(grid.GetCol(col),point); } } void WColSelector::OnMouseMove(UINT nFlags, CPoint point) { if(bDragEdge||bDragCol) { if(grid.bHScroll) { CRect rect; grid.GetClientRect(&rect); int cx=0; if(grid.GetScrollPos(SB_HORZ)!=grid.GetLeft()) { int col=PtToCol(point); if(grid.IsValidCol(col)) { CPoint pt0(grid.GetCol(col).GetLeft(),0); grid.GetDC().LPtoDP(&pt0); if(pt0.x=rect.right) { grid.MoveView(5,0); grid.UpdateWindow(); return; } else if(point.x<=rect.left+cx) { grid.MoveView(-5,0); grid.UpdateWindow(); return; } } CClientDC dc(this); // device context for painting CPoint pt; grid.GetUpCorner(pt); if(grid.IsRowSel()) dc.SetViewportOrg(pt.x-grid.GetRowHeight(),0);//对齐。 else dc.SetViewportOrg(pt.x,0);//对齐。 CDC&gdc=grid.GetDC(); if(bDragCol) { SetCursor(LoadCursor(NULL,IDC_SIZEWE)); long col=PtToCol(point); if(col>=0&&col<=grid.GetColNum()&&grid.OnMovingCol(col)) { if(col==grid.GetColNum()) point.x=grid.GetRight(); else point.x=grid.GetCol(col).GetLeft(); if(point.x!=oldPoint.x) { if(oldPoint.x!=-1) gdc.InvertRect(CRect(oldPoint.x,0,oldPoint.x+3,10000)); gdc.InvertRect(CRect(point.x,0,point.x+3,10000)); oldPoint=point; } } } else { dc.DPtoLP(&point); gdc.InvertRect(CRect(oldPoint.x,0,oldPoint.x+1,10000)); gdc.InvertRect(CRect(point.x,0,point.x+1,10000)); oldPoint=point; } } CWnd::OnMouseMove(nFlags, point); } BOOL WColSelector::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) { if(!grid.IsColFixWidth()) { CPoint point; GetCursorPos(&point); ScreenToClient(&point); CClientDC dc(this); // device context for painting CPoint pt; grid.GetUpCorner(pt); if(grid.IsRowSel()) dc.SetViewportOrg(pt.x-grid.GetRowHeight(),0);//对齐。 else dc.SetViewportOrg(pt.x,0);//对齐。 dc.DPtoLP(&point); for(long i=0;i&colList=grid.colList; colList.MoveTo(dragColIndex); if(point.x>colList.GetCurData()->GetLeft()+1) { int cx=point.x-colList.GetCurData()->GetRight(); colList.GetCurData()->SetRight(point.x); for(colList.MoveToNext();!colList.IsOut();colList.MoveToNext()) colList.GetCurData()->Move(cx); grid.RecalcLayout(); } bDragEdge=false; } else { long destCol=PtToCol(point); if(destCol>=0&&destCol<=grid.GetColNum()&& grid.OnMoveCol(destCol)) { TDualPtrList&selList=grid.colSelList; long firstCol=selList[0]; long lastCol=selList[selList.GetLastIndex()]; long col; if(destCollastCol+1) { for(col=lastCol;col>=firstCol;col--) grid.MoveCol(col,destCol+col-lastCol); for(selList.MoveToFirst();!selList.IsOut();selList.MoveToNext()) selList.SetCurData(selList.GetCurData()+destCol-lastCol-1); Invalidate(); grid.OnEndMoveCol(); grid.OnDataChanged(); } } bDragCol=false; } oldPoint.x=-1; } grid.SetFocus(); CWnd::OnLButtonUp(nFlags, point); } /////////////////////////////////////////////////////////////////////////////////////////////// //WRowSelector WRowSelector::WRowSelector(WDGrid&g):grid(g),bDragRow(false),oldPoint(0,-1),m_iCurRow(-1) { brush.CreateSolidBrush(GetSysColor(COLOR_3DFACE)); const TCHAR* pszClassName = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_SAVEBITS|CS_DBLCLKS, LoadCursor(NULL,IDC_ARROW),HBRUSH(brush.GetSafeHandle())); CRect rect(0,0,grid.GetRowHeight(),10000); if(grid.IsColSel()) rect.top=grid.GetColHeaderHeight(); CWnd::Create(pszClassName,NULL,WS_VISIBLE|WS_CHILD,rect,&grid,104); EnableToolTips(); } BEGIN_MESSAGE_MAP(WRowSelector, CWnd) ON_WM_PAINT() ON_WM_LBUTTONDOWN() ON_WM_MOUSEMOVE() ON_WM_LBUTTONUP() ON_WM_RBUTTONUP() ON_WM_LBUTTONDBLCLK() END_MESSAGE_MAP() void WRowSelector::OnLButtonDblClk(UINT nFlags,CPoint point) { CWnd::OnLButtonDblClk(nFlags,point); long row=PtToRow(point); if(grid.IsValidRow(row)) grid.OnDblClick(grid.GetRow(row)); } INT_PTR WRowSelector::OnToolHitTest(CPoint point,TOOLINFO*pTI)const { CString sTip; long row=PtToRow(point); if(grid.IsValidRow(row)&&grid.OnRowTip(row,sTip)) { pTI->hwnd = m_hWnd; pTI->uId =(UINT_PTR)m_hWnd; pTI->uFlags |= TTF_IDISHWND|TTF_NOTBUTTON|TTF_ALWAYSTIP|TTF_CENTERTIP; pTI->lpszText=new TCHAR[20]; wsprintf(pTI->lpszText,sTip); return row; } return -1; } void WRowSelector::OnPaint() { CAcModuleResourceOverride vTemp; //其坐标系纵向与grid重合 CPaintDC dc(this); // device context for painting CPoint pt; grid.GetUpCorner(pt); if(grid.IsColSel()) dc.SetViewportOrg(0,pt.y-grid.GetColHeaderHeight());//对齐。 else dc.SetViewportOrg(0,pt.y);//对齐。 int rowHeight=grid.GetRowHeight(); long rowNum=grid.GetRowNum(); for(long i=0;iLoadIcon(IDI_CUR_ROW),rowHeight,rowHeight, NULL,NULL,DI_NORMAL); } if(!grid.IsNoAppendButton()) { CRect rect(0,i*rowHeight,rowHeight,(i+1)*rowHeight); if(grid.IsFlatButton()) dc.Draw3dRect(&rect,RGB(240,240,240),RGB(80,80,80)); else dc.DrawFrameControl(&rect,DFCS_BUTTON3STATE,0); DrawIconEx(dc.GetSafeHdc(),0,i*rowHeight,AfxGetApp()->LoadIcon(IDI_LAST_ROW),rowHeight,rowHeight, NULL,NULL,DI_NORMAL); } } void WRowSelector::OnCurRowChanged() { // add by gjm if (!::IsWindowVisible(grid.GetSafeHwnd())) return; //其坐标系纵向与grid重合 CClientDC dc(this); // device context for painting CPoint pt; grid.GetUpCorner(pt); if(grid.IsColSel()) dc.SetViewportOrg(0,pt.y-grid.GetColHeaderHeight());//对齐。 else dc.SetViewportOrg(0,pt.y);//对齐。 int rowHeight=grid.GetRowHeight(); if(grid.IsValidRow(m_iCurRow)) { long i=m_iCurRow; CRect rect(0,i*rowHeight,rowHeight,(i+1)*rowHeight); if(grid.IsFlatButton()) dc.Draw3dRect(&rect,RGB(240,240,240),RGB(80,80,80)); else dc.DrawFrameControl(&rect,DFCS_BUTTON3STATE,0); } m_iCurRow=grid.GetCurRowIndex(); if(grid.IsValidRow(m_iCurRow)) { long i=m_iCurRow; CRect rect(0,i*rowHeight,rowHeight,(i+1)*rowHeight); if(grid.IsFlatButton()) dc.Draw3dRect(&rect,RGB(240,240,240),RGB(80,80,80)); else dc.DrawFrameControl(&rect,DFCS_BUTTON3STATE,0); DrawIconEx(dc.GetSafeHdc(),0,i*rowHeight,AfxGetApp()->LoadIcon(IDI_CUR_ROW),rowHeight,rowHeight, NULL,NULL,DI_NORMAL); } } void WRowSelector::OnRButtonUp(UINT nFlags, CPoint point) { //CWnd::OnRButtonUp(nFlags,point); grid.SetFocus(); long row=PtToRow(point); if(grid.IsValidRow(row)) { ClientToScreen(&point); if(!grid.IsRowSelected(row)) { grid.UnSelect(); grid.SelectRow(row); } grid.OnRClickRow(grid.GetRow(row),point); } } void WRowSelector::OnLButtonDown(UINT nFlags, CPoint point) { long row=PtToRow(point); if(grid.IsNewRow(row)&&!grid.IsNoAppendButton()) { grid.EndEditCell(); if(grid.GetRowNum()==row) grid.DoAppendRow(false); else grid.ShowAppendRow(); return; } SetFocus(); SetCapture(); if(grid.IsValidRow(row)) { bool bCtrl=!grid.IsSingleSelRow()&&(GetKeyState(VK_CONTROL)&-128)!=0; bool bShift=!grid.IsSingleSelRow()&&(GetKeyState(VK_SHIFT)&-128)!=0; if(grid.IsRowSelected(row)) { if(!bCtrl&&!grid.IsRowPosFix()) { //选择集中树行必须全部折叠、且不包含禁上删除行。 bDragRow=grid.IsSelFold()&&!grid.IsSelDelUnable()&&grid.OnBeginMoveRow(); oldPoint.y=-1; if(bDragRow) rowStart=row; } else if(bCtrl) grid.SelectRow(row,false); } else { if(bShift) { TDualPtrList&selList=grid.rowSelList; if(grid.IsSelConnect()) { if(selList[0]>row) for(long i=selList[0]-1;i>=row;i--) grid.SelectRow(i); else if(selList[selList.GetLastIndex()]=rect.bottom) { grid.MoveView(0,5); grid.UpdateWindow(); return; } else if(point.y<=rect.top+cy) { grid.MoveView(0,-5); grid.UpdateWindow(); return; } } SetCursor(LoadCursor(NULL,IDC_SIZENS)); CClientDC dc(this); // device context for painting CPoint pt; grid.GetUpCorner(pt); if(grid.IsColSel()) dc.SetViewportOrg(0,pt.y-rowHeight);//对齐。 else dc.SetViewportOrg(0,pt.y);//对齐。 long row=PtToRow(point); if(row!=rowStart//目标行与起始行不能相同 &&row>=0&&row<=grid.GetRowNum()&&grid.OnMovingRow(row)) { if(row==grid.GetRowNum()) { if(grid.IsNoAppendButton()) point.y=grid.GetBottom(); else point.y=grid.GetBottom()-grid.GetRowHeight(); } else point.y=grid.GetRow(row).GetTop(); if(point.y!=oldPoint.y) { CDC&gdc=grid.GetDC(); if(oldPoint.y!=-1) gdc.InvertRect(CRect(0,oldPoint.y,10000,oldPoint.y+3)); gdc.InvertRect(CRect(0,point.y,10000,point.y+3)); oldPoint=point; } } } CWnd::OnMouseMove(nFlags, point); } void WRowSelector::OnLButtonUp(UINT nFlags,CPoint point) { ReleaseCapture(); if(bDragRow) { CClientDC dc(this); // device context for painting CPoint pt; grid.GetUpCorner(pt); if(grid.IsColSel()) dc.SetViewportOrg(0,pt.y-grid.GetColHeaderHeight());//对齐。 else dc.SetViewportOrg(0,pt.y);//对齐。 CDC&gdc=grid.GetDC(); if(oldPoint.y!=-1) gdc.InvertRect(CRect(0,oldPoint.y,10000,oldPoint.y+3)); long destRow=PtToRow(point); if(destRow!=rowStart//目标行与起始行不能相同 &&destRow>=0&&destRow<=grid.GetRowNum()&& grid.OnMoveRow(destRow)) { TTable& selList=grid.rowSelList; long count=0; for(selList.MoveToLast();!selList.IsOut();selList.MoveToPre()) if(selList.GetCurData() backup; backup.Conbine(grid.pasteList); grid.ClipSelect(); grid.Paste(destRow-count); grid.pasteList.Conbine(backup); grid.OnEndMoveRow(); grid.OnDataChanged(); } bDragRow=false; oldPoint.y=-1; } grid.SetFocus(); CWnd::OnLButtonUp(nFlags,point); }