| 注册
请输入搜索内容

热门搜索

Java Linux MySQL PHP JavaScript Hibernate jQuery Nginx
yushang
9年前发布

一个基于WTL的电子表格控件

#ifndef _DBUFF_VEW_H   #define _DBUFF_VEW_H     #include <atlbase.h>   #include <atlstr.h>   #include <atlapp.h>   #include <atlframe.h>   #include <atlctrls.h>   #include <atlgdix.h>   #include <atlcoll.h>   #include <atlcrack.h>   #include <atlctrlw.h>   #define _WTL_NO_CSTRING   #include <atlmisc.h>   #include <iostream>   #include <array>   #include "resource.h"     using namespace std;   extern HINSTANCE g_hInstance;     #define DRG_NONE 0   #define DRG_COL_MOVE 1   #define DRG_COL_SIZE 2   #define SIZE_POINT 3     typedef CWinTraitsOR<WS_HSCROLL|WS_VSCROLL,WS_EX_CLIENTEDGE,CControlWinTraits> DBuffViewTraits;   class CGridView : public CDoubleBufferWindowImpl<CGridView,CWindow,DBuffViewTraits>   {   public:   DECLARE_WND_CLASS_EX(_T("CGridView"),0,COLOR_BTNFACE)   typedef CDoubleBufferWindowImpl<CGridView,CWindow,DBuffViewTraits> _baseClass;     BEGIN_MSG_MAP(CGridView)   MSG_WM_HSCROLL(OnHScroll)   MSG_WM_VSCROLL(OnVScroll)   MSG_WM_CREATE(OnCreate)   MSG_WM_MOUSEMOVE(OnMouseMove)   MSG_WM_MOUSEWHEEL(OnMouseWheel)   MSG_WM_LBUTTONDOWN(OnLButtonDown)   MSG_WM_LBUTTONUP(OnLButtonUp)   CHAIN_MSG_MAP(_baseClass)   END_MSG_MAP()     struct COLINFO   {   int Idx;   int Width;   BYTE HorzAlg;   int ColIdx;   };   //   void ColAt(int x, int &Col , int &Start , int &End)   {   int Off = m_IndWidth;   for (int i = m_StartCol ; i < m_Cols.size() ; i++)   {   Off += m_Cols[i].Width;   if ( x <= Off )   {   Start = Off - m_Cols[i].Width;   End = Off;   Col = i;   return;   }   }   }   //   void OnLButtonDown(UINT nFlags, CPoint point)   {   if ( point.x > m_IndWidth && point.y < m_HeaderHeight && ::DragDetect(m_hWnd,point) )   {   ColAt(point.x, m_DragCol, m_DragStart, m_DragEnd);   SetCapture();   if ( point.x > m_DragEnd - SIZE_POINT )   {   SetCursor(LoadCursor(g_hInstance,MAKEINTRESOURCE(WTLDEMO_SIZE)));   m_DragType = DRG_COL_SIZE;   }   else   {   SetCursor(LoadCursor(g_hInstance,MAKEINTRESOURCE(WTLDEMO_DRAG)));   m_DragType = DRG_COL_MOVE;   }   }   }   //   void OnLButtonUp(UINT nFlags, CPoint point)   {   if ( point.x < 0 || point.y < 0 )   goto ret;     if ( m_DragType == DRG_COL_MOVE )   {   int DropCol;   int Dummy;   ColAt(point.x, DropCol, Dummy, Dummy);     COLINFO tmp = m_Cols[m_DragCol];     if ( DropCol == m_DragCol ) goto ret;     if ( DropCol < m_DragCol )   {   for (int i = m_DragCol ; i < m_Cols.size()-1; i++)   m_Cols[i] = m_Cols[i+1];     for (int i = m_Cols.size() -1 ; i > DropCol  ; i--)   m_Cols[i] = m_Cols[i-1];   m_Cols[DropCol] = tmp;   }   else   {   for (int i = m_DragCol ; i < DropCol; i++)   m_Cols[i] = m_Cols[i+1];   m_Cols[DropCol] = tmp;   }     }     if ( m_DragType == DRG_COL_SIZE )   {   m_Cols[m_DragCol].Width = max(m_DragRc.right - m_DragRc.left,3);   }   ret:   SetCursor(LoadCursor(NULL,IDC_ARROW));   ReleaseCapture();   m_DragType = DRG_NONE;   Invalidate();   }   //   void OnMouseMove(UINT nFlags, CPoint point)   {   if (m_DragType == DRG_COL_MOVE )   {   int Width = m_Cols[m_DragCol].Width;   m_DragRc.left = point.x-Width/2;   m_DragRc.top = point.y- m_HeaderHeight/2;   m_DragRc.right = point.x+Width/2;   m_DragRc.bottom = point.y+m_HeaderHeight/2;   Invalidate();   return;   }     if ( m_DragType == DRG_COL_SIZE )   {   m_DragRc.left = m_DragStart;   m_DragRc.top = 0;   m_DragRc.right = point.x;   m_DragRc.bottom = m_HeaderHeight;   Invalidate();   return;   }     int Dummy , End;   ColAt(point.x, Dummy, Dummy, End);   if ( point.x > End - SIZE_POINT )   SetCursor(LoadCursor(g_hInstance,MAKEINTRESOURCE(WTLDEMO_SIZE)));   else if ( point.y < m_HeaderHeight )   SetCursor(LoadCursor(g_hInstance,MAKEINTRESOURCE(WTLDEMO_GRAB)));     }     BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)   {   if ( zDelta < 0 )   {   if ( nFlags & MK_CONTROL )   PageScroll(false);   else   PageScroll();   }   else   {   if ( nFlags & MK_CONTROL )   PageScroll(false,false);   else   PageScroll(true,false);   }   return TRUE;   }     void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar pScrollBar)   {   SCROLLINFO sc = { sizeof(SCROLLINFO), SIF_POS };   switch (nSBCode)   {   case SB_PAGERIGHT:   PageScroll(false);   break;   case SB_PAGELEFT:   PageScroll(false,false);   break;   case SB_LINERIGHT:   LineScroll(false);   break;   case SB_LINELEFT:   LineScroll(false,false);   break;   case SB_THUMBTRACK:   case SB_THUMBPOSITION:   m_StartCol = nPos;   sc.nPos = m_StartCol;   SetScrollInfo(SB_HORZ,&sc);   Invalidate();   break;   }   }     void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar pScrollBar)   {   SCROLLINFO sc = { sizeof(SCROLLINFO), SIF_POS };   switch (nSBCode)   {   case SB_PAGEDOWN:   PageScroll();   break;   case SB_PAGEUP:   PageScroll(true,false);   break;   case SB_LINERIGHT:   LineScroll();   break;   case SB_LINELEFT:   LineScroll(true,false);   break;   case SB_THUMBTRACK:   case SB_THUMBPOSITION:   m_StartRow = nPos;   sc.nPos = m_StartRow;   SetScrollInfo(SB_VERT,&sc);   Invalidate();   break;   }   }     void UpdateScrollBar(bool vertical = true)   {   SCROLLINFO sc = { sizeof(SCROLLINFO), SIF_POS };   if ( vertical )   {   sc.nPos = m_StartRow;   SetScrollInfo(SB_VERT,&sc);   }   else   {   sc.nPos = m_StartCol;   SetScrollInfo(SB_HORZ,&sc);   }   Invalidate();   }     void PageScroll(bool vertical = true , bool down = true)   {   if ( vertical )   {   m_StartRow += down ? m_PageCnt : - m_PageCnt;    m_StartRow = min(max(m_StartRow,0),m_Rows.size()-1);   }   else   {   m_StartCol += down ? m_PageCnt : - m_PageCnt;    m_StartCol = min(max(m_StartCol,0),m_Cols.size()-1);   }   UpdateScrollBar(vertical);   }     void LineScroll(bool vertical = true, bool down = true)   {   if ( vertical )   {   m_StartRow += down ? m_LineCnt : - m_LineCnt;    m_StartRow =min( max(m_StartRow,0),m_Rows.size()-1);   }   else   {   m_StartCol += down ? m_LineCnt : - m_LineCnt;    m_StartCol = min(max(m_StartCol,0),m_Cols.size()-1);   }   UpdateScrollBar(vertical);   }     void DoPaint(CDCHandle dc)   {   HBRUSH OldBrush;   HFONT OldFont;     OldFont = dc.SelectFont(m_GridFont);   OldBrush = dc.SelectBrush(m_Bk);     DrawBackGround(dc);   DrawHLines(dc);   DrawVLines(dc);     DrawIndicators(dc);   DrawColumnHeadders(dc);   DrawCells(dc);     if ( m_DragType == DRG_COL_MOVE || m_DragType == DRG_COL_SIZE )   DrawColumnHeader(dc, m_DragRc, m_Cols[m_DragCol].HorzAlg, m_Cols[m_DragCol].Idx);     dc.SelectFont(OldFont);   dc.SelectBrush(OldBrush);   }     void DrawHLines(CDCHandle dc)   {   RECT rc;   HPEN OldPen;   OldPen = dc.SelectPen(m_GridPen);   dc.SetBkMode(TRANSPARENT);   GetClientRect(&rc);   for (int i = 2 ; i < 100; i++)   {   dc.MoveTo(m_IndWidth, i*m_IndHeight);   dc.LineTo(m_IndWidth + rc.right, i*m_IndHeight);   }   dc.SelectPen(OldPen);   }     void DrawVLines(CDCHandle dc)   {   RECT rc;   HPEN OldPen;   OldPen = dc.SelectPen(m_GridPen);   dc.SetBkMode(TRANSPARENT);   int EndCol;   GetClientRect(&rc);   EndCol = rc.right;   int Off = 0;   for (int i = m_StartCol ; EndCol > 0 && i < m_Cols.size(); i++)   {   dc.MoveTo(m_IndWidth + Off + m_Cols[i].Width, m_HeaderHeight);   dc.LineTo(m_IndWidth + Off + m_Cols[i].Width, rc.bottom);     Off += m_Cols[i].Width;   EndCol -= m_Cols[i].Width;   }   dc.SelectPen(OldPen);   }     void DrawCells(CDCHandle dc)   {   RECT rc;   HPEN OldPen;   OldPen = dc.SelectPen(m_GridPen);     int EndRow , EndCol , Idx = 0;   GetClientRect(&rc);   EndRow = rc.bottom;   EndCol = rc.right;     dc.SetBkMode(TRANSPARENT);     for (int i = m_StartRow ; EndRow > 0 && i < m_Rows.size(); i++)   {   int Off = 0;   int Delta = EndCol;   for ( int j = m_StartCol ; Delta > 0 && j < m_Cols.size()  ; j++)   {   rc.left = m_IndWidth + Off;   rc.top  = m_HeaderHeight + Idx * m_IndHeight + m_Padding;   rc.right= m_IndWidth + Off + m_Cols[j].Width + m_Padding;   rc.bottom = rc.top + m_IndHeight;     rc.left++;   rc.top++;   rc.right--;   rc.bottom--;     char *Cell = m_Rows[i][m_Cols[j].ColIdx];   //sprintf(Cell,"Cell %d.%d", m_StartRow + i, m_Cols[j].Idx);   dc.DrawText(Cell, strlen(Cell), &rc,   DT_SINGLELINE | DT_VCENTER | m_Cols[j].HorzAlg | DT_END_ELLIPSIS);     Off += m_Cols[j].Width;   Delta -= m_Cols[j].Width;   }   Idx++;   EndRow -= m_IndHeight;   }   dc.SelectPen(OldPen);   }   //   void DrawColumnHeader(CDCHandle dc , RECT &rc , int Alg , int Idx)   {   HPEN OldPen;   TCHAR title[200];   OldPen = dc.SelectPen(m_GridPen);   dc.SetBkMode(TRANSPARENT);   dc.FillRect(&rc,::GetSysColorBrush(COLOR_3DFACE));   dc.Draw3dRect(rc.left,   rc.top,   rc.right - rc.left,   rc.bottom - rc.top,   ::GetSysColor(COLOR_3DHILIGHT),   ::GetSysColor(COLOR_3DSHADOW));     sprintf(title,"COLUMN %d",Idx);   rc.left++;   rc.top++;   rc.bottom--;   rc.right--;     dc.DrawText(title, strlen(title), &rc,   DT_SINGLELINE | DT_VCENTER | Alg | DT_END_ELLIPSIS);   dc.SelectPen(OldPen);   }   void DrawColumnHeadders(CDCHandle dc)   {   RECT rc;   int Off = 0;   int Idx = 0;   int EndCol;     GetClientRect(&rc);   EndCol = rc.right;     for ( int i=m_StartCol ; EndCol > 0 && i < m_Cols.size(); i++ )   {   rc.left = m_IndWidth + Off;   rc.right = rc.left + m_Cols[i].Width + m_Padding;   rc.top = 0;   rc.bottom = m_HeaderHeight;     DrawColumnHeader(dc,rc,m_Cols[i].HorzAlg, m_Cols[i].Idx);     Off += m_Cols[i].Width;   EndCol -= m_Cols[i].Width;   }   }     void DrawIndicators(CDCHandle dc)   {   RECT rc;   int EndRow;   TCHAR num[100];   GetClientRect(&rc);   EndRow = rc.bottom / m_IndHeight;   for (int i = 0 ; i< EndRow ; i++)   {   RECT rc = { 0,    i* m_IndHeight + m_HeaderHeight + m_Padding,    m_IndWidth,    i* m_IndHeight + m_IndHeight + m_HeaderHeight };   dc.FillRect(&rc,::GetSysColorBrush(COLOR_3DFACE));   dc.Draw3dRect(rc.left,   rc.top,   rc.right-rc.left,   rc.bottom-rc.top,   ::GetSysColor(COLOR_3DHILIGHT),   ::GetSysColor(COLOR_3DSHADOW));     sprintf(num,"%d",m_StartRow + i);   rc.left++;   rc.top++;   rc.bottom--;   rc.right--;     dc.SetBkMode(TRANSPARENT);   dc.DrawText(num, strlen(num), &rc,   DT_SINGLELINE | DT_VCENTER | DT_RIGHT | DT_END_ELLIPSIS);     }   }     void DrawBackGround(CDCHandle dc)   {   RECT rc;   GetClientRect(&rc);   dc.FillRect(&rc,m_Bk);   }     int OnCreate(LPCREATESTRUCT lpCreateStruct)   {   RECT rc;   SCROLLINFO sc = { sizeof(SCROLLINFO), SIF_PAGE |SIF_POS };   GetClientRect(&rc);   SetScrollRange(SB_HORZ,0,m_Width-1);   SetScrollRange(SB_VERT,0,m_Height-1);   //   if ( m_Width <= (rc.right - rc.left) )   ShowScrollBar(SB_HORZ,FALSE);   else   {     }   if ( m_Height <= rc.bottom - rc.top )   ShowScrollBar(SB_VERT,FALSE);   return 0;   }       CGridView() :    m_Width(0),   m_Height(0),    m_IndWidth(50),   m_IndHeight(20),   m_Padding(0),   m_StartRow(0),   m_StartCol(0),   m_HeaderHeight(20),   m_PageCnt(10),   m_LineCnt(1),   m_DragType(DRG_NONE)   {   //   LOGBRUSH Pen = {0};   Pen.lbStyle = BS_SOLID;   Pen.lbColor = RGB(230,230,230);   DWORD PenStyle[2] = {1,1};   m_GridPen.CreatePen(PS_COSMETIC | PS_USERSTYLE,1,&Pen,2,PenStyle);   //   LOGFONT fnt = {0};   fnt.lfHeight = min(m_HeaderHeight,20);   fnt.lfWeight = 2;   sprintf(fnt.lfFaceName,_T("Courier New"));   m_GridFont.CreateFontIndirect(&fnt);   //   m_Bk.CreateSolidBrush(RGB(255,255,255));   //   for (int i = 0; i < 300 ; i++)   {   COLINFO col;   col.Idx = i;   col.Width = 150;   col.ColIdx = i;   col.HorzAlg = i % 4 ? DT_RIGHT : DT_LEFT;   m_Cols[i] = col;   m_Width++;   }   for ( int i = 0 ; i < 500 ; i++)   {   for ( int j = 0 ; j< 300; j++ )   {   char *buf = new char[200];   sprintf(buf,"Cell %d.%d",i,j);   m_Rows[i][j] = buf;   }   m_Height++;   }   }     ~CGridView()   {   for ( int i = 0 ; i < 500 ; i++)   {   for ( int j = 0 ; j< 300; j++ )   {   //cout << m_Rows[i][j] << endl;   delete m_Rows[i][j];   }   }   }   virtual void OnFinalMessage(HWND /*hWnd*/)   {   delete this;   }       private:   int m_Width; // Column Count   int m_Height; // Row Count   int m_IndWidth;   int m_IndHeight;   int m_Padding;   int m_StartRow;   int m_StartCol;   int m_PageCnt;   int m_LineCnt;   CPen m_GridPen;   CFont m_GridFont;   CBrush m_Bk;   RECT m_DragRc;   int m_DragCol;   int m_DragStart;   int m_DragEnd;   std::tr1::array<COLINFO,300> m_Cols;   std::tr1::array< std::tr1::array<char*,300>,500> m_Rows;   int m_HeaderHeight;   int m_DragType;       };     #endif