📄 customgrid.cpp
字号:
// CustomGrid.cpp : implementation file
//
#include "stdafx.h"
#include "CustomGrid.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CCustomGrid
CCustomGrid::CCustomGrid()
{
WNDCLASS wndcls;
HINSTANCE hInst = AfxGetInstanceHandle();
if (!(::GetClassInfo(hInst, GRIDCTRL_CLASSNAME, &wndcls)))
{
// otherwise we need to register a new class
wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
wndcls.lpfnWndProc = ::DefWindowProc;
wndcls.cbClsExtra = wndcls.cbWndExtra = 0;
wndcls.hInstance = hInst;
wndcls.hIcon = NULL;
wndcls.hCursor = AfxGetApp()->LoadStandardCursor(IDC_ARROW);
wndcls.hbrBackground = (HBRUSH) (COLOR_3DFACE + 1);
wndcls.lpszMenuName = NULL;
wndcls.lpszClassName = GRIDCTRL_CLASSNAME;
if (!AfxRegisterClass(&wndcls)) {
AfxThrowResourceException();
return;
}
}
m_nRows = 0;
m_nColums = 0;
m_nFixedRows = 1;
m_nFixedColums = 0;
m_nVScrollMax = 0;
m_nHScrollMax = 0;
m_bCanScrollPage = false;
m_nMouseMode = MOUSE_NOTHING;
m_bCellEditable = false;
}
CCustomGrid::~CCustomGrid()
{
m_Font.DeleteObject();
m_strItems.RemoveAll();
DestroyWindow();
}
BEGIN_MESSAGE_MAP(CCustomGrid, CWnd)
//{{AFX_MSG_MAP(CCustomGrid)
ON_WM_LBUTTONDOWN()
ON_WM_MOUSEMOVE()
ON_WM_VSCROLL()
ON_WM_HSCROLL()
ON_WM_PAINT()
ON_WM_SIZE()
ON_WM_LBUTTONUP()
ON_WM_LBUTTONDBLCLK()
//}}AFX_MSG_MAP
ON_MESSAGE(WM_GETFONT, OnGetFont)
ON_NOTIFY(GVN_ENDLABELEDIT, IDC_CELLEDIT_CONTROL, OnModifyEditCell)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CCustomGrid custom function
void CCustomGrid::SetItemFont(int FontHeight)
{//创建栅格中文字显示使用的字体
m_Font.DeleteObject();
m_Font.CreateFont(FontHeight, 0, 0, 0, FW_NORMAL, false, false, false,
DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, DEFAULT_PITCH, "宋体");//创建字体
m_nFontHeight = FontHeight;
}
void CCustomGrid::SetRowCount(UINT row)
{
//改变行数,调整数组大小
if(m_nRows != row){
m_nRows = row;
m_strItems.SetSize(m_nRows * m_nColums);
}
//更新显示
if (GetSafeHwnd())
{
ResetScrollBars();
}
//调整固定行的最大值
if(m_nRows < m_nFixedRows)
m_nFixedRows = m_nRows;
}
void CCustomGrid::SetColumnCount(UINT colum, int* columwidth)
{
int i, j;
CString item;
if(colum < m_nColums){//列变少,数组变小
for(i = 1; i < m_nRows; i++){
for(j = 0; j < colum; j++){
item = m_strItems.GetAt(i*m_nColums+j);
m_strItems.SetAt( i*colum+j, item );
}
}
m_strItems.SetSize(m_nRows * colum);
}
else if(colum > m_nColums){//列变多,数组变大
m_strItems.SetSize(m_nRows * colum);
for(i = m_nRows-1; i > 0; i--){
for(j = m_nColums-1; j >= 0; j--){
item = m_strItems.GetAt( i*m_nColums+j);
m_strItems.SetAt( i*colum+j, item );
}
}
}
m_nColumsWidth.SetSize(colum);
if(columwidth)
for(i = 0 ; i < colum; i++)
m_nColumsWidth.SetAt(i, *(columwidth+i));
else
for(i = m_nColums; i < colum; i++)
m_nColumsWidth.SetAt(i, DEFAULT_COLUMWIDTH);
m_nColums = colum;
if (GetSafeHwnd())
{
ResetScrollBars();
}
//调整固定列的最大值
if(m_nColums < m_nFixedColums)
m_nFixedColums = m_nColums;
}
void CCustomGrid::SetItemString(int row, int colum, LPCTSTR item)
{
ASSERT( row < m_nRows && colum < m_nColums);
m_strItems.SetAt(row*m_nColums + colum, item);
}
int CCustomGrid::GetFixedColumnWidth()
{
int i, n;
if(m_nFixedColums > m_nColums){
return 0;
}
for(i=0, n=0;i<m_nFixedColums;i++){
n += m_nColumsWidth[i];
}
n += m_nFixedColums * (DEFAULT_TEXTWRAP * 2 +1);
return n;
}
int CCustomGrid::GetFixedRowHeight()
{
if( m_nFixedRows > m_nRows)
return 0;
else
return m_nFixedRows * (m_nFontHeight + DEFAULT_TEXTWRAP * 2 +1);
}
int CCustomGrid::GetVirtualWidth()
{
int i,n;
for(i=0, n=0;i<m_nColums;i++){
n += m_nColumsWidth[i];
}
n += m_nColums * (DEFAULT_TEXTWRAP * 2 +1);
return n;
}
int CCustomGrid::GetVirtualHeight()
{
return m_nRows * (m_nFontHeight + DEFAULT_TEXTWRAP * 2 + 1);
}
void CCustomGrid::ResetScrollBars()
{
if (!::IsWindow(GetSafeHwnd()))
return;
CRect rect;
GetClientRect(rect);
int hPage = rect.Width() - GetFixedColumnWidth();
int vPage = rect.Height() - GetFixedRowHeight();
SCROLLINFO si;
si.cbSize = sizeof(SCROLLINFO);
si.fMask = SIF_PAGE;
si.nPage = hPage; SetScrollInfo(SB_HORZ, &si, FALSE);
si.nPage = vPage; SetScrollInfo(SB_VERT, &si, FALSE);
if (rect.Height() < GetVirtualHeight() && rect.Height() > GetFixedRowHeight()){
m_nVScrollMax = GetVirtualHeight() - rect.Height();
SetScrollRange(SB_VERT, 0, m_nVScrollMax + vPage, FALSE);
}
else{
m_nVScrollMax = 0;
SetScrollRange(SB_VERT, 0, 0, TRUE);
}
if (rect.Width() < GetVirtualWidth() && rect.Width() > GetFixedColumnWidth()){
m_nHScrollMax = GetVirtualWidth() - rect.Width();
SetScrollRange(SB_HORZ, 0, m_nHScrollMax + hPage, TRUE);
}
else{
m_nHScrollMax = 0;
SetScrollRange(SB_HORZ, 0, 0, TRUE);
}
Invalidate(false);//更新显示
}
int CCustomGrid::GetScrollPos32(int nBar, BOOL bGetTrackPos /* = FALSE */)
{
SCROLLINFO si;
si.cbSize = sizeof(SCROLLINFO);
if (bGetTrackPos)
{
if (GetScrollInfo(nBar, &si, SIF_TRACKPOS))
return si.nTrackPos;
}
else
{
if (GetScrollInfo(nBar, &si, SIF_POS))
return si.nPos;
}
return 0;
}
BOOL CCustomGrid::SetScrollPos32(int nBar, int nPos, BOOL bRedraw /* = TRUE */)
{
SCROLLINFO si;
si.cbSize = sizeof(SCROLLINFO);
si.fMask = SIF_POS;
si.nPos = nPos;
return SetScrollInfo(nBar, &si, bRedraw);
}
void CCustomGrid::DrawCell(CDC* pDC, int nRow, int nCol, CRect rect)
{
COLORREF oldcolor = pDC->SetTextColor(CR_DEFAULT_ITEM);
int oldbkmode = pDC->SetBkMode(TRANSPARENT);//背景透明
CFont* oldfont = pDC->SelectObject( &m_Font );
CString title = GetItemString(nRow, nCol);
pDC->ExtTextOut(rect.left, rect.top, ETO_CLIPPED , rect, title, NULL);
pDC->SelectObject( oldfont );
pDC->SetTextColor(oldcolor);
pDC->SetBkMode(oldbkmode);
}
void CCustomGrid::DrawFixedCell(CDC* pDC, int nRow, int nCol, CRect rect)
{
COLORREF oldcolor = pDC->SetTextColor(CR_DEFAULT_FIXITEM);
int oldbkmode = pDC->SetBkMode(TRANSPARENT);//背景透明
CFont* oldfont = pDC->SelectObject( &m_Font );
CRect bkrect(rect.left -DEFAULT_TEXTWRAP, rect.top -DEFAULT_TEXTWRAP, rect.right+DEFAULT_TEXTWRAP, rect.bottom+DEFAULT_TEXTWRAP);
pDC->FillSolidRect(bkrect, CR_DEFAULT_FIXEDBK);
CString title = GetItemString(nRow, nCol);
pDC->ExtTextOut(rect.left, rect.top, ETO_CLIPPED, rect, title, NULL);
pDC->SelectObject( oldfont );
pDC->SetTextColor(oldcolor);
pDC->SetBkMode(oldbkmode);
}
CPoint CCustomGrid::GetScrolledCellFromPT(CPoint& Point)
{
CPoint cell;
int i;
if(Point.x < GetFixedColumnWidth())
cell.x = 0;
else
cell.x = -GetScrollPos32(SB_HORZ);
for(i=0;i< m_nColums; i++){
if(cell.x + m_nColumsWidth[i] + 2 * DEFAULT_TEXTWRAP + 1 > Point.x)
break;
cell.x += m_nColumsWidth[i] + 2 * DEFAULT_TEXTWRAP + 1;
}
cell.x = i >= m_nColums ? -1 : i;
if(Point.y < GetFixedRowHeight())
cell.y = 0;
else
cell.y = -GetScrollPos32(SB_VERT);
i = (Point.y - cell.y) * 1.0 / (2 * DEFAULT_TEXTWRAP + 1 + m_nFontHeight);
cell.y = i >= m_nRows ? -1 : i;
return cell;
}
RECT CCustomGrid::GetScrolledCellRect(int Row, int Col)
{
ASSERT(Row < m_nRows && Col < m_nColums);
CRect rect(0, 0, 0, 0);
int i;
if(Col < m_nFixedColums){
rect.left = 0;
}
else{
rect.left = -GetScrollPos32(SB_HORZ);
}
for(i = 0; i < Col; i++){
rect.left += m_nColumsWidth[i] + 2 * DEFAULT_TEXTWRAP + 1;
}
rect.right = rect.left + m_nColumsWidth[i] + 2 * DEFAULT_TEXTWRAP + 1;
if(Row < m_nFixedRows){
rect.top = 0;
}
else{
rect.top = -GetScrollPos32(SB_VERT);
}
rect.top += Row * (m_nFontHeight + 2 * DEFAULT_TEXTWRAP + 1);
rect.bottom = rect.top + m_nFontHeight + 2 * DEFAULT_TEXTWRAP + 1;
return rect;
}
void CCustomGrid::VisibleCell(int Row, int Col)
{
CRect CellRect = GetScrolledCellRect(Row, Col);
CRect ClientRect;
GetClientRect(&ClientRect);
int vOffset, hOffset;
ClientRect.left += GetFixedColumnWidth();
ClientRect.top += GetFixedRowHeight();
if(Row < m_nFixedRows)
vOffset = 0;
else if( (CellRect.Height() > ClientRect.Height())
|| (CellRect.top < ClientRect.top) )
vOffset = CellRect.top - ClientRect.top;
else if(CellRect.bottom > ClientRect.bottom)
vOffset = CellRect.bottom - ClientRect.bottom;
else
vOffset = 0;
if(Col < m_nFixedColums)
hOffset = 0;
else if( (CellRect.Width() > ClientRect.Width())
|| (CellRect.left < ClientRect.left) )
hOffset = CellRect.left - ClientRect.left;
else if(CellRect.right > ClientRect.right)
hOffset = CellRect.right - ClientRect.right;
else
hOffset = 0;
SetScrollPos(SB_HORZ, GetScrollPos(SB_HORZ) + hOffset);
SetScrollPos(SB_VERT, GetScrollPos(SB_VERT) + vOffset);
Invalidate(false);
}
int CCustomGrid::MouseOverColumnResizeArea(CPoint& point)
{
CPoint Cell = GetScrolledCellFromPT(point);
if(Cell.x < 0 || Cell.y < 0)
return -1;
CRect CellRect = GetScrolledCellRect(Cell.y, Cell.x);
int i=-1;
if( Cell.y == 0 && Cell.x > 0 && abs(point.x - CellRect.left) <= DEFAULT_TEXTWRAP )
i = Cell.x -1;
if( Cell.y == 0 && Cell.x >= 0 && abs(point.x - CellRect.right) <= DEFAULT_TEXTWRAP )
i = Cell.x;
return i;
}
LRESULT CCustomGrid::SendMessageToParent(int nRow, int nCol, int nMessage)
{
if (!IsWindow(m_hWnd) || nRow < 0 || nCol < 0)
return 0;
NMHDR32 nmgv;
nmgv.hwndFrom = m_hWnd;
nmgv.idFrom = GetDlgCtrlID();
nmgv.code = nMessage;
nmgv.nRow = nRow;
nmgv.nCol = nCol;
nmgv.strText = GetItemString(nRow, nCol);
CWnd *pOwner = GetOwner();
if (pOwner && IsWindow(pOwner->m_hWnd))
return pOwner->SendMessage(WM_NOTIFY, nmgv.idFrom, (LPARAM)&nmgv);
else
return 0;
}
void CCustomGrid::StartEditCell(int nRow, int nCol)
{
CRect CellRect = GetScrolledCellRect(nRow, nCol);
if(!IsEditable() || nRow < 0 || nCol < 0 || nCol < m_nFixedColums || nRow < m_nFixedRows )
//指定单元不可编辑
return;
new CCellEdit(this, CellRect, IDC_CELLEDIT_CONTROL, nRow, nCol, GetItemString(nRow, nCol));
}
/////////////////////////////////////////////////////////////////////////////
// CCustomGrid message handlers
void CCustomGrid::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
SetFocus();
CPoint Cell = GetScrolledCellFromPT(point);
if (m_nMouseMode == MOUSE_OVER_COL_DIVIDE) // sizing column
{
CRect client;
GetClientRect(client);
CRect invertedRect(point.x - 1, client.top, point.x + 1, client.bottom);
CDC* pDC = GetDC();
if (pDC) {
pDC->InvertRect(&invertedRect);
ReleaseDC(pDC);
m_nMouseMode = MOUSE_SIZING_COL;
m_OldPoint = point;
}
if(m_nSizingCol == m_nColums - 1){
m_bCanScrollPage = true;
}
ClientToScreen(&client);
ClipCursor(client);
}
else if(m_nMouseMode == MOUSE_NOTHING){
CPoint Cell = GetScrolledCellFromPT(point);
if(Cell.x >= 0 && Cell.y >= 0)
//移动滚动条,显示指定单元
VisibleCell(Cell.y, Cell.x);
if( IsEditable() )
//创建编辑对话框
StartEditCell(Cell.y, Cell.x);
}
if(Cell.x >=0 && Cell.y >=0)
SendMessageToParent(Cell.y, Cell.x, GVN_CLICK);
}
void CCustomGrid::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CRect client;
GetClientRect(client);
if(m_nMouseMode == MOUSE_NOTHING){
if( (m_nSizingCol = MouseOverColumnResizeArea(point)) >= 0){
::SetClassLong(GetSafeHwnd(), GCL_HCURSOR, (LONG)AfxGetApp()->LoadStandardCursor(IDC_SIZEWE));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -