📄 gridctrl.cpp.svn-base
字号:
// draw vertical lines (drawn at ends of cells)
if (m_nGridLines == GVL_BOTH || m_nGridLines == GVL_VERT)
{
int x = nFixedColWidth;
for (col = minVisibleCol; col <= maxVisibleCol; col++) {
x += GetColumnWidth(col);
pDC->MoveTo(x-1, nFixedRowHeight);
pDC->LineTo(x-1, VisRect.bottom);
}
}
// draw horizontal lines (drawn at bottom of each cell)
if (m_nGridLines == GVL_BOTH || m_nGridLines == GVL_HORZ)
{
int y = nFixedRowHeight;
for (row = minVisibleRow; row <= maxVisibleRow; row++) {
y += GetRowHeight(row);
pDC->MoveTo(nFixedColWidth, y-1);
pDC->LineTo(VisRect.right, y-1);
}
}
pDC->SelectStockObject(NULL_PEN);
#ifdef USE_MEMDC // Use a memDC for flicker free update
}
#else // Use normal DC - this helps in debugging
}
#endif
////////////////////////////////////////////////////////////////////////////////////////
// CGridCtrl Cell selection stuff
BOOL CGridCtrl::IsValid(int nRow, int nCol) const
{
return (nRow >= 0 && nRow < m_nRows && nCol >= 0 && nCol < m_nCols);
}
BOOL CGridCtrl::IsValid(const CCellID& cell) const
{
return IsValid(cell.row, cell.col);
}
BOOL CGridCtrl::IsValid(const CCellRange& range) const
{
return (range.GetMinRow() >= 0 && range.GetMinCol() >= 0 &&
range.GetMaxRow() >= 0 && range.GetMaxCol() >= 0 &&
range.GetMaxRow() < m_nRows && range.GetMaxCol() < m_nCols &&
range.GetMinRow() <= range.GetMaxRow() && range.GetMinCol() <= range.GetMaxCol());
}
// Enables/Disables redraw for certain operations like columns auto-sizing etc,
// but not for user caused things such as selection changes.
void CGridCtrl::SetRedraw(BOOL bAllowDraw, BOOL bResetScrollBars /* = FALSE */)
{
TRACE(_T("%s: Setting redraw to %s\n"),
GetRuntimeClass()->m_lpszClassName, bAllowDraw? _T("TRUE") : _T("FALSE"));
if (bAllowDraw && !m_bAllowDraw)
Invalidate();
m_bAllowDraw = bAllowDraw;
if (bResetScrollBars)
ResetScrollBars();
}
// Forces a redraw of a cell immediately (using a direct DC construction,
// or the supplied dc)
BOOL CGridCtrl::RedrawCell(const CCellID& cell, CDC* pDC /* = NULL */)
{
return RedrawCell(cell.row, cell.col, pDC);
}
BOOL CGridCtrl::RedrawCell(int nRow, int nCol, CDC* pDC /* = NULL */)
{
BOOL bResult = TRUE;
BOOL bMustReleaseDC = FALSE;
if (!m_bAllowDraw || !IsCellVisible(nRow, nCol))
return FALSE;
CRect rect;
if (!GetCellRect(nRow, nCol, rect))
return FALSE;
if (!pDC) {
pDC = GetDC();
if (pDC)
bMustReleaseDC = TRUE;
}
if (pDC)
{
// Redraw cells directly
if (nRow < m_nFixedRows || nCol < m_nFixedCols)
{
bResult = DrawFixedCell(pDC, nRow, nCol, rect, TRUE);
}
else
{
bResult = DrawCell(pDC, nRow, nCol, rect, TRUE);
// Since we have erased the background, we will need to redraw the gridlines
CPen pen;
TRY {
pen.CreatePen(PS_SOLID, 0, m_crGridColour);
} CATCH (CException, e) {e->Delete();} END_CATCH
CPen* pOldPen = (CPen*) pDC->SelectObject(&pen);
if (m_nGridLines == GVL_BOTH || m_nGridLines == GVL_HORZ)
{
pDC->MoveTo(rect.left, rect.bottom);
pDC->LineTo(rect.right+1, rect.bottom);
}
if (m_nGridLines == GVL_BOTH || m_nGridLines == GVL_VERT)
{
pDC->MoveTo(rect.right, rect.top);
pDC->LineTo(rect.right, rect.bottom+1);
}
pDC->SelectObject(pOldPen);
}
} else
InvalidateRect(rect, TRUE); // Could not get a DC - invalidate it anyway
// and hope that OnPaint manages to get one
if (bMustReleaseDC)
ReleaseDC(pDC);
return bResult;
}
// redraw a complete row
BOOL CGridCtrl::RedrawRow(int row)
{
BOOL bResult = TRUE;
CDC* pDC = GetDC();
for (int col = 0; col < GetColumnCount(); col++)
bResult = RedrawCell(row, col, pDC) && bResult;
if (pDC)
ReleaseDC(pDC);
return bResult;
}
// redraw a complete column
BOOL CGridCtrl::RedrawColumn(int col)
{
BOOL bResult = TRUE;
CDC* pDC = GetDC();
for (int row = 0; row < GetRowCount(); row++)
bResult = RedrawCell(row, col, pDC) && bResult;
if (pDC)
ReleaseDC(pDC);
return bResult;
}
// Sets the currently selected cell, returning the previous current cell
CCellID CGridCtrl::SetFocusCell(int nRow, int nCol)
{
return SetFocusCell(CCellID(nRow, nCol));
}
CCellID CGridCtrl::SetFocusCell(CCellID cell)
{
if (cell == m_idCurrentCell)
return m_idCurrentCell;
CCellID idPrev = m_idCurrentCell;
m_idCurrentCell = cell;
if (IsValid(idPrev))
{
SendMessageToParent(idPrev.row, idPrev.col, GVN_SELCHANGING);
SetItemState(idPrev.row, idPrev.col,
GetItemState(idPrev.row, idPrev.col) & ~GVIS_FOCUSED);
RedrawCell(idPrev);
if (idPrev.col != m_idCurrentCell.col)
for (int row = 0; row < m_nFixedRows; row++)
RedrawCell(row, idPrev.col);
if (idPrev.row != m_idCurrentCell.row)
for (int col = 0; col < m_nFixedCols; col++)
RedrawCell(idPrev.row, col);
}
if (IsValid(m_idCurrentCell)) {
SetItemState(m_idCurrentCell.row, m_idCurrentCell.col,
GetItemState(m_idCurrentCell.row, m_idCurrentCell.col) | GVIS_FOCUSED);
RedrawCell(m_idCurrentCell);
if (idPrev.col != m_idCurrentCell.col)
for (int row = 0; row < m_nFixedRows; row++)
RedrawCell(row, m_idCurrentCell.col);
if (idPrev.row != m_idCurrentCell.row)
for (int col = 0; col < m_nFixedCols; col++)
RedrawCell(m_idCurrentCell.row, col);
SendMessageToParent(m_idCurrentCell.row, m_idCurrentCell.col, GVN_SELCHANGED);
}
return idPrev;
}
// Sets the range of currently selected cells
void CGridCtrl::SetSelectedRange(const CCellRange& Range,
BOOL bForceRepaint /* = FALSE */)
{
SetSelectedRange(Range.GetMinRow(), Range.GetMinCol(),
Range.GetMaxRow(), Range.GetMaxCol(),
bForceRepaint);
}
void CGridCtrl::SetSelectedRange(int nMinRow, int nMinCol, int nMaxRow, int nMaxCol,
BOOL bForceRepaint /* = FALSE */)
{
if (!m_bEnableSelection) return;
CDC* pDC = NULL;
if (bForceRepaint) pDC = GetDC();
// Unselect all previously selected cells
for (POSITION pos = m_SelectedCellMap.GetStartPosition(); pos != NULL; )
{
DWORD key;
CCellID cell;
m_SelectedCellMap.GetNextAssoc(pos, key, (CCellID&)cell);
// Reset the selection flag on the cell
if (IsValid(cell)) {
SetItemState(cell.row, cell.col,
GetItemState(cell.row, cell.col) & ~GVIS_SELECTED);
// If this is to be reselected, continue on past the redraw
if (nMinRow <= cell.row && cell.row <= nMaxRow &&
nMinCol <= cell.col && cell.col <= nMaxCol)
continue;
if (bForceRepaint && pDC) // Redraw NOW
RedrawCell(cell.row, cell.col, pDC);
else
InvalidateCellRect(cell); // Redraw at leisure
}
}
// if any previous selected cells are to be retained (eg Ctrl is being held down)
// then copy them to the newly created list, and mark all these cells as
// selected
if (!GetSingleRowSelection())
for (POSITION pos = m_PrevSelectedCellMap.GetStartPosition(); pos != NULL; /* nothing */)
{
DWORD key;
CCellID cell;
m_PrevSelectedCellMap.GetNextAssoc(pos, key, (CCellID&)cell);
if (!IsValid(cell))
continue;
int nState = GetItemState(cell.row, cell.col);
// Set state as Selected. This will add the cell to m_SelectedCells[]
SetItemState(cell.row, cell.col, nState | GVIS_SELECTED);
// Redraw (immediately or at leisure)
if (bForceRepaint && pDC)
RedrawCell(cell.row, cell.col, pDC);
else
InvalidateCellRect(cell);
}
// Now select all cells in the cell range specified. If the cell has already
// been marked as selected (above) then ignore it.
if (nMinRow >= 0 && nMinCol >= 0 && nMaxRow >= 0 && nMaxCol >= 0 &&
nMaxRow < m_nRows && nMaxCol < m_nCols &&
nMinRow <= nMaxRow && nMinCol <= nMaxCol)
{
for (int row = nMinRow; row <= nMaxRow; row++)
for (int col = nMinCol; col <= nMaxCol; col++)
{
int nState = GetItemState(row, col);
if (nState & GVIS_SELECTED)
continue; // Already selected - ignore
// Add to list of selected cells
CCellID cell(row, col);
// Set state as Selected. This will add the cell to m_SelectedCells[]
SetItemState(row, col, nState | GVIS_SELECTED);
// Redraw (immediately or at leisure)
if (bForceRepaint && pDC)
RedrawCell(row, col, pDC);
else
InvalidateCellRect(cell);
}
}
// TRACE(_T("%d cells selected.\n"), m_SelectedCellMap.GetCount());
if (pDC != NULL)
ReleaseDC(pDC);
}
// selects all cells
void CGridCtrl::SelectAllCells()
{
if (!m_bEnableSelection)
return;
SetSelectedRange(m_nFixedRows, m_nFixedCols, GetRowCount()-1, GetColumnCount()-1);
}
// selects columns
void CGridCtrl::SelectColumns(CCellID currentCell)
{
if (!m_bEnableSelection)
return;
//if (currentCell.col == m_idCurrentCell.col) return;
if (currentCell.col < m_nFixedCols)
return;
if (!IsValid(currentCell))
return;
SetSelectedRange(GetFixedRowCount(),
min(m_SelectionStartCell.col, currentCell.col),
GetRowCount()-1,
max(m_SelectionStartCell.col, currentCell.col));
}
// selects rows
void CGridCtrl::SelectRows(CCellID currentCell)
{
if (!m_bEnableSelection)
return;
//if (currentCell.row; == m_idCurrentCell.row) return;
if (currentCell.row < m_nFixedRows)
return;
if (!IsValid(currentCell))
return;
if (GetListMode() && GetSingleRowSelection())
SetSelectedRange(currentCell.row, /*GetFixedColumnCount()*/0,
currentCell.row, GetColumnCount()-1);
else
SetSelectedRange(min(m_SelectionStartCell.row, currentCell.row),
/*GetFixedColumnCount()*/0,
max(m_SelectionStartCell.row, currentCell.row),
GetColumnCount()-1);
}
// selects cells
void CGridCtrl::SelectCells(CCellID currentCell)
{
if (!m_bEnableSelection)
return;
int row = currentCell.row;
int col = currentCell.col;
if (row < m_nFixedRows || col < m_nFixedCols)
return;
if (!IsValid(currentCell))
return;
// Prevent unnecessary redraws
//if (currentCell == m_LeftClickDownCell) return;
//else if (currentCell == m_idCurrentCell) return;
SetSelectedRange(min(m_SelectionStartCell.row, row),
min(m_SelectionStartCell.col, col),
max(m_SelectionStartCell.row, row),
max(m_SelectionStartCell.col, col));
}
void CGridCtrl::OnSelecting(const CCellID& currentCell)
{
if (!m_bEnableSelection)
return;
switch(m_MouseMode)
{
case MOUSE_SELECT_ALL: SelectAllCells(); break;
case MOUSE_SELECT_COL: SelectColumns(currentCell); break;
case MOUSE_SELECT_ROW: SelectRows(currentCell); break;
case MOUSE_SELECT_CELLS: SelectCells(currentCell); break;
}
}
#ifndef GRIDCONTROL_NO_CLIPBOARD
////////////////////////////////////////////////////////////////////////////////////////
// Clipboard functions
void CGridCtrl::CutSelectedText()
{
if (!IsEditable())
return;
// Clear contents of selected cells.
for (POSITION pos = m_SelectedCellMap.GetStartPosition(); pos != NULL; )
{
DWORD key;
CCellID cell;
m_SelectedCellMap.GetNextAssoc(pos, key, (CCellID&)cell);
if (!IsCellEditable(cell))
continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -