#pragma once #include "PDList.h" #include "SHList.h" #include "DualPtrList.h" #include "SHTable.h" #include "WDictItem.h" //表格控件 //WDGrid style #define WDG_READ_ONLY 0x0001//只读 #define WDG_ROW_FIX_LENGTH 0x0002//不能添加、删除行 #define WDG_COL_FIX_LENGTH 0x0004//不能添加、删除列 #define WDG_ROW_UNSEL 0x0008//无行选择区 #define WDG_COL_UNSEL 0x0010//无列选择区 #define WDG_NO_SORT 0x0020//不响应排序操作 #define WDG_COL_FIX_WIDTH 0x0040//不响应调整列宽度操作 #define WDG_COL_POS_FIX 0x0080//不响应移动列操作 #define WDG_ROW_POS_FIX 0x0100//不响应移动行操作 #define WDG_NO_TREE_LINE 0x0200//父行与子行无连线 #define WDG_SINGLE_SEL_ROW 0x0400//行只能单选 #define WDG_NO_PASTE 0x0800//禁止粘贴 #define WDG_LABEL_SORT 0x1000//使用编号排序 #define WDG_FLAT_BUTTON 0x2000//扁平按钮 #define WDG_NO_APPEND_BUTTON 0x4000//有没有AppendRow行 #define WDG_NO_DEFAULT_MENU 0x8000//没有默认菜单 //col style #define WDG_COL_READ_ONLY 0x0001//只读 #define WDG_COL_COMBO_EDIT 0x0002//用下拉表编辑 #define WDG_COL_COMBO_SEL 0x0004//用下拉表选择 #define WDG_COL_BUTTON_EDIT 0x0008//带右按钮编辑 #define WDG_COL_SPIN_EDIT 0x0010//带右spin编辑 #define WDG_COL_CENTER_ALIGN 0x0020//中心对齐 //row style #define WDG_ROW_READ_ONLY 0x0001//只读 #define WDG_ROW_DEL_UNABLE 0x0002//禁止删除,如选择集中有一个此类型行,整个选择集将无法移动 #define WDG_ROW_UNFOLD 0x0010//展开的父行 //cell style #define WDG_CELL_READ_ONLY 0x0001//只读单元格 //菜单ID #define ID_WDGRID_INS_ROW 1 #define ID_WDGRID_DEL_ROW 2 #define ID_WDGRID_ADD_ROW 3 #define ID_WDGRID_SELECT_ALL 4 #define ID_WDGRID_COPY_ROW 5 #define ID_WDGRID_CUT_ROW 6 #define ID_WDGRID_PASTE_ROW 7 #define ID_WDGRID_INS_COL 8 #define ID_WDGRID_DEL_COL 9 #define ID_WDGRID_ADD_COL 10 #define ID_WDGRID_ARRANGE 11 #define ID_WDGRID_REVERSE 12 #define WDGRID_MENU_ID_USER_FIRST 100 class WDGridRow; class WDGridCol; class WDGridCell; class WColSelector; class WRowSelector; class WDGActiveQuad; class WCellCtrl; class WCellEdit; class WCellCombo; class WRowData; class WDGrid : public CWnd {//表格控件 friend class WDGridRow; friend class WDGridTreeRow; friend class WDGridCol; friend class WDGridCell; friend class WColSelector; friend class WRowSelector; friend class WDGActiveQuad; friend class WCellCtrl; friend class WCellEdit; friend class WCellCombo; friend class WCellButtonEdit; friend class WCellSpinEdit; friend class WCellButton; friend class WCellSpin; DECLARE_DYNAMIC(WDGrid) protected: bool bTreeGrid;//是否支持树 int style;//属性 PDList colList;//列链 PDList rowList;//数据行链 PDList pasteList;//粘贴链 SHListkeyList;//鍵链,存储列索引,排序用 DualPtrList rowSelList,colSelList;//当前选定行、列索引链 WDGridCell *pSelCell;//当前编辑单元格 WDGridCell *pSelCell2;//下一个需要编辑单元格 long defaultWidth;//默认列宽度,不设置列宽列将使用它 long rowHeight;//内部行高=文字高度+1(行下距)。 int rowSpace;//行上距 CFont font;//字体 CBrush brush;//背景刷 CPen pen;//分界线画笔 CDC *pDC;//全局CDC对象,窗口创建后内部自动维护,保持始终有效 WDGActiveQuad*pActiveQuad;//焦点指示器 WRowSelector*pRowSelector;//列操作器 WColSelector*pColSelector;//行操作器 WCellCtrl *pCurEdit;//当前的单元格编辑器 bool bVScroll,bHScroll;//是否有滚动条。 WDGridRow* m_pAppendRow;//最后增加新行 long m_iCurRow,m_iCurCol;//当前行 bool m_bModified;//是否已经修改 protected: bool IsTreeGrid()const{return bTreeGrid;} void SendParentNotify(WORD wNotify)const;//向窗口发送通知消息 bool IsValidWnd()const{return GetSafeHwnd()!=NULL;}//windows窗口是否已创建 CDC& GetDC(){return *pDC;}//得到当前全局CDC CBrush& GetBrush(){return brush;} void CreateFont(); void PrepareDC(CDC*pD=NULL); void ClearDC(){if(pDC!=NULL)delete pDC;pDC=NULL;} long GetColHeaderHeight();//行操作器高度 void GetUpCorner(CPoint&pt);//逻辑坐标系原点的设备坐标系坐标,左上边界线的交点 long GetLeft(){return 0;}//左边界线 long GetTop(){return 0;}//上边界线 long GetRight();//右边界线 long GetBottom(){return GetTop()+GetRowNum()*GetRowHeight()+(IsNoAppendButton()?0:GetRowHeight());}//下边界线 //逻辑坐标系中的数据区 void GetRect(CRect&rect){rect.left=GetLeft();rect.top=GetTop();rect.bottom=GetBottom();rect.right=GetRight();} void GetClientRect(LPRECT lpRect);//数据区,客户区除去行列操作器 void PtToCell(CPoint pt,long&row,long&col);//设备坐标系 void ShowRect(CRect rect);//设备坐标系 void ClearSel(){rowSelList.Clear();colSelList.Clear();} void FilterDelUnable();//将不能删除行从选择集中去除 bool IsSelDelUnable();//是否选择集中有不可删除行 void ClipSelect(); void Paste(long i); void RefreshAppendRow(); protected: DECLARE_MESSAGE_MAP() virtual BOOL PreTranslateMessage(MSG* pMsg); virtual INT_PTR OnToolHitTest(CPoint point,TOOLINFO*pTI)const; afx_msg LRESULT OnSetFont(WPARAM wParam, LPARAM lParam); afx_msg LRESULT OnSetText(WPARAM wParam, LPARAM lParam); afx_msg UINT OnGetDlgCode(void); afx_msg void OnCancelMode(void); afx_msg void OnSize(UINT nType, int cx, int cy); afx_msg void OnPaint(); afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt); afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor); afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point); afx_msg void OnLButtonDown(UINT nFlags, CPoint point); afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); afx_msg void OnKillFocus(CWnd*pNewWnd); afx_msg void OnSetFocus(CWnd*pOldWnd); afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message); afx_msg BOOL OnEraseBkgnd(CDC* pDC); afx_msg void OnRButtonUp(UINT nFlags, CPoint point); afx_msg void OnTimer(UINT_PTR nIDEvent); protected: //左键事件 virtual void OnDblClick(WDGridRow&row){}//ok //右键事件 virtual void OnRClickCell(WDGridCell&cell,CPoint point){}//ok virtual void OnRClickRow(WDGridRow&row,CPoint point);//ok virtual void OnRClickCol(WDGridCol&col,CPoint pt);//ok virtual void OnRClickQuad(CPoint pt);//ok //编辑事件 virtual bool OnBeforeEdit(WDGridCell&cell,bool &bModified){return true;}//返回值代表是否继续编辑,如果在这个函数中修改了bModified设为true; virtual WCellCtrl* OnGetCellEdit(WDGridCell&cell);//准备嵌入式单元编辑器 virtual void OnCellComboString(WDGridCell&cell,CComboBox&combo){}//准备下拉列表内容 virtual bool OnCellButtonDown(WDGridCell&cell,CString&res){return false;}//单元格按钮按下响应,返回值代表是否确定,res初始为编辑器内当前内容 virtual void OnCellSpinInit(WDGridCell&cell,CSpinButtonCtrl&spin){}//初始化Spin virtual bool OnModified(WDGridCell&cell,CString &text){return true;}//单元内容将改变为text,返回值代表是否确定 virtual void OnDataChanged(){m_bModified=true;SendParentNotify(EN_CHANGE);}//内容改变,支持行列数变化、单元格内容变化 virtual void OnCurChanged();//当前行列变化,子类一定要调整用基类 //刷新事件 virtual void OnBeforeRefresh(WDGridCell&cell);//可以修改普通刷新时的文字着色 virtual bool OnRefresh(WDGridRow&row){return true;}//是否继续普通刷新 virtual bool OnRefresh(WDGridCell&cell){return true;}//是否继续普通刷新 //列事件 virtual bool OnBeforeInsertCol(long i,WDGridCol*&pNewCol){return true;}//将插入一列,返回值代表是否确定 virtual void OnInsertCol(WDGridCol&col){OnDataChanged();}//插入一列 virtual bool OnBeforeDeleteCol(){return true;}//返回值代表是否确定 virtual void OnEndDeleteCol(){}//删除列结束 virtual bool OnBeginMoveCol(){return true;}//返回值代表是否确定 virtual bool OnMovingCol(long i){return true;}//移动过程,返回值代表是否可以移动到此处 virtual bool OnMoveCol(long i){return OnMovingCol(i);}//返回值代表是否确定 virtual void OnEndMoveCol(){}//移动列结束 //行事件 virtual bool OnBeforeInsertRow(long i,WDGridRow*&pNewRow){return true;}//将插入一行 virtual bool OnBeforeInsertChild(WDGridTreeRow&row,long iChild,WDGridTreeRow*&pChild){return true;}//将插入一子行 virtual void OnInsertRow(WDGridRow&row){OnDataChanged();}//新插入一行 virtual bool OnBeforeDeleteRow(){return true;}//返回值代表是否确定  virtual void OnEndDeleteRow(){}//删除行结束 virtual bool OnBeforeClip(){return true;}//返回值代表是否确定 virtual void OnEndClip(){}//剪切结束 virtual bool OnBeforeCopy(){return true;}//返回值代表是否确定 virtual void OnEndCopy(){}//复制结束 virtual bool OnBeforePaste(long i){return true;}//返回值代表是否确定 virtual bool OnBeforePasteChild(WDGridTreeRow&row){return true;}//返回值代表是否确定 virtual void OnEndPaste(){}//粘贴结束,include paste child virtual bool OnBeginMoveRow(){return true;}//返回值代表是否确定 virtual bool OnMovingRow(long i){return true;}//移动过程,返回值代表是否可以移动到此处 virtual bool OnMoveRow(long i){return OnMovingRow(i);}//返回值代表是否确定 virtual void OnEndMoveRow(){}//移动行结束 //ToolTips virtual bool OnCellTip(long row,long col,CString&res)const{return false;} virtual bool OnRowTip(long row,CString&res)const{return false;} virtual bool OnColTip(long col,CString&res)const{return false;} virtual bool OnCellButtonTip(long row,long col,CString&res)const{return false;}//准备单元格按钮ToolTip virtual bool OnActiveQuadTip(CString&res)const{return false;} public: //contruct/distruct WDGrid(bool bTree=false,long colWidth=100); virtual ~WDGrid(); BOOL Create(const RECT& rect,DWORD wStyle=WS_VISIBLE|WS_CHILD|WS_BORDER|WS_CLIPCHILDREN | WS_CLIPSIBLINGS|WS_HSCROLL|WS_VSCROLL,CWnd* pParentWnd=NULL); BOOL Create(CWnd *pParent,UINT ID,DWORD wStyle=WS_VISIBLE|WS_TABSTOP|WS_CHILD|WS_BORDER|WS_CLIPCHILDREN | WS_CLIPSIBLINGS); //attribute int GetStyle(){return style;}//ok void SetStyle(int s){style|=s;}//ok void SetDefaultWidth(long w){defaultWidth=w;}//ok long GetDefaultWidth(){return defaultWidth;}//ok void SetReadOnly(bool bRO=true); void SetRowFixLength(bool bRFL=true); void SetColFixLength(bool bCFL=true); void SetRowSel(bool bRS=true); void SetColSel(bool bCS=true); void SetSortEnable(bool bSE=true); void SetColFixWidth(bool bCFW=true); void SetColPosFix(bool bCPF=true); void SetRowPosFix(bool bRPF=true); void SetTreeLine(bool bTL=true); void SetSingleSelRow(bool bSS=true); void SetNoPaste(bool bNP=true); void SetLabelSort(bool bLS=true); void SetFlatButton(bool bFB=true); void SetNoAppendButton(bool bNAB=true); void SetNoDefaultMenu(bool bNDM=true); bool IsColSel(){return (style&WDG_COL_UNSEL)==0;}//ok bool IsRowSel(){return (style&WDG_ROW_UNSEL)==0;}//ok bool IsColFixWidth(){return (style&WDG_COL_FIX_WIDTH)!=0;}//ok bool IsNeedTreeLine(){return (style&WDG_NO_TREE_LINE)==0;}//ok bool IsReadOnly(){return (style&WDG_READ_ONLY)!=0;}//ok bool IsRowFixLength(){return (style&WDG_ROW_FIX_LENGTH)!=0||IsReadOnly();}//ok bool IsColFixLength(){return (style&WDG_COL_FIX_LENGTH)!=0||IsReadOnly();}//ok bool IsColPosFix(){return (style&WDG_COL_POS_FIX)!=0||IsReadOnly();}//ok bool IsRowPosFix(){return (style&WDG_ROW_POS_FIX)!=0||IsReadOnly();}//ok bool IsSortEnable(){return (style&WDG_NO_SORT)==0&&!IsRowPosFix();}//ok bool IsSingleSelRow(){return (style&WDG_SINGLE_SEL_ROW)!=0;}//ok bool IsNoPaste(){return (style&WDG_NO_PASTE)!=0;}//ok bool IsLabelSort(){return (style&WDG_LABEL_SORT)!=0;}//ok bool IsFlatButton(){return (style&WDG_FLAT_BUTTON)!=0;}//ok bool IsNoAppendButton(){return (style&WDG_NO_APPEND_BUTTON)!=0||IsRowFixLength();}//ok bool IsNoDefaultMenu(){return (style&WDG_NO_DEFAULT_MENU)!=0;}//ok //row void Clear(); bool IsValidRow(long i)const{return rowList.IsValidIndex(i);}//ok bool IsNewRow(long i)const{return i==rowList.GetLength();}//ok bool IsEmpty()const{return rowList.IsEmpty();}//ok void AppendRow(WDGridRow*pR=NULL); void InsertRow(long i,WDGridRow*pR=NULL);//树行慎用! void DelRow(long i);//不支持删除展开父行! void DelRowEx(long i);//支持删除展开父行 void MoveRow(long from,long to);//树行慎用! void SetRowNum(long n);//TreeGrid慎用 long GetRowNum()const{return rowList.GetLength();}//行数(不计被折叠子行) long GetCurRowIndex(){return m_iCurRow;}//当前唯一选定行或当前编辑行,初始为-1,可能无效 void SetCurRowIndex(long iRow);//强制改变当前行 void MoveToFirst(){rowList.MoveToFirst();}//ok void MoveToNext(){rowList.MoveToNext();}//ok void MoveToPre(){rowList.MoveToPre();}//ok void MoveTo(long i){rowList.MoveTo(i);}//ok bool IsOut(){return rowList.IsOut();}//ok WDGridRow* CurRow(){return rowList.GetCurData();}//ok WDGridTreeRow* CurTreeRow(){return (WDGridTreeRow*)CurRow();}//ok long GetCur(){return rowList.GetCur();}//ok WDGridRow& GetRow(long row){return *rowList[row];}//ok WDGridRow& operator[](long row){return GetRow(row);}//ok WDGridTreeRow& GetTreeRow(long row){return (WDGridTreeRow&)GetRow(row);}//ok //col WDGridCol& GetCol(long i){return *colList[i];}//ok bool IsColEmpty()const{return colList.IsEmpty();}//ok bool IsValidCol(long i)const{return colList.IsValidIndex(i);}//ok void SetColNum(long n); long GetColNum()const{return colList.GetLength();}//ok void InsertCol(long i,WDGridCol*pCol=NULL,long width=0); void InsertCol(long i,const TCHAR*name,long width=0); void AppendCol(WDGridCol*pCol=NULL,long width=0); void AppendCol(const TCHAR*name,long width=0); void DelCol(long i); void MoveCol(long from,long to); long GetCurColIndex(){return m_iCurCol;}///当前唯一选定列或当前编辑列,初始为-1,可能无效 //cell WDGridCell &GetCell(long row,long col); bool GetCurCell(long&row,long&col)const; void BeginEditCell(long i,long j); void EndEditCell(); void CancelEditCell(); void AutoEditCell(WDGridCell*pCell=NULL);//自动编辑和编辑锁定,pCell为NULL则锁定pSelCell void AutoCloseCell(int iTime=0); bool IsEditing()const{return pSelCell!=NULL;}//ok bool IsCellLocking()const{return pSelCell2!=NULL;}//ok //draw void Invalidate(BOOL bErase=TRUE);//更新显示 void Refresh();//执行显示 void RecalcLayout(BOOL bRedraw = TRUE);//更新布局 bool FitLastCol();//如果总列宽小于窗口宽度,调整最后一行宽度使之恰好充满窗口 void MoveView(int cx,int cy);//新设备原点相对旧设备原点的偏移 long GetRowSpace(){return rowSpace;}//ok,行上距 void SetRowSpace(int space=3){rowSpace=space;RecalcLayout();}//ok CFont& GetFont(){return font;}//ok long GetRowHeight(){return rowHeight+rowSpace;}//ok,字高+行上距 void ShowAppendRow(); //select void SelectRow(long i,bool bSel=true); void SelectCol(long i,bool bSel=true); void SelectAll(); void UnSelect(); bool IsColSelected(){return !colSelList.IsEmpty();}//ok bool IsRowSelected(){return !rowSelList.IsEmpty();}//ok bool IsColSelected(long col){return colSelList.Find(col)!=NOT_FOUND;}//ok bool IsRowSelected(long row){return rowSelList.Find(row)!=NOT_FOUND;}//ok long GetRowSelNum(){return rowSelList.GetLength();}//ok long GetColSelNum(){return colSelList.GetLength();}//ok WDGridRow& GetSelRow(long i){return GetRow(rowSelList[i]);}//ok WDGridCol& GetSelCol(long i){return GetCol(colSelList[i]);}//ok void GetSel(SHTable&table);//当前行选择集 void GetSel(SHTable&table);//当前列选择集 bool IsSelConnect();//选择集是否连续 bool IsSelFold();//选择集内的树行是否全部折叠 bool FindAndSel(const TCHAR*s,long iCol);//比较第iCol列,找行并选出 //arrange long GetMainKey(){return keyList.IsEmpty()?-1:keyList[0];}//ok void AppendKey(long i){keyList.AddTail(i);}//ok void ClearKey(){keyList.Clear();}//ok void Arrange(bool bIncrease=true); //command bool DoInsertCol(); bool DoAppendCol(); bool DoInsertColAfter(); bool DoInsertRow(); bool DoInsertRowAfter(); bool DoInsertTree(); bool DoInsertTreeAfter(); bool DoAppendRow(bool bSel=true); bool DoAppendTree(); bool DoAppendChild(); bool DoDelete(); bool DoClip(); bool DoCopy(); bool DoPaste(); bool DoPasteChild(); //other PDList& GetRowPaste(){return pasteList;}//ok,当前粘贴板内容 void ShowActive(bool bActive=true);//显示是否拥有输入焦点 bool IsMyFocus(const CWnd*pNewWnd)const;//判断当前焦点 bool IsModified()const{return m_bModified;} void SetModify(bool bTrue){m_bModified=bTrue;} }; class WDGridCol { friend class WDGrid; friend class WDGridRow; friend class WDGridCell; friend class WColSelector; friend class WRowSelector; protected: long index;//索引 int style;//属性 TString name;//列名 long left;//左分界线 long right;//右分界线 COLORREF backColor,textColor;//字体和背景色 CBrush brush;//背景刷 WDGrid& grid;//所属数据表格 protected: void SetIndex(long i){index=i;} void Move(long cx){left+=cx;right+=cx;} void SetLeft(long l){left=l;} void SetRight(long r){right=r;} long GetLeft(){return left;} long GetTop(){return grid.GetTop();} long GetRight(){return right;} long GetBottom(){return grid.GetBottom();} void GetRect(CRect &rect) {rect.left=GetLeft();rect.top=GetTop();rect.right=GetRight();rect.bottom=GetBottom();} CBrush& GetBrush(){return brush;}//only for OnCtlColor void Select(bool bSel=true);//翻转颜色 public: //contruct/distruct WDGridCol(const TCHAR*n,WDGrid& parent); virtual ~WDGridCol(){}//ok //attribute bool IsReadOnly(){return (style&WDG_COL_READ_ONLY)!=0||grid.IsReadOnly();}//ok bool IsComboEdit(){return (style&WDG_COL_COMBO_EDIT)!=0;}//ok bool IsComboSel(){return (style&WDG_COL_COMBO_SEL)!=0;}//ok bool IsRightButton(){return (style&WDG_COL_BUTTON_EDIT)!=0;}//ok bool IsRightSpin(){return (style&WDG_COL_SPIN_EDIT)!=0;}//ok bool IsCenterAlign(){return (style&WDG_COL_CENTER_ALIGN)!=0;}//ok void SetReadOnly(bool bRO=true); void SetComboEdit(bool bCE=true); void SetComboSel(bool bCS=true); void SetRightButton(bool bRB=true); void SetRightSpin(bool bRS=true); void SetCenterAlign(bool CA=true); long GetIndex(){return index;}//ok const TCHAR * GetName(){return name;}//ok void SetName(const TCHAR*n){name=n;}//ok long GetWidth(){return right-left;}//ok int GetStyle(){return style;}//ok void SetStyle(int s){style|=s;}//ok COLORREF GetTextColor(){return textColor;}//ok COLORREF GetBackColor(){return backColor;}//ok void SetTextColor(COLORREF color){textColor=color;}//ok void SetBackColor(COLORREF color){backColor=color;brush.DeleteObject();brush.CreateSolidBrush(color);}//ok //compare bool operator>(WDGridCol&col){return index>col.GetIndex();}//ok bool operator<(WDGridCol&col){return index cellList;//单元格链 WDGrid& grid; protected: virtual void InsertCol(long i,WDGridCol&col); virtual void AppendCol(WDGridCol&col); virtual void DelCol(long i){cellList.Del(i);} virtual void MoveCol(long from,long to){cellList.Move(from,to);} int GetStyle(){return style;} void SetIndex(long id){index=id;} long GetLeft(){return grid.GetLeft();} long GetTop(){return grid.GetTop()+index*grid.GetRowHeight();} long GetRight(){return grid.GetRight();} long GetBottom(){return grid.GetTop()+(index+1)*grid.GetRowHeight();} void GetRect(CRect &rect) {rect.left=GetLeft();rect.top=GetTop();rect.right=GetRight();rect.bottom=GetBottom();} void Select(bool bSel=true);//颜色翻转,参数无用 public: //construct/distruct WDGridRow(WDGrid&grid); WDGridRow& operator=(WDGridRow&row);//exclude index virtual ~WDGridRow();//ok //attribute virtual bool IsParentRow(){return false;}//ok virtual bool IsChildRow(){return false;}//ok virtual bool IsTreeRow(){return false;}//ok long GetIndex(){return index;}//ok bool IsReadOnly(){return (style&WDG_ROW_READ_ONLY)!=0||grid.IsReadOnly();}//ok bool IsDelUnable(){return (style&WDG_ROW_DEL_UNABLE)!=0||IsReadOnly();}//ok void SetReadOnly(bool bRO=true); void SetDelUnable(bool bDU=true); void SetExtendData(WRowData*p); WRowData* GetExtendData(){return pData;}//ok //cell WDGridCell&operator[](long col){return *cellList[col];}//ok //draw virtual void Refresh();//对所有Cell调用Refresh(); //compare bool operator>(WDGridRow&row); bool operator<(WDGridRow&row); }; class WDGridTreeRow:public WDGridRow { friend class WDGrid; friend class WDGridCell; protected: PDList childRow; WDGridTreeRow*pParent; protected: virtual void InsertCol(long i,WDGridCol&col); virtual void AppendCol(WDGridCol&col); virtual void DelCol(long i); virtual void MoveCol(long from,long to); long GetGlobalChildIndex(long i);//取第i个子行的grid index long GetChildIndex(WDGridTreeRow*pRow); void GetTreeQuad(CRect&rect); bool IsPtInTreeQuad(CPoint&pt){CRect rect;GetTreeQuad(rect);return rect.PtInRect(pt)==TRUE;}//ok public: //construct/distruct WDGridTreeRow(WDGrid&grid); WDGridTreeRow(WDGridTreeRow*parent); WDGridTreeRow&operator=(WDGridTreeRow&row); void operator<<(WDGridTreeRow&row);//除了拷贝,还取下扩展数据. virtual ~WDGridTreeRow(){}//ok //attribute virtual bool IsParentRow(){return !childRow.IsEmpty();}//ok virtual bool IsChildRow(){return pParent!=NULL;}//ok virtual bool IsTreeRow(){return true;}//ok bool IsRootRow(){return !IsChildRow();}//ok bool IsFold(){return (style&WDG_ROW_UNFOLD)==0;}//ok void SetUnFoldFlag(bool bUF=true); void SetParent(WDGridTreeRow*p){pParent=p;}//ok WDGridTreeRow& GetParent(){return *pParent;}//ok WDGridTreeRow* Parent(){return pParent;}//ok WDGridTreeRow* RootRow(); bool IsVisible(){return index!=-1;}//ok,是否已经插入到grid bool IsChildVisible(){return GetChild(0).IsVisible();}//ok long GetParentNum();//父行数 long GetChildNum(){return childRow.GetLength();}//ok,直接子行数 long GetOffspringNum();//后代总数 long GetRowNum();//实际占用的行数(包括自身),不考虑是否自身已经插入grid void MoveToFirst(){childRow.MoveToFirst();}//ok void MoveToNext(){childRow.MoveToNext();}//ok void MoveToPre(){childRow.MoveToPre();}//ok bool IsOut(){return childRow.IsOut();}//ok WDGridTreeRow* CurChild(){return childRow.GetCurData();}//ok WDGridTreeRow& GetChild(long i){return *childRow[i];}//ok WDGridTreeRow& GetLastChild(){childRow.MoveToLast();return *childRow.GetCurData();}//ok //child row void InsertChild(long i,WDGridTreeRow*pRow=NULL); void AppendChild(WDGridTreeRow*pRow=NULL){InsertChild(GetChildNum(),pRow);}//ok void DelChild(long i); void ClearChild(); //operator void Fold(); void UnFold(); void FoldAll(); void UnFoldAll(); void ArrangeChild(bool bIncrease=true); bool FindAndSel(const TCHAR*sId,long iCol); }; class WDGridCell { friend class WDGridRow; friend class WDGridTreeRow; friend class WDGridCol; friend class WDGrid; friend class WColSelector; friend class WRowSelector; protected: TString text;//数据 int style;//特性 WDGridRow&row;//所属行 WDGridCol&col;//所属列 WDGrid&grid;//所属表格 public: //contruct/distruct WDGridCell(WDGrid&g,WDGridRow&r,WDGridCol&c); WDGridCell&operator=(WDGridCell&cell);//all data virtual ~WDGridCell(){} //attribute bool IsReadOnly(){return (style&WDG_CELL_READ_ONLY)!=0||col.IsReadOnly()||row.IsReadOnly()||grid.IsReadOnly();}//ok void SetReadOnly(bool bRO=true); //data void SetText(const TCHAR* s){text=s;}//ok TString& GetText(){return text;}//ok operator const TCHAR*(){return text;}//ok operator double(){return text;}//ok operator int(){return text;}//ok WDGridRow& GetRow(){return row;}//ok WDGridCol& GetCol(){return col;}//ok WDGrid& GetGrid(){return grid;}//ok long GetRowIndex(){return row.GetIndex();}//ok long GetColIndex(){return col.GetIndex();}//ok //draw void Select(bool bSel=true);//bSel参数实际无用 void Refresh(); void GetRect(CRect &rect)//ok,包含分界线 {rect.left=col.GetLeft();rect.top=row.GetTop();rect.right=col.GetRight();rect.bottom=row.GetBottom();} void GetTextRect(CRect&rect)//ok,不包含分界线 {rect.left=col.GetLeft()+1;rect.top=row.GetTop()+1;rect.right=col.GetRight();rect.bottom=row.GetBottom();} //compare bool operator>(WDGridCell&cell){return text>cell.GetText();}//ok bool operator<(WDGridCell&cell){return textGetRowIndex(); col=pSelCell->GetColIndex(); return TRUE; } //数据区(除去行列选择器)的客户区设置坐标系表示 inline void WDGrid::GetClientRect(LPRECT lpRect)//ok { CWnd::GetClientRect(lpRect); if(IsRowSel()) lpRect->left+=GetRowHeight(); if(IsColSel()) lpRect->top+=GetColHeaderHeight(); } //数据区的左上角,逻辑坐标系原点在设备坐标系的表示 inline void WDGrid::GetUpCorner(CPoint&pt) { int x=bHScroll?GetScrollPos(SB_HORZ):0; int y=bVScroll?GetScrollPos(SB_VERT):0; CRect rect; GetClientRect(&rect); pt.x=-x+rect.left; pt.y=-y+rect.top; } inline void WDGrid::SendParentNotify(WORD wNotify)const { UINT id=GetDlgCtrlID(); if(GetParent()!=NULL) GetParent()->SendMessage(WM_COMMAND,MAKEWPARAM(id,wNotify),(LPARAM)GetSafeHwnd()); } inline WDGridCell& WDGrid::GetCell(long row,long col){return GetRow(row)[col];}//ok //pt为设备坐标系 inline long WColSelector::PtToCol(CPoint pt)const { long row,col; if(grid.IsRowSel()) pt.x+=grid.GetRowHeight(); grid.PtToCell(pt,row,col); return col; } //pt为设备坐标系 inline long WRowSelector::PtToRow(CPoint pt)const { long row,col; if(grid.IsColSel()) pt.y+=grid.GetColHeaderHeight(); grid.PtToCell(pt,row,col); return row; } inline void WDGrid::ShowActive(bool bActive)//ok { if(pActiveQuad!=NULL) pActiveQuad->ShowActive(bActive); } inline long WDGrid::GetRight() { if(colList.IsEmpty()) return GetLeft(); colList.MoveToLast(); return colList.GetCurData()->GetRight(); } class DictRowData : public WRowData { public: int nType; DualPtrList lstStr; }; class DictGrid : public WDGrid { public: DictGrid(); void SetModified(bool bModified = false); bool IsModified(); void DictToGrid(WDict *pDict); void GridToDict(WDict *pDict); virtual void OnCellComboString(WDGridCell&cell, CComboBox&combo); virtual bool OnBeforeEdit(WDGridCell&cell, bool &bModified); virtual bool OnModified(WDGridCell&cell, CString &text); virtual bool OnBeforeInsertChild(WDGridTreeRow&row, long iChild, WDGridTreeRow*&pChild);//将插入一子行 virtual void OnInsertRow(WDGridRow&row); // add by xly on 110408 截获鼠标滚轴 BOOL PreTranslateMessage(MSG* pMsg); protected: bool m_bModified; int GetTypeIndex(CString szType); void DictToTreeRow(WDict *pDict, WDGridTreeRow *pRow); void DictToRow(WDict *pDict, WDGridTreeRow *pRow); void TreeRowToDict(WDGridTreeRow &row, WDict *pDict); void RowToDict(WDGridTreeRow &row, WDict *pDict); };