📄 gridctrl.cpp
字号:
//的同时对nRight每次增加一列的宽
//道理同上:
m_idTopLeftCell.row = m_nFixedRows;
int nTop = 0;
while (nTop < nVertScroll && m_idTopLeftCell.row < (GetRowCount()-1))
nTop += GetRowHeight(m_idTopLeftCell.row++);
TRACE2("TopLeft cell is row %d, col %d\n",m_idTopLeftCell.row, m_idTopLeftCell.col);
return m_idTopLeftCell;//返回当前的左上角单元格ID(就是行列号)
}
// This gets even partially visible cells
// 得到可见部分的单元格:
CCellRange CGridCtrl::GetVisibleNonFixedCellRange(LPRECT pRect /*=NULL*/,
BOOL bForceRecalculation /*=FALSE*/)
{
CRect rect;
GetClientRect(rect);//窗口的区域
//左上角非固定单元格的ID:
//GetTopleftNonFixedCell会根据滚动条的位置返回不同的左上角非固定单元格。
//有了这个功能,GetVisibleNonFixedCellRange才会返回不同的单元格范围
CCellID idTopLeft = GetTopleftNonFixedCell(bForceRecalculation);//左上角非固定单元格的ID
// calc bottom
// 找到底部(可视单元格区域的底部)
int bottom = GetFixedRowHeight();//固定行的高
for (int i = idTopLeft.row; i < GetRowCount(); i++)
{
bottom += GetRowHeight(i);//为bottom增加那一行的高
//因为可能用户调整后各行的高都不一样
if (bottom >= rect.bottom)//如果bottom大于等于窗口的底
{
bottom = rect.bottom;//botto就等于窗口的底
break; //然后就跳出循环
}
}
int maxVisibleRow = min(i, GetRowCount() - 1);//在i和总行数-1中取小
// calc right
//找到右边界
int right = GetFixedColumnWidth();//固定列的宽
for (i = idTopLeft.col; i < GetColumnCount(); i++)
{
right += GetColumnWidth(i);//为right增加那一列的宽
//因为用户调整后各列的宽也可能不一样
if (right >= rect.right)//如果right大于等于窗口的right
{
right = rect.right; //right就等于窗口的right
break; //然后就跳出循环
}
}
int maxVisibleCol = min(i, GetColumnCount() - 1);//在i和总列数-1中取小
if (pRect)
{
//对pRect初始化:
pRect->left = pRect->top = 0;
pRect->right = right;
pRect->bottom = bottom;
}
//返回可视部分的单元格范围:
return CCellRange(idTopLeft.row, idTopLeft.col, maxVisibleRow, maxVisibleCol);
}
BOOL CGridCtrl::OnEraseBkgnd(CDC* pDC)
{
return true;
// return CWnd::OnEraseBkgnd(pDC);
}
BOOL CGridCtrl::SetItemText(int nRow, int nCol, LPCTSTR str)
{
CGridCellBase* pCell = GetCell(nRow, nCol);
if (!pCell)
return FALSE;
pCell->SetText(str);
return TRUE;
}
void CGridCtrl::SetSortColumn(int nCol)
{
// if (m_nSortColumn >= 0)
// InvalidateCellRect(0, m_nSortColumn);
m_nSortColumn = nCol;
// if (nCol >= 0)
// InvalidateCellRect(0, nCol);
}
void CGridCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
CCellID cellid=GetCellFromPt(point);//得到鼠标点中的CellID
int row=cellid.row;
int col=cellid.col;
COLORREF lastclr;
CDC* pDC=GetDC();
m_bLMouseButtonDown = TRUE;//设置鼠标按下标志(OnMouseMove()中需要)
m_LeftClickDownPoint = point;//鼠标点(OnMouseMove()中需要)
m_LeftClickDownCell = GetCellFromPt(point);//鼠标点中的单元格ID(重要)
CRect cellrect;
GetCellRect(m_LeftClickDownCell,&cellrect);
if(m_LeftClickDownPoint.x<=(cellrect.left+5))//如果鼠标点在此范围内,就设定为左边的单元格
m_LeftClickDownCell.col--; //这样,就限制只能从右边界调整单元格宽度
if (m_bAllowColumnResize && MouseOverColumnResizeArea(point))
{
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZEWE));//改变光标
}
if(this->IsValid(m_SelectedCell))//m_SelectedCell保存上一次选择的单元格,因为没有初始化
//所以第一次是非法的。
//如果它合法:
{
CGridCellBase* pcell=GetCell(row,col);//得到鼠标点中的单元格
if(m_SelectedCell!=cellid)//如果m_SelectedCell不是当前鼠标点中的
{
if(pcell)
{
lastclr=GetDefaultCell(FALSE, FALSE)->GetBackClr();//缺省的非固定单元格的背景色
pcell->SetBackClr(RGB(128,196,255));//设置新的背景色
CGridCellBase* pSelcell=GetCell(m_SelectedCell.row,m_SelectedCell.col);//得到上次选中的单元格
pSelcell->SetBackClr(lastclr);//恢复他的背景色
m_SelectedCell=cellid;//保存这次选中的单元格
}
}
}
else//m_SelectedCell为非法(第一次肯定是的)
{
CGridCellBase* pcell=GetCell(row,col);
if(pcell)
{
lastclr=GetDefaultCell(FALSE, FALSE)->GetBackClr();
pcell->SetBackClr(RGB(128,196,255));
m_SelectedCell=cellid;
}
}
if(m_LeftClickDownCell.row < GetFixedRowCount())
{
OnFixedRowClick(m_LeftClickDownCell);
}
Invalidate();
// RedrawWindow();
CWnd::OnLButtonDown(nFlags, point);
}
// If resizing or cell counts/sizes change, call this - it'll fix up the scroll bars
void CGridCtrl::ResetScrollBars()
{
// Force a refresh.
m_idTopLeftCell.row = -1;
if (!m_bAllowDraw || !::IsWindow(GetSafeHwnd()))
return;
CRect rect;
// This would have caused OnSize event - Brian
//EnableScrollBars(SB_BOTH, FALSE);
GetClientRect(rect);
if (rect.left == rect.right || rect.top == rect.bottom)//没有窗口面积就返回
return;
if (IsVisibleVScroll())
rect.right += GetSystemMetrics(SM_CXVSCROLL) + GetSystemMetrics(SM_CXBORDER);
//GetSystemMetrics返回显示器的屏幕尺寸
//GetSystemMetrics(SM_CXVSCROLL)得到垂直滚动条的宽
if (IsVisibleHScroll())
rect.bottom += GetSystemMetrics(SM_CYHSCROLL) + GetSystemMetrics(SM_CYBORDER);
rect.left += GetFixedColumnWidth();//左边界右移
rect.top += GetFixedRowHeight();//顶边界下移
if (rect.left >= rect.right || rect.top >= rect.bottom)//不显示滚动条的条件
{
// EnableScrollBarCtrl(SB_BOTH, FALSE);
return;
}
//可见区域:
CRect VisibleRect(GetFixedColumnWidth(), GetFixedRowHeight(),
rect.right, rect.bottom);
//虚区域:
CRect VirtualRect(GetFixedColumnWidth(), GetFixedRowHeight(),
GetVirtualWidth(), GetVirtualHeight());
// Removed to fix single row scrollbar problem (Pontus Goffe)
// CCellRange visibleCells = GetUnobstructedNonFixedCellRange();
// if (!IsValid(visibleCells)) return;
//TRACE(_T("Visible: %d x %d, Virtual %d x %d. H %d, V %d\n"),
// VisibleRect.Width(), VisibleRect.Height(),
// VirtualRect.Width(), VirtualRect.Height(),
// IsVisibleHScroll(), IsVisibleVScroll());
// If vertical scroll bar, horizontal space is reduced
//如果显示垂直滚动条,水平空间会减少一个滚动条的宽度
if (VisibleRect.Height() < VirtualRect.Height())
VisibleRect.right -= ::GetSystemMetrics(SM_CXVSCROLL);
// If horz scroll bar, vert space is reduced
//如果显示水平滚动条,垂直空间会减少一个滚动条的宽度
if (VisibleRect.Width() < VirtualRect.Width())
VisibleRect.bottom -= ::GetSystemMetrics(SM_CYHSCROLL);
// Recheck vertical scroll bar
//if (VisibleRect.Height() < VirtualRect.Height())
// VisibleRect.right -= ::GetSystemMetrics(SM_CXVSCROLL);
if (VisibleRect.Height() < VirtualRect.Height())
{
//EnableScrollBars(SB_VERT, TRUE);
m_nVScrollMax = VirtualRect.Height() - 1;
}
else
{
// EnableScrollBars(SB_VERT, FALSE);
m_nVScrollMax = 0;
}
if (VisibleRect.Width() < VirtualRect.Width())
{
// EnableScrollBars(SB_HORZ, TRUE);
m_nHScrollMax = VirtualRect.Width() - 1;
}
else
{
// EnableScrollBars(SB_HORZ, FALSE);
m_nHScrollMax = 0;
}
ASSERT(m_nVScrollMax < INT_MAX && m_nHScrollMax < INT_MAX); // This should be fine
/* Old code - CJM
SCROLLINFO si;
si.cbSize = sizeof(SCROLLINFO);
si.fMask = SIF_PAGE;
si.nPage = (m_nHScrollMax>0)? VisibleRect.Width() : 0;
SetScrollInfo(SB_HORZ, &si, FALSE);
si.nPage = (m_nVScrollMax>0)? VisibleRect.Height() : 0;
SetScrollInfo(SB_VERT, &si, FALSE);
SetScrollRange(SB_VERT, 0, m_nVScrollMax, TRUE);
SetScrollRange(SB_HORZ, 0, m_nHScrollMax, TRUE);
*/
// New code - Paul Runstedler
CMyGridFrame *pWnd=(CMyGridFrame*)(this->GetParent());
SCROLLINFO si;
si.cbSize = sizeof(SCROLLINFO);
si.fMask = SIF_PAGE | SIF_RANGE;
si.nPage = (m_nHScrollMax>0)? VisibleRect.Width() : 0;
si.nMin = 0;
si.nMax = m_nHScrollMax;
//CWnd* pWnd=GetParent();
SetScrollInfo(SB_HORZ,&si, TRUE);
si.fMask |= SIF_DISABLENOSCROLL;
si.nPage = (m_nVScrollMax>0)? VisibleRect.Height() : 0;
si.nMin = 0;
si.nMax = m_nVScrollMax;
SetScrollInfo(SB_VERT,&si, TRUE);
}
void CGridCtrl::EnableScrollBars(int nBar, BOOL bEnable /*=TRUE*/)
{
CMyGridFrame* pWnd=(CMyGridFrame*)(this->GetParent());
if (bEnable)
{
if (!IsVisibleHScroll() && (nBar == SB_HORZ || nBar == SB_BOTH))
{
m_nBarState |= GVL_HORZ;
pWnd->EnableScrollBarCtrl(SB_HORZ, bEnable);
//CWnd::EnableScrollBarCtrl(SB_HORZ, bEnable);
}
if (!IsVisibleVScroll() && (nBar == SB_VERT || nBar == SB_BOTH))
{
m_nBarState |= GVL_VERT;
pWnd->EnableScrollBarCtrl(SB_VERT, bEnable);
//CWnd::EnableScrollBarCtrl(SB_VERT, bEnable);
}
}
else
{
if ( IsVisibleHScroll() && (nBar == SB_HORZ || nBar == SB_BOTH))
{
m_nBarState &= ~GVL_HORZ;
pWnd->EnableScrollBarCtrl(SB_HORZ, bEnable);
//CWnd::EnableScrollBarCtrl(SB_HORZ, bEnable);
}
if ( IsVisibleVScroll() && (nBar == SB_VERT || nBar == SB_BOTH))
{
m_nBarState &= ~GVL_VERT;
pWnd->EnableScrollBarCtrl(SB_VERT, bEnable);
//CWnd::EnableScrollBarCtrl(SB_VERT, bEnable);
}
}
}
long CGridCtrl::GetVirtualWidth() const
{
long lVirtualWidth = 0;
int iColCount = GetColumnCount();
for (int i = 0; i < iColCount; i++)
lVirtualWidth += m_arColWidths[i];
return lVirtualWidth;
}
long CGridCtrl::GetVirtualHeight() const
{
long lVirtualHeight = 0;
int iRowCount = GetRowCount();
for (int i = 0; i < iRowCount; i++)
lVirtualHeight += m_arRowHeights[i];
return lVirtualHeight;
}
void CGridCtrl::OnSize(UINT nType, int cx, int cy)
{
CWnd::OnSize(nType, cx, cy);
// this->EnableScrollBarCtrl(SB_BOTH,FALSE);//不能加这一句。否则会出 "Debug Assertion Failed"错误。
//你不能禁止滚动控件。
//你只是把滚动控制权交给了父窗口。
//通过重载GetScrollBarCtrl()把滚动控制权交给了CMyGridFrame.
ResetScrollBars();
}
void CGridCtrl::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
int scrollPos =GetScrollPos32(SB_HORZ);
CCellID idTopLeft = GetTopleftNonFixedCell();
CRect rect;
GetClientRect(rect);
switch (nSBCode)
{
case SB_LINERIGHT:
if (scrollPos < m_nHScrollMax)
{
// may have contiguous hidden columns. Blow by them
while (idTopLeft.col < (GetColumnCount()-1)
&& GetColumnWidth( idTopLeft.col) < 1 )
{
idTopLeft.col++;
}
int xScroll = GetColumnWidth(idTopLeft.col);
SetScrollPos32(SB_HORZ, scrollPos + xScroll);
if (GetScrollPos32(SB_HORZ) == scrollPos)
break; // didn't work
rect.left = GetFixedColumnWidth();
//rect.left = GetFixedColumnWidth() + xScroll;
//ScrollWindow(-xScroll, 0, rect);
//rect.left = rect.right - xScroll;
InvalidateRect(rect);
}
break;
case SB_LINELEFT:
if (scrollPos > 0 && idTopLeft.col > GetFixedColumnCount())
{
int iColToUse = idTopLeft.col-1;
// may have contiguous hidden columns. Blow by them
while( iColToUse > GetFixedColumnCount()
&& GetColumnWidth( iColToUse) < 1 )
{
iColToUse--;
}
int xScroll = GetColumnWidth(iColToUse);
SetScrollPos32(SB_HORZ, max(0, scrollPos - xScroll));
rect.left = GetFixedColumnWidth();
//ScrollWindow(xScroll, 0, rect);
//rect.right = rect.left + xScroll;
InvalidateRect(rect);
}
break;
case SB_PAGERIGHT:
if (scrollPos < m_nHScrollMax)
{
rect.left = GetFixedColumnWidth();
int offset = rect.Width();
int pos = min(m_nHScrollMax, scrollPos + offset);
SetScrollPos32(SB_HORZ, pos);
rect.left = GetFixedColumnWidth();
InvalidateRect(rect);
}
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -