#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