📄 gridctrl.cpp
字号:
}
////////////////////////////////////////////////////////////////////////////////////////
// hittest-like functions
// Get cell from point
CCellID CGridCtrl::GetCellFromPt(CPoint point, BOOL bAllowFixedCellCheck /*=TRUE*/)
{
CCellID idTopLeft = GetTopleftNonFixedCell();
CCellID cellID; // return value
// calculate column index
int fixedColWidth = GetFixedColumnWidth();
if (point.x < 0 || (!bAllowFixedCellCheck && point.x < fixedColWidth)) // not in window
cellID.col = -1;
else if (point.x < fixedColWidth) // in fixed col
{
int xpos = 0;
for (int col = 0; col < m_nFixedCols; col++)
{
xpos += GetColumnWidth(col);
if (xpos > point.x) break;
}
cellID.col = col;
}
else // in non-fixed col
{
int xpos = fixedColWidth;
for (int col = idTopLeft.col; col < GetColumnCount(); col++)
{
xpos += GetColumnWidth(col);
if (xpos > point.x) break;
}
if (col >= GetColumnCount())
cellID.col = GetColumnCount() - 1;
else
cellID.col = col;
}
// calculate row index
int fixedRowHeight = GetFixedRowHeight();
if (point.y < 0 || (!bAllowFixedCellCheck && point.y < fixedRowHeight)) // not in window
cellID.row = -1;
else if (point.y < fixedRowHeight) // in fixed col
{
int ypos = 0;
for (int row = 0; row < m_nFixedRows; row++)
{
ypos += GetRowHeight(row);
if (ypos > point.y) break;
}
cellID.row = row;
}
else
{
int ypos = fixedRowHeight;
for (int row = idTopLeft.row; row < GetRowCount(); row++)
{
ypos += GetRowHeight(row);
if (ypos > point.y) break;
}
if (row >= GetRowCount())
cellID.row = -1;
else
cellID.row = row;
}
return cellID;
}
////////////////////////////////////////////////////////////////////////////////
// CGridCtrl cellrange functions
CCellID CGridCtrl::GetTopleftNonFixedCell()
{
int nVertScroll = GetScrollPos(SB_VERT),
nHorzScroll = GetScrollPos(SB_HORZ);
int nColumn = m_nFixedCols, nRight = 0;
while (nRight < nHorzScroll && nColumn < (GetColumnCount()-1))
nRight += GetColumnWidth(nColumn++);
int nRow = m_nFixedRows, nTop = 0;
while (nTop < nVertScroll && nRow < (GetRowCount()-1))
nTop += GetRowHeight(nRow++);
//TRACE("TopLeft cell is row %d, col %d\n",nRow, nColumn);
return CCellID(nRow, nColumn);
}
// This gets even partially visible cells
CCellRange CGridCtrl::GetVisibleNonFixedCellRange(LPRECT pRect /*=NULL*/)
{
CRect rect;
GetClientRect(rect);
CCellID idTopLeft = GetTopleftNonFixedCell();
// calc bottom
int bottom = GetFixedRowHeight();
for (int i = idTopLeft.row; i < GetRowCount(); i++)
{
bottom += GetRowHeight(i);
if (bottom >= rect.bottom) {
bottom = rect.bottom;
break;
}
}
int maxVisibleRow = min(i, GetRowCount() - 1);
// calc right
int right = GetFixedColumnWidth();
for (i = idTopLeft.col; i < GetColumnCount(); i++)
{
right += GetColumnWidth(i);
if (right >= rect.right) {
right = rect.right;
break;
}
}
int maxVisibleCol = min(i, GetColumnCount() - 1);
if (pRect) {
pRect->left = pRect->top = 0;
pRect->right = right;
pRect->bottom = bottom;
}
return CCellRange(idTopLeft.row, idTopLeft.col, maxVisibleRow, maxVisibleCol);
}
// used by ResetScrollBars() - This gets only fully visible cells
CCellRange CGridCtrl::GetUnobstructedNonFixedCellRange()
{
CRect rect;
GetClientRect(rect);
CCellID idTopLeft = GetTopleftNonFixedCell();
// calc bottom
int bottom = GetFixedRowHeight();
for (int i = idTopLeft.row; i < GetRowCount(); i++)
{
bottom += GetRowHeight(i);
if (bottom >= rect.bottom) break;
}
int maxVisibleRow = min(i, GetRowCount() - 1);
if (maxVisibleRow > 0 && bottom > rect.bottom) maxVisibleRow--;
// calc right
int right = GetFixedColumnWidth();
for (i = idTopLeft.col; i < GetColumnCount(); i++)
{
right += GetColumnWidth(i);
if (right >= rect.right) break;
}
int maxVisibleCol = min(i, GetColumnCount() - 1);
if (maxVisibleCol > 0 && right > rect.right) maxVisibleCol--;
return CCellRange(idTopLeft.row, idTopLeft.col, maxVisibleRow, maxVisibleCol);
}
// Returns the minimum bounding range of the current selection
// If no selection, then the returned CCellRange will be invalid
CCellRange CGridCtrl::GetSelectedCellRange()
{
CCellRange Selection(GetRowCount(), GetColumnCount(), -1,-1);
for (POSITION pos = m_SelectedCellMap.GetStartPosition(); pos != NULL; )
{
DWORD key;
CCellID cell;
m_SelectedCellMap.GetNextAssoc(pos, key, (CCellID&)cell);
Selection.SetMinRow( min(Selection.GetMinRow(), cell.row) );
Selection.SetMinCol( min(Selection.GetMinCol(), cell.col) );
Selection.SetMaxRow( max(Selection.GetMaxRow(), cell.row) );
Selection.SetMaxCol( max(Selection.GetMaxCol(), cell.col) );
}
return Selection;
}
// Returns ALL the cells in the grid
CCellRange CGridCtrl::GetCellRange()
{
return CCellRange(0, 0, GetRowCount() - 1, GetColumnCount() - 1);
}
void CGridCtrl::ResetSelectedRange()
{
SetSelectedRange(-1,-1,-1,-1);
}
// Get/Set scroll position using 32 bit functions
int CGridCtrl::GetGridScrollPos(int nBar)
{
SCROLLINFO si;
si.cbSize = sizeof(SCROLLINFO);
if (GetScrollInfo(nBar, &si, SIF_POS))
return si.nPos;
else
return 0;
}
BOOL CGridCtrl::SetGridScrollPos(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 CGridCtrl::ResetScrollBars()
{
if (!m_bAllowDraw || !::IsWindow(GetSafeHwnd())) return;
CRect rect;
GetClientRect(rect);
rect.left += GetFixedColumnWidth();
rect.top += GetFixedRowHeight();
if (rect.left >= rect.right || rect.top >= rect.bottom) return;
CRect VisibleRect(GetFixedColumnWidth(), GetFixedRowHeight(), rect.right, rect.bottom);
CRect VirtualRect(GetFixedColumnWidth(), GetFixedRowHeight(), GetVirtualWidth(), GetVirtualHeight());
CCellRange visibleCells = GetUnobstructedNonFixedCellRange();
if (!IsValid(visibleCells)) return;
SCROLLINFO si;
si.cbSize = sizeof(SCROLLINFO);
si.fMask = SIF_PAGE;
si.nPage = VisibleRect.Width(); SetScrollInfo(SB_HORZ, &si, FALSE);
si.nPage = VisibleRect.Height(); SetScrollInfo(SB_VERT, &si, FALSE);
if (VisibleRect.Height() < VirtualRect.Height())
m_nVScrollMax = VirtualRect.Height()-1; //+ GetRowHeight(visibleCells.GetTopLeft().row);
else
m_nVScrollMax = 0;
if (VisibleRect.Width() < VirtualRect.Width())
m_nHScrollMax = VirtualRect.Width()-1; //+ GetColumnWidth(visibleCells.GetTopLeft().col);
else
m_nHScrollMax = 0;
ASSERT(m_nVScrollMax < INT_MAX && m_nHScrollMax < INT_MAX); // This should be fine :)
SetScrollRange(SB_VERT, 0, m_nVScrollMax, TRUE);
SetScrollRange(SB_HORZ, 0, m_nHScrollMax, TRUE);
}
////////////////////////////////////////////////////////////////////////////////////
// Row/Column position functions
// returns the top left point of the cell. Returns FALSE if cell not visible.
BOOL CGridCtrl::GetCellOrigin(int nRow, int nCol, LPPOINT p)
{
int i;
if (!IsValid(nRow, nCol)) return FALSE;
CCellID idTopLeft;
if (nCol >= m_nFixedCols || nRow >= m_nFixedRows)
idTopLeft = GetTopleftNonFixedCell();
if ((nRow >= m_nFixedRows && nRow < idTopLeft.row) ||
(nCol>= m_nFixedCols && nCol < idTopLeft.col))
return FALSE;
p->x = 0;
if (nCol < m_nFixedCols) // is a fixed column
for (i = 0; i < nCol; i++)
p->x += GetColumnWidth(i);
else { // is a scrollable data column
for (i = 0; i < m_nFixedCols; i++)
p->x += GetColumnWidth(i);
for (i = idTopLeft.col; i < nCol; i++)
p->x += GetColumnWidth(i);
}
p->y = 0;
if (nRow < m_nFixedRows) // is a fixed row
for (i = 0; i < nRow; i++)
p->y += GetRowHeight(i);
else { // is a scrollable data row
for (i = 0; i < m_nFixedRows; i++)
p->y += GetRowHeight(i);
for (i = idTopLeft.row; i < nRow; i++)
p->y += GetRowHeight(i);
}
return TRUE;
}
BOOL CGridCtrl::GetCellOrigin(const CCellID& cell, LPPOINT p)
{
return GetCellOrigin(cell.row, cell.col, p);
}
// Returns the bounding box of the cell
BOOL CGridCtrl::GetCellRect(const CCellID& cell, LPRECT pRect)
{
return GetCellRect(cell.row, cell.col, pRect);
}
BOOL CGridCtrl::GetCellRect(int nRow, int nCol, LPRECT pRect)
{
CPoint CellOrigin;
if (!GetCellOrigin(nRow, nCol, &CellOrigin)) return FALSE;
pRect->left = CellOrigin.x;
pRect->top = CellOrigin.y;
pRect->right = CellOrigin.x + GetColumnWidth(nCol)-1;
pRect->bottom = CellOrigin.y + GetRowHeight(nRow)-1;
//TRACE("Row %d, col %d: L %d, T %d, W %d, H %d: %d,%d - %d,%d\n",
// nRow,nCol, CellOrigin.x, CellOrigin.y, GetColumnWidth(nCol), GetRowHeight(nRow),
// pRect->left, pRect->top, pRect->right, pRect->bottom);
return TRUE;
}
// Returns the bounding box of a range of cells
BOOL CGridCtrl::GetCellRangeRect(const CCellRange& cellRange, LPRECT lpRect)
{
CPoint MinOrigin,MaxOrigin;
if (!GetCellOrigin(cellRange.GetMinRow(), cellRange.GetMinCol(), &MinOrigin))
return FALSE;
if (!GetCellOrigin(cellRange.GetMaxRow(), cellRange.GetMaxCol(), &MaxOrigin))
return FALSE;
lpRect->left = MinOrigin.x;
lpRect->top = MinOrigin.y;
lpRect->right = MaxOrigin.x + GetColumnWidth(cellRange.GetMaxCol()-1);
lpRect->bottom = MaxOrigin.y + GetRowHeight(cellRange.GetMaxRow()-1);
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////////
// Grid attribute functions
LRESULT CGridCtrl::OnSetFont(WPARAM hFont, LPARAM /*lParam */)
{
LRESULT result = Default();
CFont *pFont = CFont::FromHandle((HFONT)hFont);
if (pFont) {
LOGFONT lf;
pFont->GetLogFont(&lf);
m_Font.DeleteObject();
m_Font.CreateFontIndirect(&lf);
}
// Get the font size and hence the default cell size
CDC* pDC = GetDC();
if (pDC) {
CFont* pOldFont = pDC->SelectObject(&m_Font);
TEXTMETRIC tm;
pDC->GetTextMetrics(&tm);
m_nMargin = pDC->GetTextExtent(_T(" "),1).cx;
pDC->SelectObject(pOldFont);
ReleaseDC(pDC);
m_nDefCellHeight = tm.tmHeight+tm.tmExternalLeading + 2*m_nMargin;
m_nDefCellWidth = tm.tmAveCharWidth*12 + 2*m_nMargin;
}
if (::IsWindow(GetSafeHwnd())) Invalidate();
return result;
}
LRESULT CGridCtrl::OnGetFont(WPARAM /*wParam*/, LPARAM /*lParam*/)
{
return (LRESULT) m_Font.m_hObject;
}
BOOL CGridCtrl::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
if (nHitTest == HTCLIENT)
{
switch (m_MouseMode)
{
case MOUSE_OVER_COL_DIVIDE: SetCursor(::LoadCursor(NULL, IDC_SIZEWE)); break;
case MOUSE_OVER_ROW_DIVIDE: SetCursor(::LoadCursor(NULL, IDC_SIZENS)); break;
case MOUSE_DRAGGING: brea
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -