📄 gridctrl.cpp
字号:
{
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
for (pos = m_PrevSelectedCellMap.GetStartPosition(); pos != NULL; )
{
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;
SetSelectedRange(min(m_SelectionStartCell.row, currentCell.row), GetFixedColumnCount(),
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;
}
}
////////////////////////////////////////////////////////////////////////////////////////
// Clipboard functions
void CGridCtrl::CutSelectedText()
{
// Clear contents of selected cells.
for (POSITION pos = m_SelectedCellMap.GetStartPosition(); pos != NULL; )
{
DWORD key;
CCellID cell;
m_SelectedCellMap.GetNextAssoc(pos, key, (CCellID&)cell);
CGridCell* pCell = GetCell(cell.row, cell.col);
if (pCell) EmptyCell(pCell, cell.row, cell.col);
}
Invalidate();
}
COleDataSource* CGridCtrl::CopyTextFromGrid()
{
CCellRange Selection = GetSelectedCellRange();
if (!IsValid(Selection)) return NULL;
// Get a tab delimited string to copy to cache
CString str;
for (int row = Selection.GetMinRow(); row <= Selection.GetMaxRow(); row++)
{
for (int col = Selection.GetMinCol(); col <= Selection.GetMaxCol(); col++)
{
if (GetItemState(row,col) & GVIS_SELECTED) str += GetItemText(row,col);
if (col != Selection.GetMaxCol()) str += _T("\t");
}
if (row != Selection.GetMaxRow()) str += _T("\r\n");
}
// Write to shared file
CSharedFile sf(GMEM_MOVEABLE|GMEM_DDESHARE|GMEM_ZEROINIT);
sf.Write(str, str.GetLength());
HGLOBAL hMem = sf.Detach();
if (!hMem) return NULL;
// Cache data
COleDataSource* pSource = new COleDataSource();
pSource->CacheGlobalData(CF_TEXT, hMem);
return pSource;
}
BOOL CGridCtrl::PasteTextToGrid(CCellID cell, COleDataObject* pDataObject)
{
if (!pDataObject->IsDataAvailable(CF_TEXT) || !IsValid(cell))
return FALSE;
// Get the text from the COleDataObject
HGLOBAL hmem = pDataObject->GetGlobalData(CF_TEXT);
CMemFile sf((BYTE*) ::GlobalLock(hmem), ::GlobalSize(hmem));
CString strText;
LPTSTR szBuffer;
try {
szBuffer = strText.GetBufferSetLength(::GlobalSize(hmem));
}
catch (CMemoryException* ex) {
ex->ReportError();
ex->Delete();
return FALSE;
}
sf.Read(szBuffer, ::GlobalSize(hmem));
::GlobalUnlock(hmem);
strText.ReleaseBuffer();
// Parse text data and set in cells...
strText.LockBuffer();
CString strLine = strText;
int nLine = 0;
// Find the end of the first line
int nIndex;
do {
int nColumn = 0;
nIndex = strLine.Find(_T("\r\n"));
// Store the remaining chars after the newline
CString strNext = (nIndex < 0)? _T("") : strLine.Mid(nIndex+1);
// Remove all chars after the newline
if (nIndex >= 0) strLine = strLine.Left(nIndex);
LPTSTR szLine = strLine.GetBuffer(1);
// Break the current line into tokens (tab or comma delimited)
LPTSTR pszCellText = _tcstok(szLine, _T("\t,\n"));
while (pszCellText != NULL)
{
SetItemText(cell.row + nLine, cell.col + nColumn, pszCellText);
pszCellText = _tcstok(NULL, _T("\t,\n"));
nColumn++;
}
strLine.ReleaseBuffer();
strLine = strNext;
nLine++;
} while (nIndex >= 0);
strText.UnlockBuffer();
Invalidate();
return TRUE;
}
void CGridCtrl::OnBeginDrag()
{
if (!m_bAllowDragAndDrop) return;
COleDataSource* pSource = CopyTextFromGrid();
if (pSource)
{
m_MouseMode = MOUSE_DRAGGING;
DROPEFFECT dropEffect = pSource->DoDragDrop(DROPEFFECT_COPY|DROPEFFECT_MOVE);
if (dropEffect & DROPEFFECT_MOVE)
CutSelectedText();
if (pSource) delete pSource; // Did not pass source to clipboard, so must delete
}
}
DROPEFFECT CGridCtrl::OnDragOver(COleDataObject* pDataObject, DWORD dwKeyState,
CPoint point)
{
// Any text data available for us?
if (!m_bAllowDragAndDrop || !pDataObject->IsDataAvailable(CF_TEXT))
return DROPEFFECT_NONE;
// Find which cell we are over and drop-highlight it
CCellID cell = GetCellFromPt(point, FALSE);
// If not valid, Set the previously drop-highlighted cell as no longer drop-highlighted
if (!IsValid(cell))
{
OnDragLeave();
m_LastDragOverCell = CCellID(-1,-1);
return DROPEFFECT_NONE;
}
// Have we moved over a different cell than last time?
if (cell != m_LastDragOverCell)
{
// Set the previously drop-highlighted cell as no longer drop-highlighted
if (IsValid(m_LastDragOverCell)) {
UINT nState = GetItemState(m_LastDragOverCell.row, m_LastDragOverCell.col);
SetItemState(m_LastDragOverCell.row, m_LastDragOverCell.col,
nState & ~GVIS_DROPHILITED);
RedrawCell(m_LastDragOverCell);
}
m_LastDragOverCell = cell;
// Set the new cell as drop-highlighted
if (IsValid(m_LastDragOverCell)) {
UINT nState = GetItemState(m_LastDragOverCell.row, m_LastDragOverCell.col);
SetItemState(m_LastDragOverCell.row, m_LastDragOverCell.col,
nState | GVIS_DROPHILITED);
RedrawCell(m_LastDragOverCell);
}
}
// Return an appropraite value of DROPEFFECT so mouse cursor is set properly
if (dwKeyState & MK_CONTROL)
return DROPEFFECT_COPY;
else
return DROPEFFECT_MOVE;
}
DROPEFFECT CGridCtrl::OnDragEnter(COleDataObject* pDataObject, DWORD dwKeyState,
CPoint point)
{
// Any text data available for us?
if (!m_bAllowDragAndDrop || !pDataObject->IsDataAvailable(CF_TEXT))
return DROPEFFECT_NONE;
// Find which cell we are over and drop-highlight it
m_LastDragOverCell = GetCellFromPt(point, FALSE);
if (!IsValid(m_LastDragOverCell))
return DROPEFFECT_NONE;
if (IsValid(m_LastDragOverCell))
{
UINT nState = GetItemState(m_LastDragOverCell.row, m_LastDragOverCell.col);
SetItemState(m_LastDragOverCell.row, m_LastDragOverCell.col,
nState | GVIS_DROPHILITED);
RedrawCell(m_LastDragOverCell);
}
// Return an appropraite value of DROPEFFECT so mouse cursor is set properly
if (dwKeyState & MK_CONTROL)
return DROPEFFECT_COPY;
else
return DROPEFFECT_MOVE;
}
void CGridCtrl::OnDragLeave()
{
// Set the previously drop-highlighted cell as no longer drop-highlighted
if (IsValid(m_LastDragOverCell)) {
UINT nState = GetItemState(m_LastDragOverCell.row, m_LastDragOverCell.col);
SetItemState(m_LastDragOverCell.row, m_LastDragOverCell.col,
nState & ~GVIS_DROPHILITED);
RedrawCell(m_LastDragOverCell);
}
}
BOOL CGridCtrl::OnDrop(COleDataObject* pDataObject, DROPEFFECT /*dropEffect*/,
CPoint /* point */)
{
if (!m_bAllowDragAndDrop) return FALSE;
m_MouseMode = MOUSE_NOTHING;
OnDragLeave();
return PasteTextToGrid(m_LastDragOverCell, pDataObject);
}
void CGridCtrl::OnEditCut()
{
COleDataSource* pSource = CopyTextFromGrid();
if (!pSource) return;
pSource->SetClipboard();
CutSelectedText();
}
void CGridCtrl::OnEditCopy()
{
COleDataSource* pSource = CopyTextFromGrid();
if (!pSource) return;
pSource->SetClipboard();
}
void CGridCtrl::OnEditPaste()
{
// Get the Focus cell, or if none, get the topleft (non-fixed) cell
CCellID cell = GetFocusCell();
if (!IsValid(cell)) cell = GetTopleftNonFixedCell();
if (!IsValid(cell)) return;
// Attach a COleDataObject to the clipboard and paste the data to the grid
COleDataObject obj;
if (obj.AttachClipboard())
PasteTextToGrid(cell, &obj);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -