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

清华大佬耗费三个月吐血整理的几百G的资源,免费分享!....>>>

#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