- int startCol = nCols - addedCols;
- for (int col = startCol; col < nCols; col++)
- m_arColWidths[col] = m_cellFixedColDef.GetWidth();
- // initialise column data
- if (!GetVirtualMode())
- {
- for (int row = 0; row < m_nRows; row++)
- for (col = startCol; col < nCols; col++)
- {
- GRID_ROW* pRow = m_RowData[row];
- if (pRow)
- pRow->SetAt(col, CreateCell(row, col));
- }
- }
- }
- // else // check for selected cell ranges
- // ResetSelectedRange();
- }
- CATCH (CMemoryException, e)
- {
- e->ReportError();
- bResult = FALSE;
- }
- END_CATCH
- m_nCols = nCols;
- SetModified();
- ResetScrollBars();
- Refresh();
- return bResult;
- }
- // Insert a column at a given position, or add to end of columns (if nColumn = -1)
- int CGridCtrl::InsertColumn(LPCTSTR strHeading,
- UINT nFormat /* = DT_CENTER|DT_VCENTER|DT_SINGLELINE */,
- int nColumn /* = -1 */)
- {
- if (nColumn >= 0 && nColumn < m_nFixedCols)
- {
- // TODO: Fix it so column insertion works for in the fixed column area
- ASSERT(FALSE);
- return -1;
- }
- // If the insertion is for a specific column, check it's within range.
- if (nColumn >= 0 && nColumn > GetColumnCount())
- return -1;
- // Force recalculation
- m_idTopLeftCell.col = -1;
- ResetSelectedRange();
- // Gotta be able to at least _see_ some of the column.
- if (m_nRows < 1)
- SetRowCount(1);
- // Allow the user to insert after the last of the columns, but process it as a
- // "-1" column, meaning it gets flaged as being the last column, and not a regular
- // "insert" routine.
- if (nColumn == GetColumnCount())
- nColumn = -1;
- TRY
- {
- if (nColumn < 0)
- {
- nColumn = m_nCols;
- m_arColWidths.Add(0);
- if (!GetVirtualMode())
- {
- for (int row = 0; row < m_nRows; row++)
- {
- GRID_ROW* pRow = m_RowData[row];
- if (!pRow)
- return -1;
- pRow->Add(CreateCell(row, nColumn));
- }
- }
- }
- else
- {
- m_arColWidths.InsertAt(nColumn, (int)0);
- if (!GetVirtualMode())
- {
- for (int row = 0; row < m_nRows; row++)
- {
- GRID_ROW* pRow = m_RowData[row];
- if (!pRow)
- return -1;
- pRow->InsertAt(nColumn, CreateCell(row, nColumn));
- }
- }
- }
- }
- CATCH (CMemoryException, e)
- {
- e->ReportError();
- return FALSE;
- }
- END_CATCH
- m_nCols++;
- // Initialise column data
- SetItemText(0, nColumn, strHeading);
- for (int row = 0; row < m_nRows; row++)
- SetItemFormat(row, nColumn, nFormat);
- // initialized column width
- m_arColWidths[nColumn] = GetTextExtent(0, nColumn, strHeading).cx;
- if (m_idCurrentCell.col != -1 && nColumn < m_idCurrentCell.col)
- m_idCurrentCell.col++;
- ResetScrollBars();
- SetModified();
- return nColumn;
- }
- // Insert a row at a given position, or add to end of rows (if nRow = -1)
- int CGridCtrl::InsertRow(LPCTSTR strHeading, int nRow /* = -1 */)
- {
- if (nRow >= 0 && nRow < m_nFixedRows)
- {
- // TODO: Fix it so column insertion works for in the fixed row area
- ASSERT(FALSE);
- return -1;
- }
- // If the insertion is for a specific row, check it's within range.
- if (nRow >= 0 && nRow >= GetRowCount())
- return -1;
- // Force recalculation
- m_idTopLeftCell.col = -1;
- ResetSelectedRange();
- // Gotta be able to at least _see_ some of the row.
- if (m_nCols < 1)
- SetColumnCount(1);
- TRY
- {
- // Adding a row to the bottom
- if (nRow < 0)
- {
- nRow = m_nRows;
- m_arRowHeights.Add(0);
- if (!GetVirtualMode())
- m_RowData.Add(new GRID_ROW);
- }
- else
- {
- m_arRowHeights.InsertAt(nRow, (int)0);
- if (!GetVirtualMode())
- m_RowData.InsertAt(nRow, new GRID_ROW);
- }
- if (!GetVirtualMode())
- m_RowData[nRow]->SetSize(m_nCols);
- }
- CATCH (CMemoryException, e)
- {
- e->ReportError();
- return FALSE;
- }
- END_CATCH
- m_nRows++;
- // Initialise cell data
- if (!GetVirtualMode())
- {
- for (int col = 0; col < m_nCols; col++)
- {
- GRID_ROW* pRow = m_RowData[nRow];
- if (!pRow)
- return -1;
- pRow->SetAt(col, CreateCell(nRow, col));
- }
- }
- // Set row title
- SetItemText(nRow, 0, strHeading);
- // initialized row height
- if (strHeading && strHeading[0])
- m_arRowHeights[nRow] = GetTextExtent(nRow, 0, strHeading).cy;
- else
- m_arRowHeights[nRow] = m_cellFixedRowDef.GetHeight();
- if (m_idCurrentCell.row != -1 && nRow < m_idCurrentCell.row)
- m_idCurrentCell.row++;
- ResetScrollBars();
- SetModified();
- return nRow;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // Cell creation stuff
- BOOL CGridCtrl::SetCellType(int nRow, int nCol, CRuntimeClass* pRuntimeClass)
- {
- if (GetVirtualMode())
- return FALSE;
- ASSERT(IsValid(nRow, nCol));
- if (!IsValid(nRow, nCol))
- return FALSE;
- if (!pRuntimeClass->IsDerivedFrom(RUNTIME_CLASS(CGridCellBase)))
- {
- ASSERT( FALSE);
- return FALSE;
- }
- CGridCellBase* pNewCell = (CGridCellBase*) pRuntimeClass->CreateObject();
- CGridCellBase* pCurrCell = GetCell(nRow, nCol);
- if (pCurrCell)
- *pNewCell = *pCurrCell;
- SetCell(nRow, nCol, pNewCell);
- delete pCurrCell;
- return TRUE;
- }
- BOOL CGridCtrl::SetDefaultCellType( CRuntimeClass* pRuntimeClass)
- {
- ASSERT( pRuntimeClass != NULL );
- if (!pRuntimeClass->IsDerivedFrom(RUNTIME_CLASS(CGridCellBase)))
- {
- ASSERT( FALSE);
- return FALSE;
- }
- m_pRtcDefault = pRuntimeClass;
- return TRUE;
- }
- // Creates a new grid cell and performs any necessary initialisation
- /*virtual*/ CGridCellBase* CGridCtrl::CreateCell(int nRow, int nCol)
- {
- ASSERT(!GetVirtualMode());
- if (!m_pRtcDefault || !m_pRtcDefault->IsDerivedFrom(RUNTIME_CLASS(CGridCellBase)))
- {
- ASSERT( FALSE);
- return NULL;
- }
- CGridCellBase* pCell = (CGridCellBase*) m_pRtcDefault->CreateObject();
- if (!pCell)
- return NULL;
- pCell->SetGrid(this);
- pCell->SetCoords(nRow, nCol);
- // Make format same as cell above
- if (nRow > 0 && nCol >= 0 && nCol < m_nCols)
- pCell->SetFormat(GetItemFormat(nRow - 1, nCol));
- if (nCol < m_nFixedCols)
- pCell->SetState(pCell->GetState() | GVIS_FIXED | GVIS_FIXEDCOL);
- if (nRow < m_nFixedRows)
- pCell->SetState(pCell->GetState() | GVIS_FIXED | GVIS_FIXEDROW);
- return pCell;
- }
- // Performs any cell cleanup necessary to maintain grid integrity
- /*virtual*/ void CGridCtrl::DestroyCell(int nRow, int nCol)
- {
- // Should NEVER get here in virtual mode.
- ASSERT(!GetVirtualMode());
- // Set the cells state to 0. If the cell is selected, this
- // will remove the cell from the selected list.
- SetItemState(nRow, nCol, 0);
- delete GetCell(nRow, nCol);
- }
- BOOL CGridCtrl::DeleteColumn(int nColumn)
- {
- if (nColumn < 0 || nColumn >= GetColumnCount())
- return FALSE;
- ResetSelectedRange();
- if (!GetVirtualMode())
- {
- for (int row = 0; row < GetRowCount(); row++)
- {
- GRID_ROW* pRow = m_RowData[row];
- if (!pRow)
- return FALSE;
- DestroyCell(row, nColumn);
- pRow->RemoveAt(nColumn);
- }
- }
- m_arColWidths.RemoveAt(nColumn);
- m_nCols--;
- if (nColumn < m_nFixedCols)
- m_nFixedCols--;
- if (nColumn == m_idCurrentCell.col)
- m_idCurrentCell.row = m_idCurrentCell.col = -1;
- else if (nColumn < m_idCurrentCell.col)
- m_idCurrentCell.col--;
- ResetScrollBars();
- SetModified();
- return TRUE;
- }
- BOOL CGridCtrl::DeleteRow(int nRow)
- {
- if (nRow < 0 || nRow >= GetRowCount())
- return FALSE;
- ResetSelectedRange();
- if (!GetVirtualMode())
- {
- GRID_ROW* pRow = m_RowData[nRow];
- if (!pRow)
- return FALSE;
- for (int col = 0; col < GetColumnCount(); col++)
- DestroyCell(nRow, col);
- delete pRow;
- m_RowData.RemoveAt(nRow);
- }
- m_arRowHeights.RemoveAt(nRow);
- m_nRows--;
- if (nRow < m_nFixedRows)
- m_nFixedRows--;
- if (nRow == m_idCurrentCell.row)
- m_idCurrentCell.row = m_idCurrentCell.col = -1;
- else if (nRow < m_idCurrentCell.row)
- m_idCurrentCell.row--;
- ResetScrollBars();
- SetModified();
- return TRUE;
- }
- // Handy function that removes all non-fixed rows
- BOOL CGridCtrl::DeleteNonFixedRows()
- {
- ResetSelectedRange();
- int nFixed = GetFixedRowCount();
- int nCount = GetRowCount();
- // Delete all data rows
- for (int nRow = nCount; nRow >= nFixed; nRow--)
- DeleteRow(nRow);
- return TRUE;
- }
- // Removes all rows, columns and data from the grid.
- BOOL CGridCtrl::DeleteAllItems()
- {
- ResetSelectedRange();
- m_arColWidths.RemoveAll();
- m_arRowHeights.RemoveAll();
- // Delete all cells in the grid
- if (!GetVirtualMode())
- {
- for (int row = 0; row < m_nRows; row++)
- {
- for (int col = 0; col < m_nCols; col++)
- DestroyCell(row, col);
- GRID_ROW* pRow = m_RowData[row];
- delete pRow;
- }
- // Remove all rows
- m_RowData.RemoveAll();
- }
- m_idCurrentCell.row = m_idCurrentCell.col = -1;
- m_nRows = m_nFixedRows = m_nCols = m_nFixedCols = 0;
- ResetScrollBars();
- SetModified();
- return TRUE;
- }
- void CGridCtrl::AutoFill()
- {
- if (!::IsWindow(m_hWnd))
- return;
- CRect rect;
- GetClientRect(rect);
- SetColumnCount(rect.Width() / m_cellDefault.GetWidth() + 1);
- SetRowCount(rect.Height() / m_cellDefault.GetHeight() + 1);
- SetFixedRowCount(1);
- SetFixedColumnCount(1);
- ExpandToFit();
- }
- /////////////////////////////////////////////////////////////////////////////
- // CGridCtrl data functions
- // Set CListCtrl::GetNextItem for details
- CCellID CGridCtrl::GetNextItem(CCellID& cell, int nFlags) const
- {
- if ((nFlags & GVNI_ALL) == GVNI_ALL)
- { // GVNI_ALL Search whole Grid beginning from cell
- // First row (cell.row) -- ONLY Columns to the right of cell
- // following rows -- ALL Columns
- int row = cell.row , col = cell.col + 1;
- if (row <= 0)
- row = GetFixedRowCount();
- for (; row < GetRowCount(); row++)
- {
- if (col <= 0)
- col = GetFixedColumnCount();
- for (; col < GetColumnCount(); col++)
- {
- int nState = GetItemState(row, col);
- if ((nFlags & GVNI_DROPHILITED && nState & GVIS_DROPHILITED) ||
- (nFlags & GVNI_FOCUSED && nState & GVIS_FOCUSED) ||
- (nFlags & GVNI_SELECTED && nState & GVIS_SELECTED) ||
- (nFlags & GVNI_READONLY && nState & GVIS_READONLY) ||
- (nFlags & GVNI_FIXED && nState & GVIS_FIXED) ||
- (nFlags & GVNI_MODIFIED && nState & GVIS_MODIFIED))
- return CCellID(row, col);
- }
- // go to First Column
- col = GetFixedColumnCount();
- }
- }
- else if ((nFlags & GVNI_BELOW) == GVNI_BELOW &&
- (nFlags & GVNI_TORIGHT) == GVNI_TORIGHT)
- { // GVNI_AREA Search Grid beginning from cell to Lower-Right of Grid
- // Only rows starting with cell.row and below
- // All rows -- ONLY Columns to the right of cell
- int row = cell.row;
- if (row <= 0)
- row = GetFixedRowCount();
- for (; row < GetRowCount(); row++)
- {
- int col = cell.col + 1;
- if (col <= 0)
- col = GetFixedColumnCount();
- for (; col < GetColumnCount(); col++)
- {
- int nState = GetItemState(row, col);
- if ((nFlags & GVNI_DROPHILITED && nState & GVIS_DROPHILITED) ||
- (nFlags & GVNI_FOCUSED && nState & GVIS_FOCUSED) ||
- (nFlags & GVNI_SELECTED && nState & GVIS_SELECTED) ||
- (nFlags & GVNI_READONLY && nState & GVIS_READONLY) ||
- (nFlags & GVNI_FIXED && nState & GVIS_FIXED) ||
- (nFlags & GVNI_MODIFIED && nState & GVIS_MODIFIED))
- return CCellID(row, col);
- }
- }
- }
- else if ((nFlags & GVNI_ABOVE) == GVNI_ABOVE)
- {
- for (int row = cell.row - 1; row >= GetFixedRowCount(); row--)
- {
- int nState = GetItemState(row, cell.col);
- if ((nFlags & GVNI_DROPHILITED && nState & GVIS_DROPHILITED) ||
- (nFlags & GVNI_FOCUSED && nState & GVIS_FOCUSED) ||
- (nFlags & GVNI_SELECTED && nState & GVIS_SELECTED) ||
- (nFlags & GVNI_READONLY && nState & GVIS_READONLY) ||
- (nFlags & GVNI_FIXED && nState & GVIS_FIXED) ||
- (nFlags & GVNI_MODIFIED && nState & GVIS_MODIFIED))
- return CCellID(row, cell.col);
- }
- }
- else if ((nFlags & GVNI_BELOW) == GVNI_BELOW)
- {
- for (int row = cell.row + 1; row < GetRowCount(); row++)
- {
- int nState = GetItemState(row, cell.col);
- if ((nFlags & GVNI_DROPHILITED && nState & GVIS_DROPHILITED) ||
- (nFlags & GVNI_FOCUSED && nState & GVIS_FOCUSED) ||
- (nFlags & GVNI_SELECTED && nState & GVIS_SELECTED) ||
- (nFlags & GVNI_READONLY && nState & GVIS_READONLY) ||
- (nFlags & GVNI_FIXED && nState & GVIS_FIXED) ||
- (nFlags & GVNI_MODIFIED && nState & GVIS_MODIFIED))
- return CCellID(row, cell.col);
- }
- }
- else if ((nFlags & GVNI_TOLEFT) == GVNI_TOLEFT)
- {
- for (int col = cell.col - 1; col >= GetFixedColumnCount(); col--)
- {
- int nState = GetItemState(cell.row, col);
- if ((nFlags & GVNI_DROPHILITED && nState & GVIS_DROPHILITED) ||
- (nFlags & GVNI_FOCUSED && nState & GVIS_FOCUSED) ||
- (nFlags & GVNI_SELECTED && nState & GVIS_SELECTED) ||
- (nFlags & GVNI_READONLY && nState & GVIS_READONLY) ||
- (nFlags & GVNI_FIXED && nState & GVIS_FIXED) ||
- (nFlags & GVNI_MODIFIED && nState & GVIS_MODIFIED))
- return CCellID(cell.row, col);
- }
- }
- else if ((nFlags & GVNI_TORIGHT) == GVNI_TORIGHT)
- {
- for (int col = cell.col + 1; col < GetColumnCount(); col++)
- {
- int nState = GetItemState(cell.row, col);
- if ((nFlags & GVNI_DROPHILITED && nState & GVIS_DROPHILITED) ||
- (nFlags & GVNI_FOCUSED && nState & GVIS_FOCUSED) ||
- (nFlags & GVNI_SELECTED && nState & GVIS_SELECTED) ||
- (nFlags & GVNI_READONLY && nState & GVIS_READONLY) ||
- (nFlags & GVNI_FIXED && nState & GVIS_FIXED) ||
- (nFlags & GVNI_MODIFIED && nState & GVIS_MODIFIED))
- return CCellID(cell.row, col);
- }
- }
- return CCellID(-1, -1);
- }
- // Sorts on a given column using the cell text
- BOOL CGridCtrl::SortTextItems(int nCol, BOOL bAscending)
- {
- SetSortColumn(nCol);
- SetSortAscending(bAscending);
- ResetSelectedRange();
- SetFocusCell(-1, - 1);
- return SortTextItems(nCol, bAscending, GetFixedRowCount(), - 1);
- }
- // recursive sort implementation
- BOOL CGridCtrl::SortTextItems(int nCol, BOOL bAscending, int low, int high)
- {
- if (nCol >= GetColumnCount())
- return FALSE;
- if (high == -1)
- high = GetRowCount() - 1;
- int lo = low;
- int hi = high;
- if (hi <= lo)
- return FALSE;
- CString midItem = GetItemText((lo + hi)/2, nCol);
- // loop through the list until indices cross
- while (lo <= hi)
- {
- // Find the first element that is greater than or equal to the partition
- // element starting from the left Index.
- if (bAscending)
- while (lo < high && GetItemText(lo, nCol) < midItem)
- ++lo;
- else
- while (lo < high && GetItemText(lo, nCol) > midItem)
- ++lo;
- // Find an element that is smaller than or equal to the partition
- // element starting from the right Index.
- if (bAscending)
- while (hi > low && GetItemText(hi, nCol) > midItem)
- --hi;
- else
- while (hi > low && GetItemText(hi, nCol) < midItem)
- --hi;
- // If the indexes have not crossed, swap if the items are not equal
- if (lo <= hi)
- {
- // swap only if the items are not equal
- if (GetItemText(lo, nCol) != GetItemText(hi, nCol))
- {
- for (int col = 0; col < GetColumnCount(); col++)
- {
- CGridCellBase *pCell = GetCell(lo, col);
- SetCell(lo, col, GetCell(hi, col));
- SetCell(hi, col, pCell);
- }
- UINT nRowHeight = m_arRowHeights[lo];
- m_arRowHeights[lo] = m_arRowHeights[hi];
- m_arRowHeights[hi] = nRowHeight;
- }
- ++lo;
- --hi;
- }
- }
- // If the right index has not reached the left side of array
- // must now sort the left partition.
- if (low < hi)
- SortTextItems(nCol, bAscending, low, hi);
- // If the left index has not reached the right side of array
- // must now sort the right partition.
- if (lo < high)
- SortTextItems(nCol, bAscending, lo, high);
- return TRUE;
- }
- // Sorts on a given column using the supplied compare function (see CListCtrl::SortItems)
- BOOL CGridCtrl::SortItems(PFNLVCOMPARE pfnCompare, int nCol, BOOL bAscending,
- LPARAM data /* = 0 */)
- {
- SetSortColumn(nCol);
- SetSortAscending(bAscending);
- ResetSelectedRange();
- SetFocusCell(-1, - 1);
- return SortItems(pfnCompare, nCol, bAscending, data, GetFixedRowCount(), -1);
- }
- // recursive sort implementation
- BOOL CGridCtrl::SortItems(PFNLVCOMPARE pfnCompare, int nCol, BOOL bAscending, LPARAM data,
- int low, int high)
- {
- if (nCol >= GetColumnCount())
- return FALSE;
- if (high == -1)
- high = GetRowCount() - 1;
- int lo = low;
- int hi = high;
- if (hi <= lo)
- return FALSE;
- LPARAM midItem = GetItemData((lo + hi)/2, nCol);
- // loop through the list until indices cross
- while (lo <= hi)
- {
- // Find the first element that is greater than or equal to the partition
- // element starting from the left Index.
- if (bAscending)
- while (lo < high && pfnCompare(GetItemData(lo, nCol), midItem, data) < 0)
- ++lo;
- else
- while (lo < high && pfnCompare(GetItemData(lo, nCol), midItem, data) > 0)
- ++lo;
- // Find an element that is smaller than or equal to the partition
- // element starting from the right Index.
- if (bAscending)
- while (hi > low && pfnCompare(GetItemData(hi, nCol), midItem, data) > 0)
- --hi;
- else
- while (hi > low && pfnCompare(GetItemData(hi, nCol), midItem, data) < 0)
- --hi;
- // If the indexes have not crossed, swap if the items are not equal
- if (lo <= hi)
- {
- // swap only if the items are not equal
- if (pfnCompare(GetItemData(lo, nCol), GetItemData(hi, nCol), data) != 0)
- {
- for (int col = 0; col < GetColumnCount(); col++)
- {
- CGridCellBase *pCell = GetCell(lo, col);
- SetCell(lo, col, GetCell(hi, col));
- SetCell(hi, col, pCell);
- }
- UINT nRowHeight = m_arRowHeights[lo];
- m_arRowHeights[lo] = m_arRowHeights[hi];
- m_arRowHeights[hi] = nRowHeight;
- }
- ++lo;
- --hi;
- }
- }
- // If the right index has not reached the left side of array
- // must now sort the left partition.
- if (low < hi)
- SortItems(pfnCompare, nCol, bAscending, data, low, hi);
- // If the left index has not reached the right side of array
- // must now sort the right partition.
- if (lo < high)
- SortItems(pfnCompare, nCol, bAscending, data, lo, high);
- return TRUE;
- }
- /////////////////////////////////////////////////////////////////////////////
- // CGridCtrl data functions
- BOOL CGridCtrl::SetItem(const GV_ITEM* pItem)
- {
- if (!pItem || GetVirtualMode())
- return FALSE;
- CGridCellBase* pCell = GetCell(pItem->row, pItem->col);
- if (!pCell)
- return FALSE;
- SetModified(pItem->row, pItem->col);
- if (pItem->mask & GVIF_TEXT)
- pCell->SetText(pItem->strText);
- if (pItem->mask & GVIF_PARAM)
- pCell->SetData(pItem->lParam);
- if (pItem->mask & GVIF_IMAGE)
- pCell->SetImage(pItem->iImage);
- if (pItem->mask & GVIF_STATE)
- pCell->SetState(pItem->nState);
- if (pItem->mask & GVIF_FORMAT)
- pCell->SetFormat(pItem->nFormat);
- if (pItem->mask & GVIF_BKCLR)
- pCell->SetBackClr(pItem->crBkClr);
- if (pItem->mask & GVIF_FGCLR)
- pCell->SetTextClr(pItem->crFgClr);
- if (pItem->mask & GVIF_FONT)
- pCell->SetFont(&(pItem->lfFont));
- if( pItem->mask & GVIF_MARGIN)
- pCell->SetMargin( pItem->nMargin);
- return TRUE;
- }
- BOOL CGridCtrl::GetItem(GV_ITEM* pItem)
- {
- if (!pItem)
- return FALSE;
- CGridCellBase* pCell = GetCell(pItem->row, pItem->col);
- if (!pCell)
- return FALSE;
- if (pItem->mask & GVIF_TEXT)
- pItem->strText = GetItemText(pItem->row, pItem->col);
- if (pItem->mask & GVIF_PARAM)
- pItem->lParam = pCell->GetData();;
- if (pItem->mask & GVIF_IMAGE)
- pItem->iImage = pCell->GetImage();
- if (pItem->mask & GVIF_STATE)
- pItem->nState = pCell->GetState();
- if (pItem->mask & GVIF_FORMAT)
- pItem->nFormat = pCell->GetFormat();
- if (pItem->mask & GVIF_BKCLR)
- pItem->crBkClr = pCell->GetBackClr();
- if (pItem->mask & GVIF_FGCLR)
- pItem->crFgClr = pCell->GetTextClr();
- if (pItem->mask & GVIF_FONT)
- memcpy(&(pItem->lfFont), pCell->GetFont(), sizeof(LOGFONT));
- if( pItem->mask & GVIF_MARGIN)
- pItem->nMargin = pCell->GetMargin();
- return TRUE;
- }
- BOOL CGridCtrl::SetItemText(int nRow, int nCol, LPCTSTR str)
- {
- if (GetVirtualMode())
- return FALSE;
- CGridCellBase* pCell = GetCell(nRow, nCol);
- if (!pCell)
- return FALSE;
- pCell->SetText(str);
- SetModified(TRUE, nRow, nCol);
- return TRUE;
- }
- #if (_WIN32_WCE >= 210)
- // EFW - 06/13/99 - Added to support printf-style formatting codes
- BOOL CGridCtrl::SetItemTextFmt(int nRow, int nCol, LPCTSTR szFmt, ...)
- {
- if (GetVirtualMode())
- return FALSE;
- CString strText;
- va_list argptr;
- CGridCellBase* pCell = GetCell(nRow, nCol);
- if (!pCell)
- return FALSE;
- // Format the message text
- va_start(argptr, szFmt);
- strText.FormatV(szFmt, argptr);
- va_end(argptr);
- pCell->SetText(strText);
- SetModified(TRUE, nRow, nCol);
- return TRUE;
- }
- // EFW - 06/13/99 - Added to support string resource ID. Supports
- // a variable argument list too.
- BOOL CGridCtrl::SetItemTextFmtID(int nRow, int nCol, UINT nID, ...)
- {
- if (GetVirtualMode())
- return FALSE;
- CString strFmt, strText;
- va_list argptr;
- CGridCellBase* pCell = GetCell(nRow, nCol);
- if (!pCell)
- return FALSE;
- // Format the message text
- va_start(argptr, nID);
- VERIFY(strFmt.LoadString(nID));
- strText.FormatV(strFmt, argptr);
- va_end(argptr);
- pCell->SetText(strText);
- SetModified(TRUE, nRow, nCol);
- return TRUE;
- }
- #endif
- BOOL CGridCtrl::SetItemData(int nRow, int nCol, LPARAM lParam)
- {
- if (GetVirtualMode())
- return FALSE;
- CGridCellBase* pCell = GetCell(nRow, nCol);
- if (!pCell)
- return FALSE;
- pCell->SetData(lParam);
- SetModified(TRUE, nRow, nCol);
- return TRUE;
- }
- LPARAM CGridCtrl::GetItemData(int nRow, int nCol) const
- {
- CGridCellBase* pCell = GetCell(nRow, nCol);
- if (!pCell)
- return (LPARAM) 0;
- return pCell->GetData();
- }
- BOOL CGridCtrl::SetItemImage(int nRow, int nCol, int iImage)
- {
- if (GetVirtualMode())
- return FALSE;
- CGridCellBase* pCell = GetCell(nRow, nCol);
- if (!pCell)
- return FALSE;
- pCell->SetImage(iImage);
- SetModified(TRUE, nRow, nCol);
- return TRUE;
- }
- int CGridCtrl::GetItemImage(int nRow, int nCol) const
- {
- CGridCellBase* pCell = GetCell(nRow, nCol);
- ASSERT(pCell);
- if (!pCell)
- return -1;
- return pCell->GetImage();
- }
- BOOL CGridCtrl::SetItemState(int nRow, int nCol, UINT state)
- {
- BOOL bSelected = IsCellSelected(nRow, nCol);
- // If the cell is being unselected, remove it from the selected list
- if (bSelected && !(state & GVIS_SELECTED))
- {
- CCellID cell;
- DWORD key = MAKELONG(nRow, nCol);
- if (m_SelectedCellMap.Lookup(key, (CCellID&)cell))
- m_SelectedCellMap.RemoveKey(key);
- }
- // If cell is being selected, add it to the list of selected cells
- else if (!bSelected && (state & GVIS_SELECTED))
- {
- CCellID cell(nRow, nCol);
- m_SelectedCellMap.SetAt(MAKELONG(nRow, nCol), cell);
- }
- if (GetVirtualMode())
- return FALSE;
- CGridCellBase* pCell = GetCell(nRow, nCol);
- ASSERT(pCell);
- if (!pCell)
- return FALSE;
- // Set the cell's state
- pCell->SetState(state);
- return TRUE;
- }
- UINT CGridCtrl::GetItemState(int nRow, int nCol) const
- {
- CGridCellBase* pCell = GetCell(nRow, nCol);
- ASSERT(pCell);
- if (!pCell)
- return 0;
- return pCell->GetState();
- }
- BOOL CGridCtrl::SetItemFormat(int nRow, int nCol, UINT nFormat)
- {
- if (GetVirtualMode())
- return FALSE;
- CGridCellBase* pCell = GetCell(nRow, nCol);
- ASSERT(pCell);
- if (!pCell)
- return FALSE;
- pCell->SetFormat(nFormat);
- return TRUE;
- }
- UINT CGridCtrl::GetItemFormat(int nRow, int nCol) const
- {
- CGridCellBase* pCell = GetCell(nRow, nCol);
- ASSERT(pCell);
- if (!pCell)
- return 0;
- return pCell->GetFormat();
- }
- BOOL CGridCtrl::SetItemBkColour(int nRow, int nCol, COLORREF cr /* = CLR_DEFAULT */)
- {
- if (GetVirtualMode())
- return FALSE;
- CGridCellBase* pCell = GetCell(nRow, nCol);
- ASSERT(pCell);
- if (!pCell)
- return FALSE;
- pCell->SetBackClr(cr);
- return TRUE;
- }
- COLORREF CGridCtrl::GetItemBkColour(int nRow, int nCol) const
- {
- CGridCellBase* pCell = GetCell(nRow, nCol);
- ASSERT(pCell);
- if (!pCell)
- return 0;
- return pCell->GetBackClr();
- }
- BOOL CGridCtrl::SetItemFgColour(int nRow, int nCol, COLORREF cr /* = CLR_DEFAULT */)
- {
- if (GetVirtualMode())
- return FALSE;
- CGridCellBase* pCell = GetCell(nRow, nCol);
- ASSERT(pCell);
- if (!pCell)
- return FALSE;
- pCell->SetTextClr(cr);
- return TRUE;
- }
- COLORREF CGridCtrl::GetItemFgColour(int nRow, int nCol) const
- {
- CGridCellBase* pCell = GetCell(nRow, nCol);
- ASSERT(pCell);
- if (!pCell)
- return 0;
- return pCell->GetTextClr();
- }
- BOOL CGridCtrl::SetItemFont(int nRow, int nCol, const LOGFONT* plf)
- {
- if (GetVirtualMode())
- return FALSE;
- CGridCellBase* pCell = GetCell(nRow, nCol);
- ASSERT(pCell);
- if (!pCell)
- return FALSE;
- pCell->SetFont(plf);
- return TRUE;
- }
- const LOGFONT* CGridCtrl::GetItemFont(int nRow, int nCol)
- {
- CGridCellBase* pCell = GetCell(nRow, nCol);
- ASSERT(pCell);
- if (!pCell)
- return GetDefaultCell(nRow < GetFixedRowCount(), nCol < GetFixedColumnCount())->GetFont();
- return pCell->GetFont();
- }
- BOOL CGridCtrl::IsItemEditing(int nRow, int nCol)
- {
- CGridCellBase* pCell = GetCell(nRow, nCol);
- ASSERT(pCell);
- if (!pCell)
- return FALSE;
- return pCell->IsEditing();
- }
- ////////////////////////////////////////////////////////////////////////////////////
- // Row/Column size functions
- 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;
- }
- int CGridCtrl::GetRowHeight(int nRow) const
- {
- ASSERT(nRow >= 0 && nRow < m_nRows);
- if (nRow < 0 || nRow >= m_nRows)
- return -1;
- return m_arRowHeights[nRow];
- }
- int CGridCtrl::GetColumnWidth(int nCol) const
- {
- ASSERT(nCol >= 0 && nCol < m_nCols);
- if (nCol < 0 || nCol >= m_nCols)
- return -1;
- return m_arColWidths[nCol];
- }
- BOOL CGridCtrl::SetRowHeight(int nRow, int height)
- {
- ASSERT(nRow >= 0 && nRow < m_nRows && height >= 0);
- if (nRow < 0 || nRow >= m_nRows || height < 0)
- return FALSE;
- m_arRowHeights[nRow] = height;
- ResetScrollBars();
- return TRUE;
- }
- BOOL CGridCtrl::SetColumnWidth(int nCol, int width)
- {
- ASSERT(nCol >= 0 && nCol < m_nCols && width >= 0);
- if (nCol < 0 || nCol >= m_nCols || width < 0)
- return FALSE;
- m_arColWidths[nCol] = width;
- ResetScrollBars();
- return TRUE;
- }
- int CGridCtrl::GetFixedRowHeight() const
- {
- int nHeight = 0;
- for (int i = 0; i < m_nFixedRows; i++)
- nHeight += GetRowHeight(i);
- return nHeight;
- }
- int CGridCtrl::GetFixedColumnWidth() const
- {
- int nWidth = 0;
- for (int i = 0; i < m_nFixedCols; i++)
- nWidth += GetColumnWidth(i);
- return nWidth;
- }
- BOOL CGridCtrl::AutoSizeColumn(int nCol, UINT nAutoSizeStyle /*=GVS_DEFAULT*/,
- BOOL bResetScroll /*=TRUE*/)
- {
- ASSERT(nCol >= 0 && nCol < m_nCols);
- if (nCol < 0 || nCol >= m_nCols)
- return FALSE;
- // Skip hidden columns when autosizing
- if( GetColumnWidth( nCol) <=0 )
- return FALSE;
- CSize size;
- CDC* pDC = GetDC();
- if (!pDC)
- return FALSE;
- int nWidth = 0;
- ASSERT(GVS_DEFAULT <= nAutoSizeStyle && nAutoSizeStyle <= GVS_BOTH);
- if (nAutoSizeStyle == GVS_DEFAULT)
- nAutoSizeStyle = GetAutoSizeStyle();
- int nStartRow = (nAutoSizeStyle & GVS_HEADER)? 0 : GetFixedRowCount();
- int nEndRow = (nAutoSizeStyle & GVS_DATA)? GetRowCount()-1 : GetFixedRowCount()-1;
- for (int nRow = nStartRow; nRow <= nEndRow; nRow++)
- {
- CGridCellBase* pCell = GetCell(nRow, nCol);
- if (pCell)
- size = pCell->GetCellExtent(pDC);
- if (size.cx > nWidth)
- nWidth = size.cx;
- }
- m_arColWidths[nCol] = nWidth;
- ReleaseDC(pDC);
- if (bResetScroll)
- ResetScrollBars();
- return TRUE;
- }
- BOOL CGridCtrl::AutoSizeRow(int nRow, BOOL bResetScroll /*=TRUE*/)
- {
- ASSERT(nRow >= 0 && nRow < m_nRows);
- if (nRow < 0 || nRow >= m_nRows)
- return FALSE;
- // Skip hidden rows when autosizing
- if( GetRowHeight( nRow) <=0 )
- return FALSE;
- CSize size;
- CDC* pDC = GetDC();
- if (!pDC)
- return FALSE;
- int nHeight = 0;
- int nNumColumns = GetColumnCount();
- for (int nCol = 0; nCol < nNumColumns; nCol++)
- {
- CGridCellBase* pCell = GetCell(nRow, nCol);
- if (pCell)
- size = pCell->GetCellExtent(pDC);
- if (size.cy > nHeight)
- nHeight = size.cy;
- }
- m_arRowHeights[nRow] = nHeight;
- ReleaseDC(pDC);
- if (bResetScroll)
- ResetScrollBars();
- return TRUE;
- }
- void CGridCtrl::AutoSizeColumns(UINT nAutoSizeStyle /*=GVS_DEFAULT*/)
- {
- int nNumColumns = GetColumnCount();
- for (int nCol = 0; nCol < nNumColumns; nCol++)
- {
- // Skip hidden columns when autosizing
- if( GetColumnWidth( nCol) > 0 )
- AutoSizeColumn(nCol, nAutoSizeStyle, FALSE);
- }
- ResetScrollBars();
- }
- void CGridCtrl::AutoSizeRows()
- {
- int nNumRows = GetRowCount();
- for (int nRow = 0; nRow < nNumRows; nRow++)
- {
- // Skip hidden rows when autosizing
- if( GetRowHeight( nRow) > 0 )
- AutoSizeRow(nRow, FALSE);
- }
- ResetScrollBars();
- }
- // sizes all rows and columns
- // faster than calling both AutoSizeColumns() and AutoSizeRows()
- void CGridCtrl::AutoSize(UINT nAutoSizeStyle /*=GVS_DEFAULT*/)
- {
- CDC* pDC = GetDC();
- if (!pDC)
- return;
- int nNumColumns = GetColumnCount();
- int nCol, nRow;
- ASSERT(GVS_DEFAULT <= nAutoSizeStyle && nAutoSizeStyle <= GVS_BOTH);
- if (nAutoSizeStyle == GVS_DEFAULT)
- nAutoSizeStyle = GetAutoSizeStyle();
- int nStartRow = (nAutoSizeStyle & GVS_HEADER)? 0 : GetFixedRowCount();
- int nEndRow = (nAutoSizeStyle & GVS_DATA)? GetRowCount()-1 : GetFixedRowCount()-1;
- // Row initialisation - only work on rows whose height is > 0
- for (nRow = nStartRow; nRow <= nEndRow; nRow++)
- {
- if( GetRowHeight( nRow) > 0 )
- m_arRowHeights[nRow] = 1;
- }
- CSize size;
- for (nCol = 0; nCol < nNumColumns; nCol++)
- {
- // Don't size hidden columns or rows
- if( GetColumnWidth( nCol) > 0 )
- {
- // Skip columns that are hidden, but now initialize
- m_arColWidths[nCol] = 0;
- for (nRow = nStartRow; nRow <= nEndRow; nRow++)
- {
- if( GetRowHeight( nRow) > 0 )
- {
- CGridCellBase* pCell = GetCell(nRow, nCol);
- if (pCell)
- size = pCell->GetCellExtent(pDC);
- if (size.cx >(int) m_arColWidths[nCol])
- m_arColWidths[nCol] = size.cx;
- if (size.cy >(int) m_arRowHeights[nRow])
- m_arRowHeights[nRow] = size.cy;
- }
- }
- }
- }
- ReleaseDC(pDC);
- ResetScrollBars();
- Refresh();
- }
- void CGridCtrl::ExpandColumnsToFit()
- {
- if (GetColumnCount() <= 0)
- return;
- EnableScrollBars(SB_BOTH, FALSE);
- CRect rect;
- GetClientRect(rect);
- long virtualWidth = GetVirtualWidth();
- int nDifference = rect.Width() -(int) virtualWidth;
- int nColumnAdjustment = nDifference / GetColumnCount();
- for (int i = 0; i < GetColumnCount(); i++)
- m_arColWidths[i] += nColumnAdjustment;
- if (nDifference > 0)
- {
- int leftOver = nDifference % GetColumnCount();
- for (i = 0; i < leftOver; i++)
- m_arColWidths[i] += 1;
- }
- else
- {
- int leftOver = (-nDifference) % GetColumnCount();
- for (i = 0; i < leftOver; i++)
- m_arColWidths[i] -= 1;
- }
- Refresh();
- ResetScrollBars();
- }
- void CGridCtrl::ExpandLastColumn()
- {
- if (GetColumnCount() <= 0)
- return;
- EnableScrollBars(SB_BOTH, FALSE);
- CRect rect;
- GetClientRect(rect);
- long virtualWidth = GetVirtualWidth();
- int nDifference = rect.Width() -(int) virtualWidth;
- if (nDifference > 0)
- {
- if (GetVirtualHeight() > rect.Height())
- nDifference -= GetSystemMetrics(SM_CYHSCROLL);
- m_arColWidths[ GetColumnCount()-1 ] += nDifference;
- Refresh();
- }
- ResetScrollBars();
- }
- void CGridCtrl::ExpandRowsToFit()
- {
- if (GetRowCount() <= 0)
- return;
- EnableScrollBars(SB_BOTH, FALSE);
- CRect rect;
- GetClientRect(rect);
- long virtualHeight = GetVirtualHeight();
- int nDifference = rect.Height() -(int) virtualHeight;
- int nRowAdjustment = nDifference / GetRowCount();
- for (int i = 0; i < GetRowCount(); i++)
- m_arRowHeights[i] += nRowAdjustment;
- if (nDifference > 0)
- {
- int leftOver = nDifference % GetRowCount();
- for (i = 0; i < leftOver; i++)
- m_arRowHeights[i] += 1;
- }
- else
- {
- int leftOver = (-nDifference) % GetRowCount();
- for (i = 0; i < leftOver; i++)
- m_arRowHeights[i] -= 1;
- }
- Refresh();
- ResetScrollBars();
- }
- void CGridCtrl::ExpandToFit()
- {
- ExpandColumnsToFit(); // This will remove any existing horz scrollbar
- ExpandRowsToFit(); // This will remove any existing vert scrollbar
- ExpandColumnsToFit(); // Just in case the first adjustment was with a vert
- // scrollbar in place
- Refresh();
- }
- /////////////////////////////////////////////////////////////////////////////////////
- // Attributes
- void CGridCtrl::SetVirtualMode(BOOL bVirtual)
- {
- DeleteAllItems();
- m_bVirtualMode = bVirtual;
- // Force some defaults here.
- if (m_bVirtualMode)
- {
- SetEditable(FALSE);
- SetHeaderSort(FALSE);
- SetAutoSizeStyle(GVS_HEADER);
- SetFixedColumnSelection(FALSE);
- SetFixedRowSelection(FALSE);
- }
- }
- void CGridCtrl::SetGridLines(int nWhichLines /*=GVL_BOTH*/)
- {
- m_nGridLines = nWhichLines;
- Refresh();
- }
- void CGridCtrl::SetListMode(BOOL bEnableListMode /*=TRUE*/)
- {
- ResetSelectedRange();
- SetSortColumn(-1);
- m_bListMode = bEnableListMode;
- SetFixedRowSelection(FALSE);
- Refresh();
- }
- void CGridCtrl::SetSortColumn(int nCol)
- {
- if (m_nSortColumn >= 0)
- InvalidateCellRect(0, m_nSortColumn);
- m_nSortColumn = nCol;
- if (nCol >= 0)
- InvalidateCellRect(0, nCol);
- }
- BOOL CGridCtrl::IsCellFixed(int nRow, int nCol)
- {
- return (nRow < GetFixedRowCount() || nCol < GetFixedColumnCount());
- }
- void CGridCtrl::SetModified(BOOL bModified /*=TRUE*/, int nRow /*=-1*/, int nCol /*=-1*/)
- {
- // Cannot guarantee sorting anymore...
- if (nCol < 0 || nCol == GetSortColumn())
- SetSortColumn(-1);
- if (nRow > 0 && nCol > 0)
- {
- if (bModified)
- {
- SetItemState(nRow, nCol, GetItemState(nRow, nCol) | GVIS_MODIFIED);
- m_bModified = TRUE;
- }
- else
- SetItemState(nRow, nCol, GetItemState(nRow, nCol) & ~GVIS_MODIFIED);
- }
- else
- m_bModified = bModified;
- if (!m_bModified)
- {
- for (int row = 0; row < GetRowCount(); row++)
- for (int col = 0; col < GetColumnCount(); col++)
- SetItemState(row, col, GetItemState(row, col) & ~GVIS_MODIFIED);
- }
- }
- BOOL CGridCtrl::GetModified(int nRow /*=-1*/, int nCol /*=-1*/)
- {
- if (nRow > 0 && nCol > 0)
- return ( (GetItemState(nRow, nCol) & GVIS_MODIFIED) == GVIS_MODIFIED );
- else
- return m_bModified;
- }
- /////////////////////////////////////////////////////////////////////////////////////
- // GridCtrl cell visibility tests and invalidation/redraw functions
- void CGridCtrl::Refresh()
- {
- if (GetSafeHwnd() && m_bAllowDraw)
- Invalidate();
- }
- // EnsureVisible supplied by Roelf Werkman
- void CGridCtrl::EnsureVisible(int nRow, int nCol)
- {
- CCellRange VisibleCells = GetVisibleNonFixedCellRange();
- int right = nCol - VisibleCells.GetMaxCol();
- int left = VisibleCells.GetMinCol() - nCol;
- int down = nRow - VisibleCells.GetMaxRow();
- int up = VisibleCells.GetMinRow() - nRow;
- int iColumnStart;
- int iRowStart;
- iColumnStart = VisibleCells.GetMaxCol() + 1;
- while( right > 0 )
- {
- if( GetColumnWidth( iColumnStart ) > 0 )
- SendMessage( WM_HSCROLL, SB_LINERIGHT, 0 );
- right--;
- iColumnStart++;
- }
- iColumnStart = VisibleCells.GetMinCol() - 1;
- while( left > 0 )
- {
- if( GetColumnWidth( iColumnStart ) > 0 )
- SendMessage( WM_HSCROLL, SB_LINELEFT, 0 );
- left--;
- iColumnStart--;
- }
- iRowStart = VisibleCells.GetMaxRow() + 1;
- while( down > 0 )
- {
- if( GetRowHeight( iRowStart ) > 0 )
- SendMessage( WM_VSCROLL, SB_LINEDOWN, 0 );
- down--;
- iRowStart++;
- }
- iRowStart = VisibleCells.GetMinRow() - 1;
- while( up > 0 )
- {
- if( GetRowHeight( iRowStart ) > 0 )
- SendMessage( WM_VSCROLL, SB_LINEUP, 0 );
- up--;
- iRowStart--;
- }
- // Move one more if we only see a snall bit of the cell
- CRect rectCell, rectWindow;
- if (!GetCellRect(nRow, nCol, rectCell))
- return;
- GetClientRect(rectWindow);
- // The previous fix was fixed properly by Martin Richter <martin.richter@grutzeck.de>
- while (rectCell.right > rectWindow.right
- && rectCell.left > GetFixedColumnWidth())
- {
- SendMessage(WM_HSCROLL, SB_LINERIGHT, 0);
- if (!GetCellRect(nRow, nCol, rectCell))
- return;
- }
- while (rectCell.bottom > rectWindow.bottom
- && rectCell.top > GetFixedRowHeight())
- {
- SendMessage(WM_VSCROLL, SB_LINEDOWN, 0);
- if (!GetCellRect(nRow, nCol, rectCell))
- return;
- }
- }
- BOOL CGridCtrl::IsCellEditable(CCellID &cell) const
- {
- return IsCellEditable(cell.row, cell.col);
- }
- BOOL CGridCtrl::IsCellEditable(int nRow, int nCol) const
- {
- return IsEditable() && ((GetItemState(nRow, nCol) & GVIS_READONLY) != GVIS_READONLY);
- }
- BOOL CGridCtrl::IsCellSelected(CCellID &cell) const
- {
- return IsCellSelected(cell.row, cell.col);
- }
- BOOL CGridCtrl::IsCellSelected(int nRow, int nCol) const
- {
- if (GetVirtualMode())
- {
- if (!IsSelectable())
- return FALSE;
- CCellID cell;
- DWORD key = MAKELONG(nRow, nCol);
- return (m_SelectedCellMap.Lookup(key, (CCellID&)cell));
- }
- else
- return IsSelectable() && ((GetItemState(nRow, nCol) & GVIS_SELECTED) == GVIS_SELECTED);
- }
- BOOL CGridCtrl::IsCellVisible(CCellID cell)
- {
- return IsCellVisible(cell.row, cell.col);
- }
- BOOL CGridCtrl::IsCellVisible(int nRow, int nCol)
- {
- if (!IsWindow(m_hWnd))
- return FALSE;
- int x, y;
- CCellID TopLeft;
- if (nCol >= GetFixedColumnCount() || nRow >= GetFixedRowCount())
- {
- TopLeft = GetTopleftNonFixedCell();
- if (nCol >= GetFixedColumnCount() && nCol < TopLeft.col)
- return FALSE;
- if (nRow >= GetFixedRowCount() && nRow < TopLeft.row)
- return FALSE;
- }
- CRect rect;
- GetClientRect(rect);
- if (nCol < GetFixedColumnCount())
- {
- x = 0;
- for (int i = 0; i <= nCol; i++)
- {
- if (x >= rect.right)
- return FALSE;
- x += GetColumnWidth(i);
- }
- }
- else
- {
- x = GetFixedColumnWidth();
- for (int i = TopLeft.col; i <= nCol; i++)
- {
- if (x >= rect.right)
- return FALSE;
- x += GetColumnWidth(i);
- }
- }
- if (nRow < GetFixedRowCount())
- {
- y = 0;
- for (int i = 0; i <= nRow; i++)
- {
- if (y >= rect.bottom)
- return FALSE;
- y += GetRowHeight(i);
- }
- }
- else
- {
- if (nRow < TopLeft.row)
- return FALSE;
- y = GetFixedRowHeight();
- for (int i = TopLeft.row; i <= nRow; i++)
- {
- if (y >= rect.bottom)
- return FALSE;
- y += GetRowHeight(i);
- }
- }
- return TRUE;
- }
- BOOL CGridCtrl::InvalidateCellRect(const CCellID& cell)
- {
- return InvalidateCellRect(cell.row, cell.col);
- }
- BOOL CGridCtrl::InvalidateCellRect(const int row, const int col)
- {
- if (!::IsWindow(GetSafeHwnd()) || !m_bAllowDraw)
- return FALSE;
- if (!IsValid(row, col))
- return FALSE;
- if (!IsCellVisible(row, col))
- return FALSE;
- CRect rect;
- if (!GetCellRect(row, col, rect))
- return FALSE;
- rect.right++;
- rect.bottom++;
- InvalidateRect(rect, TRUE);
- return TRUE;
- }
- BOOL CGridCtrl::InvalidateCellRect(const CCellRange& cellRange)
- {
- ASSERT(IsValid(cellRange));
- if (!::IsWindow(GetSafeHwnd()) || !m_bAllowDraw)
- return FALSE;
- CCellRange visibleCellRange = GetVisibleNonFixedCellRange().Intersect(cellRange);
- CRect rect;
- if (!GetCellRangeRect(visibleCellRange, rect))
- return FALSE;
- rect.right++;
- rect.bottom++;
- InvalidateRect(rect, TRUE);
- return TRUE;
- }
- /////////////////////////////////////////////////////////////////////////////
- // CGridCtrl Mouse stuff
- // Handles mouse wheel notifications
- // Note - if this doesn't work for win95 then use OnRegisteredMouseWheel instead
- #if !defined(_WIN32_WCE) && (_MFC_VER >= 0x0421)
- BOOL CGridCtrl::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
- {
- // A m_nRowsPerWheelNotch value less than 0 indicates that the mouse
- // wheel scrolls whole pages, not just lines.
- if (m_nRowsPerWheelNotch == -1)
- {
- int nPagesScrolled = zDelta / 120;
- if (nPagesScrolled > 0)
- for (int i = 0; i < nPagesScrolled; i++)
- PostMessage(WM_VSCROLL, SB_PAGEUP, 0);
- else
- for (int i = 0; i > nPagesScrolled; i--)
- PostMessage(WM_VSCROLL, SB_PAGEDOWN, 0);
- }
- else
- {
- int nRowsScrolled = m_nRowsPerWheelNotch * zDelta / 120;
- if (nRowsScrolled > 0)
- for (int i = 0; i < nRowsScrolled; i++)
- PostMessage(WM_VSCROLL, SB_LINEUP, 0);
- else
- for (int i = 0; i > nRowsScrolled; i--)
- PostMessage(WM_VSCROLL, SB_LINEDOWN, 0);
- }
- return CWnd::OnMouseWheel(nFlags, zDelta, pt);
- }
- #endif // !defined(_WIN32_WCE) && (_MFC_VER >= 0x0421)
- void CGridCtrl::OnMouseMove(UINT /*nFlags*/, CPoint point)
- {
- CRect rect;
- GetClientRect(rect);
- #ifndef GRIDCONTROL_NO_DRAGDROP
- // If outside client area, return (unless we are drag n dropping)
- if (m_MouseMode != MOUSE_DRAGGING && !rect.PtInRect(point))
- return;
- #endif
- // Sometimes a MOUSEMOVE message can come after the left buttons
- // has been let go, but before the BUTTONUP message hs been processed.
- // We'll keep track of mouse buttons manually to avoid this.
- // All bMouseButtonDown's have been replaced with the member m_bMouseButtonDown
- // BOOL bMouseButtonDown = ((nFlags & MK_LBUTTON) == MK_LBUTTON);
- // If the left mouse button is up, then test to see if row/column sizing is imminent
- if (!m_bMouseButtonDown ||
- (m_bMouseButtonDown && m_MouseMode == MOUSE_NOTHING))
- {
- if (m_bAllowColumnResize && MouseOverColumnResizeArea(point))
- {
- if (m_MouseMode != MOUSE_OVER_COL_DIVIDE)
- {
- #ifndef _WIN32_WCE_NO_CURSOR
- SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZEWE));
- #endif
- m_MouseMode = MOUSE_OVER_COL_DIVIDE;
- }
- }
- else if (m_bAllowRowResize && MouseOverRowResizeArea(point))
- {
- if (m_MouseMode != MOUSE_OVER_ROW_DIVIDE)
- {
- #ifndef _WIN32_WCE_NO_CURSOR
- SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZENS));
- #endif
- m_MouseMode = MOUSE_OVER_ROW_DIVIDE;
- }
- }
- else if (m_MouseMode != MOUSE_NOTHING)
- {
- #ifndef _WIN32_WCE_NO_CURSOR
- SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
- #endif
- m_MouseMode = MOUSE_NOTHING;
- }
- if (m_MouseMode == MOUSE_NOTHING)
- {
- CGridCellBase* pCell = NULL;
- CCellID idCurrentCell;
- if (!GetVirtualMode() || m_bTitleTips)
- {
- // Let the cell know that a big fat cursor is currently hovering
- // over it.
- idCurrentCell = GetCellFromPt(point);
- pCell = GetCell(idCurrentCell.row, idCurrentCell.col);
- if (pCell)
- pCell->OnMouseOver();
- }
- #ifndef GRIDCONTROL_NO_TITLETIPS
- // Titletips anyone? anyone?
- if (m_bTitleTips)
- {
- CRect TextRect, CellRect;
- if (pCell)
- {
- LPCTSTR szTipText = pCell->GetTipText();
- if (szTipText && szTipText[0]
- && !pCell->IsEditing()
- && GetCellRect( idCurrentCell.row, idCurrentCell.col, &TextRect)
- && pCell->GetTipTextRect( &TextRect)
- && GetCellRect(idCurrentCell.row, idCurrentCell.col, CellRect) )
- {
- m_TitleTip.Show(TextRect, pCell->GetTipText(), 0, CellRect,
- pCell->GetFont(), GetTitleTipTextClr(), GetTitleTipBackClr());
- }
- }
- }
- #endif
- }
- m_LastMousePoint = point;
- return;
- }
- if (!IsValid(m_LeftClickDownCell))
- {
- m_LastMousePoint = point;
- return;
- }
- // If the left mouse button is down, then process appropriately
- if (m_bMouseButtonDown)
- {
- switch (m_MouseMode)
- {
- case MOUSE_SELECT_ALL:
- break;
- case MOUSE_SELECT_COL:
- case MOUSE_SELECT_ROW:
- case MOUSE_SELECT_CELLS:
- {
- CCellID idCurrentCell = GetCellFromPt(point);
- if (!IsValid(idCurrentCell))
- return;
- if (idCurrentCell != GetFocusCell())
- {
- OnSelecting(idCurrentCell);
- // EFW - BUG FIX - Keep the appropriate cell row and/or
- // column focused. A fix in SetFocusCell() will place
- // the cursor in a non-fixed cell as needed.
- if((idCurrentCell.row >= m_nFixedRows &&
- idCurrentCell.col >= m_nFixedCols) ||
- m_MouseMode==MOUSE_SELECT_COL ||
- m_MouseMode==MOUSE_SELECT_ROW)
- {
- SetFocusCell(idCurrentCell);
- }
- }
- break;
- }
- case MOUSE_SIZING_COL:
- {
- CDC* pDC = GetDC();
- if (!pDC)
- break;
- CRect oldInvertedRect(m_LastMousePoint.x, rect.top,
- m_LastMousePoint.x + 2, rect.bottom);
- pDC->InvertRect(&oldInvertedRect);
- CRect newInvertedRect(point.x, rect.top,
- point.x + 2, rect.bottom);
- pDC->InvertRect(&newInvertedRect);
- ReleaseDC(pDC);
- }
- break;
- case MOUSE_SIZING_ROW:
- {
- CDC* pDC = GetDC();
- if (!pDC)
- break;
- CRect oldInvertedRect(rect.left, m_LastMousePoint.y,
- rect.right, m_LastMousePoint.y + 2);
- pDC->InvertRect(&oldInvertedRect);
- CRect newInvertedRect(rect.left, point.y,
- rect.right, point.y + 2);
- pDC->InvertRect(&newInvertedRect);
- ReleaseDC(pDC);
- }
- break;
- #ifndef GRIDCONTROL_NO_DRAGDROP
- case MOUSE_PREPARE_EDIT:
- case MOUSE_PREPARE_DRAG:
- m_MouseMode = MOUSE_PREPARE_DRAG;
- OnBeginDrag();
- break;
- #endif
- }
- }
- m_LastMousePoint = point;
- }
- CPoint CGridCtrl::GetPointClicked(int nRow, int nCol, const CPoint& point)
- {
- CPoint PointCellOrigin;
- if( !GetCellOrigin( nRow, nCol, &PointCellOrigin) )
- return CPoint( 0, 0);
- CPoint PointClickedCellRelative( point);
- PointClickedCellRelative -= PointCellOrigin;
- return PointClickedCellRelative;
- }
- void CGridCtrl::OnLButtonDblClk(UINT nFlags, CPoint point)
- {
- TRACE0("CGridCtrl::OnLButtonDblClkn");
- CCellID cell = GetCellFromPt(point);
- if( !IsValid( cell) )
- {
- //ASSERT(FALSE);
- return;
- }
- #ifdef _WIN32_WCE
- if (MouseOverColumnResizeArea(point))
- #else
- if (m_MouseMode == MOUSE_OVER_COL_DIVIDE)
- #endif
- {
- CPoint start;
- if (!GetCellOrigin(0, cell.col, &start))
- return;
- if (point.x - start.x <= m_nResizeCaptureRange) // Clicked right of border
- cell.col--;
- // ignore columns that are hidden and look left towards first visible column
- BOOL bFoundVisible = FALSE;
- while( cell.col >= 0)
- {
- if( GetColumnWidth( cell.col) > 0)
- {
- bFoundVisible = TRUE;
- break;
- }
- cell.col--;
- }
- if( !bFoundVisible)
- return;
- AutoSizeColumn(cell.col, GetAutoSizeStyle());
- Invalidate();
- }
- #ifdef _WIN32_WCE
- else if (MouseOverRowResizeArea(point))
- #else
- else if (m_MouseMode == MOUSE_OVER_ROW_DIVIDE)
- #endif
- {
- CPoint start;
- if (!GetCellOrigin(0, cell.col, &start))
- return;
- if (point.y - start.y <= m_nResizeCaptureRange) // Clicked below border
- cell.row--;
- // ignore rows that are hidden and look upt towards first visible row
- BOOL bFoundVisible = FALSE;
- while( cell.row >= 0)
- {
- if( GetRowHeight( cell.row) > 0)
- {
- bFoundVisible = TRUE;
- break;
- }
- cell.row--;
- }
- if( !bFoundVisible)
- return;
- AutoSizeRow(cell.row);
- Invalidate();
- }
- else if (m_MouseMode == MOUSE_NOTHING)
- {
- CPoint pointClickedRel;
- pointClickedRel = GetPointClicked( cell.row, cell.col, point);
- if (cell.row >= m_nFixedRows && IsValid(m_LeftClickDownCell) && cell.col >= m_nFixedCols)
- {
- OnEditCell(cell.row, cell.col, pointClickedRel, VK_LBUTTON);
- }
- else if (m_bListMode)
- {
- if (!IsValid(cell))
- return;
- if (cell.row >= m_nFixedRows && cell.col < GetFixedColumnCount())
- OnEditCell(cell.row, cell.col, pointClickedRel, VK_LBUTTON);
- }
- if (IsValid(cell))
- {
- CGridCellBase* pCell = GetCell(cell.row, cell.col);
- if (pCell)
- pCell->OnDblClick(pointClickedRel);
- SendMessageToParent(cell.row, cell.col, NM_DBLCLK);
- }
- }
- CWnd::OnLButtonDblClk(nFlags, point);
- }
- void CGridCtrl::OnLButtonDown(UINT nFlags, CPoint point)
- {
- #ifdef GRIDCONTROL_USE_TITLETIPS
- // EFW - Bug Fix
- m_TitleTip.Hide(); // hide any titletips
- #endif
- // TRACE0("CGridCtrl::OnLButtonDownn");
- // CWnd::OnLButtonDown(nFlags, point);
- SetFocus();
- m_bMouseButtonDown = TRUE;
- m_LeftClickDownPoint = point;
- m_LeftClickDownCell = GetCellFromPt(point);
- if (!IsValid(m_LeftClickDownCell))
- return;
- // If the SHIFT key is not down, then the start of the selection area should be the
- // cell just clicked. Otherwise, keep the previous selection-start-cell so the user
- // can add to their previous cell selections in an intuitive way. If no selection-
- // start-cell has been specified, then set it's value here and now.
- if ((nFlags & MK_SHIFT) != MK_SHIFT)
- m_SelectionStartCell = m_LeftClickDownCell;
- else
- {
- if (!IsValid(m_SelectionStartCell))
- m_SelectionStartCell = m_idCurrentCell;
- }
- EndEditing();
- // tell the cell about it -- only things like a btn embedded in a cell
- // would look at these msgs
- CGridCellBase* pCell = GetCell(m_LeftClickDownCell.row, m_LeftClickDownCell.col);
- if (pCell)
- pCell->OnClickDown( GetPointClicked( m_LeftClickDownCell.row, m_LeftClickDownCell.col, point));
- // If the user clicks on the current cell, then prepare to edit it.
- // (If the user moves the mouse, then dragging occurs)
- if (m_LeftClickDownCell == m_idCurrentCell)
- {
- if (IsCellEditable(m_LeftClickDownCell))
- m_MouseMode = MOUSE_PREPARE_EDIT;
- return;
- }
- // If the user clicks on a selected cell, then prepare to drag it.
- // (If the user moves the mouse, then dragging occurs)
- else if (IsCellSelected(m_LeftClickDownCell))
- {
- // If control is pressed then unselect the cell or row (depending on the list mode)
- if (nFlags & MK_CONTROL)
- {
- SetFocusCell(m_LeftClickDownCell);
- if (GetListMode())
- SelectRows(m_LeftClickDownCell, TRUE, FALSE);
- else
- SelectCells(m_LeftClickDownCell, TRUE, FALSE);
- return;
- }
- #ifndef GRIDCONTROL_NO_DRAGDROP
- else if (m_bAllowDragAndDrop)
- m_MouseMode = MOUSE_PREPARE_DRAG;
- #endif
- }
- else if (m_MouseMode != MOUSE_OVER_COL_DIVIDE &&
- m_MouseMode != MOUSE_OVER_ROW_DIVIDE)
- {
- SetFocusCell(-1, - 1);
- if (GetRowCount() > GetFixedRowCount() &&
- GetColumnCount() > GetFixedColumnCount())
- SetFocusCell(max(m_LeftClickDownCell.row, m_nFixedRows),
- max(m_LeftClickDownCell.col, m_nFixedCols));
- }
- SetCapture();
- if (m_MouseMode == MOUSE_NOTHING)
- {
- if (m_bAllowColumnResize && MouseOverColumnResizeArea(point))
- {
- if (m_MouseMode != MOUSE_OVER_COL_DIVIDE)
- {
- #ifndef _WIN32_WCE_NO_CURSOR
- SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZEWE));
- #endif
- m_MouseMode = MOUSE_OVER_COL_DIVIDE;
- }
- }
- else if (m_bAllowRowResize && MouseOverRowResizeArea(point))
- {
- if (m_MouseMode != MOUSE_OVER_ROW_DIVIDE)
- {
- #ifndef _WIN32_WCE_NO_CURSOR
- SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZENS));
- #endif
- m_MouseMode = MOUSE_OVER_ROW_DIVIDE;
- }
- }
- // else if (m_MouseMode != MOUSE_NOTHING)
- //{
- // SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
- // m_MouseMode = MOUSE_NOTHING;
- //}
- }
- if (m_MouseMode == MOUSE_OVER_COL_DIVIDE) // sizing column
- {
- m_MouseMode = MOUSE_SIZING_COL;
- CPoint start;
- if (!GetCellOrigin(0, m_LeftClickDownCell.col, &start))
- return;
- if( !m_bHiddenColUnhide)
- {
- // ignore columns that are hidden and look left towards first visible column
- BOOL bLookForVisible = TRUE;
- BOOL bIsCellRightBorder = point.x - start.x > m_nResizeCaptureRange;
- if( bIsCellRightBorder
- && m_LeftClickDownCell.col + 1 >= GetColumnCount() )
- {
- // clicked on last column's right border
- // if last column is visible, don't do anything
- if( m_LeftClickDownCell.col >= 0)
- bLookForVisible = FALSE;
- }
- if( bLookForVisible)
- {
- // clicked on column divider other than last right border
- BOOL bFoundVisible = FALSE;
- int iOffset = 1;
- if( bIsCellRightBorder)
- iOffset = 0;
- while( m_LeftClickDownCell.col - iOffset >= 0)
- {
- if( GetColumnWidth( m_LeftClickDownCell.col - iOffset) > 0)
- {
- bFoundVisible = TRUE;
- break;
- }
- m_LeftClickDownCell.col--;
- }
- if( !bFoundVisible)
- return;
- }
- }
- CRect rect;
- GetClientRect(rect);
- CRect invertedRect(point.x, rect.top, point.x + 2, rect.bottom);
- CDC* pDC = GetDC();
- if (pDC)
- {
- pDC->InvertRect(&invertedRect);
- ReleaseDC(pDC);
- }
- if (point.x - start.x <= m_nResizeCaptureRange) // clicked right of border
- if (!GetCellOrigin(0, --m_LeftClickDownCell.col, &start))
- return;
- rect.left = start.x;
- ClientToScreen(rect);
- #ifndef _WIN32_WCE_NO_CURSOR
- ClipCursor(rect);
- #endif
- }
- else if (m_MouseMode == MOUSE_OVER_ROW_DIVIDE) // sizing row
- {
- m_MouseMode = MOUSE_SIZING_ROW;
- CPoint start;
- if (!GetCellOrigin(m_LeftClickDownCell, &start))
- return;
- if( !m_bHiddenRowUnhide)
- {
- // ignore rows that are hidden and look up towards first visible row
- BOOL bLookForVisible = TRUE;
- BOOL bIsCellBottomBorder = point.y - start.y > m_nResizeCaptureRange;
- if( bIsCellBottomBorder
- && m_LeftClickDownCell.row + 1 >= GetRowCount() )
- {
- // clicked on last row's bottom border
- // if last row is visible, don't do anything
- if( m_LeftClickDownCell.row >= 0)
- bLookForVisible = FALSE;
- }
- if( bLookForVisible)
- {
- // clicked on row divider other than last bottom border
- BOOL bFoundVisible = FALSE;
- int iOffset = 1;
- if( bIsCellBottomBorder)
- iOffset = 0;
- while( m_LeftClickDownCell.row - iOffset >= 0)
- {
- if( GetRowHeight( m_LeftClickDownCell.row - iOffset) > 0)
- {
- bFoundVisible = TRUE;
- break;
- }
- m_LeftClickDownCell.row--;
- }
- if( !bFoundVisible)
- return;
- }
- }
- CRect rect;
- GetClientRect(rect);
- CRect invertedRect(rect.left, point.y, rect.right, point.y + 2);
- CDC* pDC = GetDC();
- if (pDC)
- {
- pDC->InvertRect(&invertedRect);
- ReleaseDC(pDC);
- }
- if (point.y - start.y <= m_nResizeCaptureRange) // clicked below border
- if (!GetCellOrigin(--m_LeftClickDownCell.row, 0, &start))
- return;
- rect.top = start.y;
- ClientToScreen(rect);
- #ifndef _WIN32_WCE_NO_CURSOR
- ClipCursor(rect);
- #endif
- }
- else
- #ifndef GRIDCONTROL_NO_DRAGDROP
- if (m_MouseMode != MOUSE_PREPARE_DRAG) // not sizing or editing -- selecting
- #endif
- {
- // If Ctrl pressed, save the current cell selection. This will get added
- // to the new cell selection at the end of the cell selection process
- m_PrevSelectedCellMap.RemoveAll();
- if (nFlags & MK_CONTROL)
- {
- for (POSITION pos = m_SelectedCellMap.GetStartPosition(); pos != NULL; )
- {
- DWORD key;
- CCellID cell;
- m_SelectedCellMap.GetNextAssoc(pos, key, (CCellID&)cell);
- m_PrevSelectedCellMap.SetAt(key, cell);
- }
- }
- if (m_LeftClickDownCell.row < GetFixedRowCount())
- OnFixedRowClick(m_LeftClickDownCell);
- else if (m_LeftClickDownCell.col < GetFixedColumnCount())
- OnFixedColumnClick(m_LeftClickDownCell);
- else
- {
- m_MouseMode = m_bListMode? MOUSE_SELECT_ROW : MOUSE_SELECT_CELLS;
- OnSelecting(m_LeftClickDownCell);
- m_nTimerID = SetTimer(WM_LBUTTONDOWN, m_nTimerInterval, 0);
- }
- }
- m_LastMousePoint = point;
- }
- void CGridCtrl::OnLButtonUp(UINT nFlags, CPoint point)
- {
- // TRACE0("CGridCtrl::OnLButtonUpn");
- CWnd::OnLButtonUp(nFlags, point);
- m_bMouseButtonDown = FALSE;
- #ifndef _WIN32_WCE_NO_CURSOR
- ClipCursor(NULL);
- #endif
- if (GetCapture()->GetSafeHwnd() == GetSafeHwnd())
- {
- ReleaseCapture();
- KillTimer(m_nTimerID);
- m_nTimerID = 0;
- }
- CPoint pointClickedRel;
- pointClickedRel = GetPointClicked( m_idCurrentCell.row, m_idCurrentCell.col, point);
- // m_MouseMode == MOUSE_PREPARE_EDIT only if user clicked down on current cell
- // and then didn't move mouse before clicking up (releasing button)
- if (m_MouseMode == MOUSE_PREPARE_EDIT)
- {
- OnEditCell(m_idCurrentCell.row, m_idCurrentCell.col, pointClickedRel, VK_LBUTTON);
- }
- #ifndef GRIDCONTROL_NO_DRAGDROP
- // m_MouseMode == MOUSE_PREPARE_DRAG only if user clicked down on a selected cell
- // and then didn't move mouse before clicking up (releasing button)
- else if (m_MouseMode == MOUSE_PREPARE_DRAG)
- {
- CGridCellBase* pCell = GetCell(m_idCurrentCell.row, m_idCurrentCell.col);
- if (pCell)
- pCell->OnClick( GetPointClicked( m_idCurrentCell.row, m_idCurrentCell.col, point) );
- SendMessageToParent(m_LeftClickDownCell.row, m_LeftClickDownCell.col, NM_CLICK);
- ResetSelectedRange();
- }
- #endif
- else if (m_MouseMode == MOUSE_SIZING_COL)
- {
- CRect rect;
- GetClientRect(rect);
- CRect invertedRect(m_LastMousePoint.x, rect.top, m_LastMousePoint.x + 2, rect.bottom);
- CDC* pDC = GetDC();
- if (pDC)
- {
- pDC->InvertRect(&invertedRect);
- ReleaseDC(pDC);
- }
- if (m_LeftClickDownPoint != point && (point.x != 0 || point.y != 0)) // 0 pt fix by email1@bierling.net
- {
- CPoint start;
- if (!GetCellOrigin(m_LeftClickDownCell, &start))
- return;
- int nColumnWidth = point.x - start.x;
- if (!m_bAllowColHide)
- nColumnWidth = max(nColumnWidth,1);
- SetColumnWidth(m_LeftClickDownCell.col, nColumnWidth);
- ResetScrollBars();
- Invalidate();
- }
- }
- else if (m_MouseMode == MOUSE_SIZING_ROW)
- {
- CRect rect;
- GetClientRect(rect);
- CRect invertedRect(rect.left, m_LastMousePoint.y, rect.right, m_LastMousePoint.y + 2);
- CDC* pDC = GetDC();
- if (pDC)
- {
- pDC->InvertRect(&invertedRect);
- ReleaseDC(pDC);
- }
- if (m_LeftClickDownPoint != point && (point.x != 0 || point.y != 0)) // 0 pt fix by email1@bierling.net
- {
- CPoint start;
- if (!GetCellOrigin(m_LeftClickDownCell, &start))
- return;
- int nRowHeight = point.y - start.y;
- if (!m_bAllowRowHide)
- nRowHeight = max(nRowHeight,1);
- SetRowHeight(m_LeftClickDownCell.row, nRowHeight);
- ResetScrollBars();
- Invalidate();
- }
- }
- else
- {
- CGridCellBase* pCell = GetCell(m_idCurrentCell.row, m_idCurrentCell.col);
- if (pCell)
- pCell->OnClick( GetPointClicked( m_idCurrentCell.row, m_idCurrentCell.col, point) );
- SendMessageToParent(m_LeftClickDownCell.row, m_LeftClickDownCell.col, NM_CLICK);
- }
- m_MouseMode = MOUSE_NOTHING;
- #ifndef _WIN32_WCE_NO_CURSOR
- SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
- #endif
- if (!IsValid(m_LeftClickDownCell))
- return;
- CWnd *pOwner = GetOwner();
- if (pOwner && IsWindow(pOwner->m_hWnd))
- pOwner->PostMessage(WM_COMMAND, MAKELONG(GetDlgCtrlID(), BN_CLICKED),
- (LPARAM) GetSafeHwnd());
- }
- #ifndef _WIN32_WCE
- // EFW - Added to forward right click to parent so that a context
- // menu can be shown without deriving a new grid class.
- void CGridCtrl::OnRButtonUp(UINT nFlags, CPoint point)
- {
- CCellID FocusCell;
- CWnd::OnRButtonUp(nFlags, point);
- FocusCell = GetCellFromPt(point);
- EndEditing(); // Auto-destroy any InPlaceEdit's
- // If not a valid cell, pass -1 for row and column
- if(!IsValid(FocusCell))
- SendMessageToParent(-1, -1, NM_RCLICK);
- else
- {
- SetFocusCell(-1,-1);
- SetFocusCell(max(FocusCell.row, m_nFixedRows),
- max(FocusCell.col, m_nFixedCols));
- // tell the cell about it
- CGridCellBase* pCell = GetCell(m_idCurrentCell.row, m_idCurrentCell.col);
- if (pCell)
- pCell->OnRClick( GetPointClicked( m_idCurrentCell.row, m_idCurrentCell.col, point) );
- SendMessageToParent(m_idCurrentCell.row, m_idCurrentCell.col, NM_RCLICK);
- }
- }
- #endif
- #if !defined(_WIN32_WCE_NO_PRINTING) && !defined(GRIDCONTROL_NO_PRINTING)
- /////////////////////////////////////////////////////////////////////////////
- // CGridCtrl printing
- // EFW - New print margin support functions
- void CGridCtrl::SetPrintMarginInfo(int nHeaderHeight, int nFooterHeight,
- int nLeftMargin, int nRightMargin, int nTopMargin,
- int nBottomMargin, int nGap)
- {
- // If any parameter is -1, keep the existing setting
- if(nHeaderHeight > -1)
- m_nHeaderHeight = nHeaderHeight;
- if(nFooterHeight > -1)
- m_nFooterHeight = nFooterHeight;
- if(nLeftMargin > -1)
- m_nLeftMargin = nLeftMargin;
- if(nRightMargin > -1)
- m_nRightMargin = nRightMargin;
- if(nTopMargin > -1)
- m_nTopMargin = nTopMargin;
- if(nBottomMargin > -1)
- m_nBottomMargin = nBottomMargin;
- if(nGap > -1)
- m_nGap = nGap;
- }
- void CGridCtrl::GetPrintMarginInfo(int &nHeaderHeight, int &nFooterHeight,
- int &nLeftMargin, int &nRightMargin, int &nTopMargin,
- int &nBottomMargin, int &nGap)
- {
- nHeaderHeight = m_nHeaderHeight;
- nFooterHeight = m_nFooterHeight;
- nLeftMargin = m_nLeftMargin;
- nRightMargin = m_nRightMargin;
- nTopMargin = m_nTopMargin;
- nBottomMargin = m_nBottomMargin;
- nGap = m_nGap;
- }
- void CGridCtrl::Print()
- {
- CDC dc;
- CPrintDialog printDlg(FALSE);
- if (printDlg.DoModal() != IDOK) // Get printer settings from user
- return;
- dc.Attach(printDlg.GetPrinterDC()); // attach a printer DC
- dc.m_bPrinting = TRUE;
- CString strTitle;
- strTitle.LoadString(AFX_IDS_APP_TITLE);
- if( strTitle.IsEmpty() )
- {
- CWnd *pParentWnd = GetParent();
- while (pParentWnd)
- {
- pParentWnd->GetWindowText(strTitle);
- if (strTitle.GetLength()) // can happen if it is a CView, CChildFrm has the title
- break;
- pParentWnd = pParentWnd->GetParent();
- }
- }
- DOCINFO di; // Initialise print doc details
- memset(&di, 0, sizeof (DOCINFO));
- di.cbSize = sizeof (DOCINFO);
- di.lpszDocName = strTitle;
- BOOL bPrintingOK = dc.StartDoc(&di); // Begin a new print job
- CPrintInfo Info;
- Info.m_rectDraw.SetRect(0,0, dc.GetDeviceCaps(HORZRES), dc.GetDeviceCaps(VERTRES));
- OnBeginPrinting(&dc, &Info); // Initialise printing
- for (UINT page = Info.GetMinPage(); page <= Info.GetMaxPage() && bPrintingOK; page++)
- {
- dc.StartPage(); // begin new page
- Info.m_nCurPage = page;
- OnPrint(&dc, &Info); // Print page
- bPrintingOK = (dc.EndPage() > 0); // end page
- }
- OnEndPrinting(&dc, &Info); // Clean up after printing
- if (bPrintingOK)
- dc.EndDoc(); // end a print job
- else
- dc.AbortDoc(); // abort job.
- dc.Detach(); // detach the printer DC
- }
- /////////////////////////////////////////////////////////////////////////////
- // CGridCtrl printing overridables - for Doc/View print/print preview framework
- // EFW - Various changes in the next few functions to support the
- // new print margins and a few other adjustments.
- void CGridCtrl::OnBeginPrinting(CDC *pDC, CPrintInfo *pInfo)
- {
- // OnBeginPrinting() is called after the user has committed to
- // printing by OK'ing the Print dialog, and after the framework
- // has created a CDC object for the printer or the preview view.
- // This is the right opportunity to set up the page range.
- // Given the CDC object, we can determine how many rows will
- // fit on a page, so we can in turn determine how many printed
- // pages represent the entire document.
- ASSERT(pDC && pInfo);
- if (!pDC || !pInfo) return;
- // Get a DC for the current window (will be a screen DC for print previewing)
- CDC *pCurrentDC = GetDC(); // will have dimensions of the client area
- if (!pCurrentDC) return;
- CSize PaperPixelsPerInch(pDC->GetDeviceCaps(LOGPIXELSX), pDC->GetDeviceCaps(LOGPIXELSY));
- CSize ScreenPixelsPerInch(pCurrentDC->GetDeviceCaps(LOGPIXELSX), pCurrentDC->GetDeviceCaps(LOGPIXELSY));
- // Create the printer font
- int nFontSize = -10;
- CString strFontName = "Arial";
- m_PrinterFont.CreateFont(nFontSize, 0,0,0, FW_NORMAL, 0,0,0, DEFAULT_CHARSET,
- OUT_CHARACTER_PRECIS, CLIP_CHARACTER_PRECIS, DEFAULT_QUALITY,
- DEFAULT_PITCH | FF_DONTCARE, strFontName);
- CFont *pOldFont = pDC->SelectObject(&m_PrinterFont);
- // Get the average character width (in GridCtrl units) and hence the margins
- m_CharSize = pDC->GetTextExtent(_T("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSATUVWXYZ"),52);
- m_CharSize.cx /= 52;
- int nMargins = (m_nLeftMargin+m_nRightMargin)*m_CharSize.cx;
- // Get the page sizes (physical and logical)
- m_PaperSize = CSize(pDC->GetDeviceCaps(HORZRES), pDC->GetDeviceCaps(VERTRES));
- if( m_bWysiwygPrinting)
- {
- m_LogicalPageSize.cx = ScreenPixelsPerInch.cx * m_PaperSize.cx / PaperPixelsPerInch.cx * 3 / 4;
- m_LogicalPageSize.cy = ScreenPixelsPerInch.cy * m_PaperSize.cy / PaperPixelsPerInch.cy * 3 / 4;
- }
- else
- {
- m_PaperSize = CSize(pDC->GetDeviceCaps(HORZRES), pDC->GetDeviceCaps(VERTRES));
- m_LogicalPageSize.cx = GetVirtualWidth()+nMargins;
- #ifdef _WIN32_WCE
- m_LogicalPageSize.cy = (m_LogicalPageSize.cx * m_PaperSize.cy) / m_PaperSize.cx;
- #else
- m_LogicalPageSize.cy = MulDiv(m_LogicalPageSize.cx, m_PaperSize.cy, m_PaperSize.cx);
- #endif
- }
- m_nPageHeight = m_LogicalPageSize.cy - GetFixedRowHeight()
- - (m_nHeaderHeight+m_nFooterHeight + 2*m_nGap)*m_CharSize.cy;
- // Get the number of pages. Assumes no row is bigger than the page size.
- int nTotalRowHeight = 0;
- m_nNumPages = 1;
- for (int row = GetFixedRowCount(); row < GetRowCount(); row++)
- {
- nTotalRowHeight += GetRowHeight(row);
- if (nTotalRowHeight > m_nPageHeight) {
- m_nNumPages++;
- nTotalRowHeight = GetRowHeight(row);
- }
- }
- // now, figure out how many additional pages must print out if rows ARE bigger
- // than page size
- int iColumnOffset = 0;
- int i1;
- for( i1=0; i1 < GetFixedColumnCount(); i1++)
- {
- iColumnOffset += GetColumnWidth( i1);
- }
- m_nPageWidth = m_LogicalPageSize.cx - iColumnOffset
- - nMargins;
- m_nPageMultiplier = 1;
- if( m_bWysiwygPrinting)
- {
- int iTotalRowWidth = 0;
- for( i1 = GetFixedColumnCount(); i1 < GetColumnCount(); i1++)
- {
- iTotalRowWidth += GetColumnWidth( i1);
- if( iTotalRowWidth > m_nPageWidth)
- {
- m_nPageMultiplier++;
- iTotalRowWidth = GetColumnWidth( i1);
- }
- }
- m_nNumPages *= m_nPageMultiplier;
- }
- // Set up the print info
- pInfo->SetMaxPage(m_nNumPages);
- pInfo->m_nCurPage = 1; // start printing at page# 1
- ReleaseDC(pCurrentDC);
- pDC->SelectObject(pOldFont);
- }
- void CGridCtrl::OnPrint(CDC *pDC, CPrintInfo *pInfo)
- {
- if (!pDC || !pInfo)
- return;
- //CRect rcPage(pInfo->m_rectDraw);
- CFont *pOldFont = pDC->SelectObject(&m_PrinterFont);
- // Set the page map mode to use GridCtrl units, and setup margin
- pDC->SetMapMode(MM_ANISOTROPIC);
- pDC->SetWindowExt(m_LogicalPageSize);
- pDC->SetViewportExt(m_PaperSize);
- pDC->SetWindowOrg(-m_nLeftMargin * m_CharSize.cx, 0);
- // Header
- pInfo->m_rectDraw.top = 0;
- pInfo->m_rectDraw.left = 0;
- pInfo->m_rectDraw.right = m_LogicalPageSize.cx - (m_nLeftMargin + m_nRightMargin) * m_CharSize.cx;
- pInfo->m_rectDraw.bottom = m_nHeaderHeight * m_CharSize.cy;
- PrintHeader(pDC, pInfo);
- pDC->OffsetWindowOrg(0, -m_nHeaderHeight * m_CharSize.cy);
- // Gap between header and column headings
- pDC->OffsetWindowOrg(0, -m_nGap * m_CharSize.cy);
- pDC->OffsetWindowOrg(0, -GetFixedRowHeight());
- // We need to find out which row to start printing for this page.
- int nTotalRowHeight = 0;
- UINT nNumPages = 1;
- m_nCurrPrintRow = GetFixedRowCount();
- // Not only the row, but we need to figure out column, too
- // Can print 4 pages, where page 1 and 2 represent the same rows but
- // with different WIDE columns.
- //
- // .......
- // .1 .2 . If representing page 3 --> iPageIfIgnoredWideCols = 2
- // ....... iWideColPageOffset = 0
- // .3 .4 . If representing page 2 --> iPageIfIgnoredWideCols = 1
- // ....... iWideColPageOffset = 1
- int iPageIfIgnoredWideCols = pInfo->m_nCurPage / m_nPageMultiplier;
- int iWideColPageOffset = pInfo->m_nCurPage - ( iPageIfIgnoredWideCols * m_nPageMultiplier);
- if( iWideColPageOffset > 0)
- iPageIfIgnoredWideCols++;
- if( iWideColPageOffset == 0)
- iWideColPageOffset = m_nPageMultiplier;
- iWideColPageOffset--;
- // calculate current print row based on iPageIfIgnoredWideCols
- while( m_nCurrPrintRow < GetRowCount()
- && (int)nNumPages < iPageIfIgnoredWideCols)
- {
- nTotalRowHeight += GetRowHeight(m_nCurrPrintRow);
- if (nTotalRowHeight > m_nPageHeight) {
- nNumPages++;
- if ((int)nNumPages == iPageIfIgnoredWideCols) break;
- nTotalRowHeight = GetRowHeight(m_nCurrPrintRow);
- }
- m_nCurrPrintRow++;
- }
- m_nPrintColumn = GetFixedColumnCount();
- int iTotalRowWidth = 0;
- int i1, i2;
- // now, calculate which print column to start displaying
- for( i1 = 0; i1 < iWideColPageOffset; i1++)
- {
- for( i2 = m_nPrintColumn; i2 < GetColumnCount(); i2++)
- {
- iTotalRowWidth += GetColumnWidth( i2);
- if( iTotalRowWidth > m_nPageWidth)
- {
- m_nPrintColumn = i2;
- iTotalRowWidth = 0;
- break;
- }
- }
- }
- PrintRowButtons( pDC, pInfo); // print row buttons on each page
- int iColumnOffset = 0;
- for( i1=0; i1 < GetFixedColumnCount(); i1++)
- {
- iColumnOffset += GetColumnWidth( i1);
- }
- // Print the column headings
- pInfo->m_rectDraw.bottom = GetFixedRowHeight();
- if( m_nPrintColumn == GetFixedColumnCount())
- {
- // have the column headings fcn draw the upper left fixed cells
- // for the very first columns, only
- pDC->OffsetWindowOrg( 0, +GetFixedRowHeight());
- m_nPageWidth += iColumnOffset;
- m_nPrintColumn = 0;
- PrintColumnHeadings(pDC, pInfo);
- m_nPageWidth -= iColumnOffset;
- m_nPrintColumn = GetFixedColumnCount();
- pDC->OffsetWindowOrg( -iColumnOffset, -GetFixedRowHeight());
- }
- else
- {
- pDC->OffsetWindowOrg( -iColumnOffset, +GetFixedRowHeight());
- PrintColumnHeadings(pDC, pInfo);
- pDC->OffsetWindowOrg( 0, -GetFixedRowHeight());
- }
- if (m_nCurrPrintRow >= GetRowCount()) return;
- // Draw as many rows as will fit on the printed page.
- // Clip the printed page so that there is no partially shown
- // row at the bottom of the page (the same row which will be fully
- // shown at the top of the next page).
- BOOL bFirstPrintedRow = TRUE;
- CRect rect;
- rect.bottom = -1;
- while (m_nCurrPrintRow < GetRowCount())
- {
- rect.top = rect.bottom+1;
- rect.bottom = rect.top + GetRowHeight(m_nCurrPrintRow) - 1;
- if (rect.bottom > m_nPageHeight) break; // Gone past end of page
- rect.right = -1;
- // modified to allow printing of wide grids on multiple pages
- for (int col = m_nPrintColumn; col < GetColumnCount(); col++)
- {
- rect.left = rect.right+1;
- rect.right = rect.left
- + GetColumnWidth( col)
- - 1;
- if( rect.right > m_nPageWidth)
- break;
- CGridCellBase* pCell = GetCell(m_nCurrPrintRow, col);
- if (pCell)
- pCell->PrintCell(pDC, m_nCurrPrintRow, col, rect);
- if (m_nGridLines == GVL_BOTH || m_nGridLines == GVL_HORZ)
- {
- int Overlap = (col == 0)? 0:1;
- pDC->MoveTo(rect.left-Overlap, rect.bottom);
- pDC->LineTo(rect.right, rect.bottom);
- if (m_nCurrPrintRow == 0) {
- pDC->MoveTo(rect.left-Overlap, rect.top);
- pDC->LineTo(rect.right, rect.top);
- }
- }
- if (m_nGridLines == GVL_BOTH || m_nGridLines == GVL_VERT)
- {
- int Overlap = (bFirstPrintedRow)? 0:1;
- pDC->MoveTo(rect.right, rect.top-Overlap);
- pDC->LineTo(rect.right, rect.bottom);
- if (col == 0) {
- pDC->MoveTo(rect.left, rect.top-Overlap);
- pDC->LineTo(rect.left, rect.bottom);
- }
- }
- }
- m_nCurrPrintRow++;
- bFirstPrintedRow = FALSE;
- }
- // Footer
- pInfo->m_rectDraw.bottom = m_nFooterHeight * m_CharSize.cy;
- pDC->SetWindowOrg( -m_nLeftMargin * m_CharSize.cx,
- -m_LogicalPageSize.cy + m_nFooterHeight * m_CharSize.cy);
- PrintFooter(pDC, pInfo);
- // SetWindowOrg back for next page
- pDC->SetWindowOrg(0,0);
- pDC->SelectObject(pOldFont);
- }
- void CGridCtrl::PrintColumnHeadings(CDC *pDC, CPrintInfo* /*pInfo*/)
- {
- CFont *pOldFont = pDC->SelectObject(&m_PrinterFont);
- CRect rect;
- rect.bottom = -1;
- BOOL bFirst = TRUE;
- // modified to allow column hdr printing of multi-page wide grids
- for (int row = 0; row < GetFixedRowCount(); row++)
- {
- rect.top = rect.bottom+1;
- rect.bottom = rect.top + GetRowHeight(row) - 1;
- rect.right = -1;
- for (int col = m_nPrintColumn; col < GetColumnCount(); col++)
- {
- rect.left = rect.right+1;
- rect.right = rect.left
- + GetColumnWidth( col)
- - 1;
- if( rect.right > m_nPageWidth)
- break;
- CGridCellBase* pCell = GetCell(row, col);
- if (pCell)
- pCell->PrintCell(pDC, row, col, rect);
- if (m_nGridLines == GVL_BOTH || m_nGridLines == GVL_HORZ)
- {
- int Overlap = (col == 0)? 0:1;
- pDC->MoveTo(rect.left-Overlap, rect.bottom);
- pDC->LineTo(rect.right, rect.bottom);
- if (row == 0) {
- pDC->MoveTo(rect.left-Overlap, rect.top);
- pDC->LineTo(rect.right, rect.top);
- }
- }
- if (m_nGridLines == GVL_BOTH || m_nGridLines == GVL_VERT)
- {
- int Overlap = (row == 0)? 0:1;
- pDC->MoveTo(rect.right, rect.top-Overlap);
- pDC->LineTo(rect.right, rect.bottom);
- if( bFirst) {
- pDC->MoveTo(rect.left-1, rect.top-Overlap);
- pDC->LineTo(rect.left-1, rect.bottom);
- bFirst = FALSE;
- }
- }
- }
- }
- pDC->SelectObject(pOldFont);
- }
- /*****************************************************************************
- Prints line of row buttons on each page of the printout. Assumes that
- the window origin is setup before calling
- *****************************************************************************/
- void CGridCtrl::PrintRowButtons(CDC *pDC, CPrintInfo* /*pInfo*/)
- {
- CFont *pOldFont = pDC->SelectObject(&m_PrinterFont);
- CRect rect;
- rect.right = -1;
- BOOL bFirst = TRUE;
- for( int iCol = 0; iCol < GetFixedColumnCount(); iCol++)
- {
- rect.left = rect.right+1;
- rect.right = rect.left
- + GetColumnWidth( iCol)
- - 1;
- rect.bottom = -1;
- for( int iRow = m_nCurrPrintRow; iRow < GetRowCount(); iRow++)
- {
- rect.top = rect.bottom+1;
- rect.bottom = rect.top + GetRowHeight( iRow) - 1;
- if( rect.bottom > m_nPageHeight)
- break;
- CGridCellBase* pCell = GetCell(iRow, iCol);
- if (pCell)
- pCell->PrintCell(pDC, iRow, iCol, rect);
- if (m_nGridLines == GVL_BOTH || m_nGridLines == GVL_HORZ)
- {
- int Overlap = (iCol == 0)? 0:1;
- pDC->MoveTo(rect.left-Overlap, rect.bottom);
- pDC->LineTo(rect.right, rect.bottom);
- if( bFirst) {
- pDC->MoveTo(rect.left-Overlap, rect.top-1);
- pDC->LineTo(rect.right, rect.top-1);
- bFirst = FALSE;
- }
- }
- if (m_nGridLines == GVL_BOTH || m_nGridLines == GVL_VERT)
- {
- int Overlap = (iRow == 0)? 0:1;
- pDC->MoveTo(rect.right, rect.top-Overlap);
- pDC->LineTo(rect.right, rect.bottom);
- if (iCol == 0) {
- pDC->MoveTo(rect.left, rect.top-Overlap);
- pDC->LineTo(rect.left, rect.bottom);
- }
- }
- }
- }
- pDC->SelectObject(pOldFont);
- }
- void CGridCtrl::PrintHeader(CDC *pDC, CPrintInfo *pInfo)
- {
- // print App title on top right margin
- CString strRight;
- strRight.LoadString(AFX_IDS_APP_TITLE);
- // print parent window title in the centre (Gert Rijs)
- CString strCenter;
- CWnd *pParentWnd = GetParent();
- while (pParentWnd)
- {
- pParentWnd->GetWindowText(strCenter);
- if (strCenter.GetLength()) // can happen if it is a CView, CChildFrm has the title
- break;
- pParentWnd = pParentWnd->GetParent();
- }
- CFont BoldFont;
- LOGFONT lf;
- //create bold font for header and footer
- VERIFY(m_PrinterFont.GetLogFont(&lf));
- lf.lfWeight = FW_BOLD;
- lf.lfWidth=18;
- lf.lfHeight=18;
- VERIFY(BoldFont.CreateFontIndirect(&lf));
- CFont *pNormalFont = pDC->SelectObject(&BoldFont);
- int nPrevBkMode = pDC->SetBkMode(TRANSPARENT);
- CRect rc(pInfo->m_rectDraw);
- if( !strCenter.IsEmpty() )
- pDC->DrawText( strCenter, &rc, DT_CENTER | DT_SINGLELINE | DT_NOPREFIX | DT_VCENTER);
- if( !strRight.IsEmpty() )
- pDC->DrawText( strRight, &rc, DT_RIGHT | DT_SINGLELINE | DT_NOPREFIX | DT_VCENTER);
- pDC->SetBkMode(nPrevBkMode);
- pDC->SelectObject(pNormalFont);
- BoldFont.DeleteObject();
- // draw ruled-line across top
- pDC->SelectStockObject(BLACK_PEN);
- pDC->MoveTo(rc.left, rc.bottom);
- pDC->LineTo(rc.right, rc.bottom);
- }
- //print footer with a line and date, and page number
- void CGridCtrl::PrintFooter(CDC *pDC, CPrintInfo *pInfo)
- {
- // page numbering on left
- CString strLeft;
- strLeft.Format(_T("ҳ: %d of %d"), pInfo->m_nCurPage, pInfo->GetMaxPage() );
- // date and time on the right
- CString strRight;
- CTime t = CTime::GetCurrentTime();
- strRight = t.Format(_T("%c"));
- CRect rc(pInfo->m_rectDraw);
- // draw ruled line on bottom
- pDC->SelectStockObject(BLACK_PEN);
- pDC->MoveTo(rc.left, rc.top);
- pDC->LineTo(rc.right, rc.top);
- CFont BoldFont;
- LOGFONT lf;
- //create bold font for header and footer
- m_PrinterFont.GetLogFont(&lf);
- lf.lfWeight = FW_BOLD;
- BoldFont.CreateFontIndirect(&lf);
- CFont *pNormalFont = pDC->SelectObject(&BoldFont);
- int nPrevBkMode = pDC->SetBkMode(TRANSPARENT);
- // EFW - Bug fix - Force text color to black. It doesn't always
- // get set to a printable color when it gets here.
- pDC->SetTextColor(RGB(0, 0, 0));
- if( !strLeft.IsEmpty() )
- pDC->DrawText( strLeft, &rc, DT_LEFT | DT_SINGLELINE | DT_NOPREFIX | DT_VCENTER);
- if( !strRight.IsEmpty() )
- pDC->DrawText( strRight, &rc, DT_RIGHT | DT_SINGLELINE | DT_NOPREFIX | DT_VCENTER);
- pDC->SetBkMode(nPrevBkMode);
- pDC->SelectObject(pNormalFont);
- BoldFont.DeleteObject();
- }
- void CGridCtrl::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
- {
- m_PrinterFont.DeleteObject();
- }
- #endif // !defined(_WIN32_WCE_NO_PRINTING) && !defined(GRIDCONTROL_NO_PRINTING)
- #ifndef _WIN32_WCE
- /////////////////////////////////////////////////////////////////////////////
- // CGridCtrl persistance
- BOOL CGridCtrl::Save(LPCTSTR filename)
- {
- CStdioFile File;
- CFileException ex;
- if (!File.Open(filename, CFile::modeWrite | CFile::modeCreate| CFile::typeText, &ex))
- {
- ex.ReportError();
- return FALSE;
- }
- TRY
- {
- int nNumColumns = GetColumnCount();
- for (int i = 0; i < nNumColumns; i++)
- {
- File.WriteString(GetItemText(0,i));
- File.WriteString((i==(nNumColumns-1))? _T("n"):_T(","));
- }
- for (i = 0; i < GetRowCount(); i++)
- {
- for (int j = 0; j < nNumColumns; j++)
- {
- File.WriteString(GetItemText(i,j));
- File.WriteString((j==(nNumColumns-1))? _T("n"):_T(","));
- }
- }
- File.Close();
- }
- CATCH (CFileException, e)
- {
- AfxMessageBox(_T("Unable to save grid list"));
- return FALSE;
- }
- END_CATCH
- return TRUE;
- }
- BOOL CGridCtrl::Load(LPCTSTR filename)
- {
- if (GetVirtualMode())
- return FALSE;
- TCHAR *token, *end;
- TCHAR buffer[1024];
- CStdioFile File;
- CFileException ex;
- if (!File.Open(filename, CFile::modeRead | CFile::typeText))
- {
- ex.ReportError();
- return FALSE;
- }
- DeleteAllItems();
- TRY
- {
- // Read Header off file
- File.ReadString(buffer, 1024);
- // Get first token
- for (token=buffer, end=buffer;
- *end && (*end != _T(',')) && (*end != _T('n'));
- end++)
- ;
- if ((*end == _T(' ')) && (token == end))
- token = NULL;
- *end = _T(' ');
- while (token)
- {
- InsertColumn(token);
- // Get next token
- for (token=++end; *end && (*end != _T(',')) && (*end != _T('n'));
- end++)
- ;
- if ((*end == _T(' ')) && (token == end))
- token = NULL;
- *end = _T(' ');
- }
- // Read in rest of data
- int nItem = 0;
- while (File.ReadString(buffer, 1024))
- {
- // Get first token
- for (token=buffer, end=buffer;
- *end && (*end != _T(',')) && (*end != _T('n')); end++)
- ;
- if ((*end == _T(' ')) && (token == end))
- token = NULL;
- *end = _T(' ');
- int nSubItem = 0;
- while (token)
- {
- if (!nSubItem)
- InsertRow(token);
- else
- SetItemText(nItem, nSubItem, token);
- // Get next token
- for (token=++end; *end && (*end != _T(',')) && (*end != _T('n'));
- end++)
- ;
- if ((*end == _T(' ')) && (token == end))
- token = NULL;
- *end = _T(' ');
- nSubItem++;
- }
- nItem++;
- }
- AutoSizeColumns(GetAutoSizeStyle());
- File.Close();
- }
- CATCH (CFileException, e)
- {
- AfxMessageBox(_T("Unable to load grid data"));
- return FALSE;
- }
- END_CATCH
- return TRUE;
- }
- #endif
- /////////////////////////////////////////////////////////////////////////////
- // CGridCtrl overrideables
- #ifndef GRIDCONTROL_NO_DRAGDROP
- // This is no longer needed since I've changed to OLE drag and drop - but it's
- // still cool code. :)
- CImageList* CGridCtrl::CreateDragImage(CPoint *pHotSpot)
- {
- CDC* pDC = GetDC();
- if (!pDC)
- return NULL;
- CRect rect;
- CCellID cell = GetFocusCell();
- if (!GetCellRect(cell.row, cell.col, rect))
- return NULL;
- // Translate coordinate system
- rect.BottomRight() = CPoint(rect.Width(), rect.Height());
- rect.TopLeft() = CPoint(0, 0);
- *pHotSpot = rect.BottomRight();
- // Create a new imagelist (the caller of this function has responsibility
- // for deleting this list)
- CImageList* pList = new CImageList;
- if (!pList || !pList->Create(rect.Width(), rect.Height(), ILC_MASK, 1, 1))
- {
- if (pList)
- delete pList;
- return NULL;
- }
- // Create mem DC and bitmap
- CDC MemDC;
- CBitmap bm;
- MemDC.CreateCompatibleDC(pDC);
- bm.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
- CBitmap* pOldBitmap = MemDC.SelectObject(&bm);
- MemDC.SetWindowOrg(0, 0);
- // Draw cell onto bitmap in memDC
- CGridCellBase* pCell = GetCell(cell.row, cell.col);
- if (pCell)
- pCell->Draw(&MemDC, cell.row, cell.col, rect, FALSE);
- // Clean up
- MemDC.SelectObject(pOldBitmap);
- ReleaseDC(pDC);
- // Add the bitmap we just drew to the image list.
- pList->Add(&bm, GetDefaultCell(FALSE, FALSE)->GetBackClr());
- bm.DeleteObject();
- return pList;
- }
- #endif
- void CGridCtrl::OnFixedRowClick(CCellID& cell)
- {
- if (!IsValid(cell))
- return;
- if (GetHeaderSort())
- {
- CWaitCursor waiter;
- if (cell.col == GetSortColumn())
- SortTextItems(cell.col, !GetSortAscending());
- else
- SortTextItems(cell.col, TRUE);
- Invalidate();
- }
- if (GetFixedRowSelection())
- {
- if (cell.col < GetFixedColumnCount())
- {
- m_MouseMode = MOUSE_SELECT_ALL;
- OnSelecting(cell);
- }
- else
- {
- m_MouseMode = MOUSE_SELECT_COL;
- OnSelecting(cell);
- }
- }
- }
- void CGridCtrl::OnFixedColumnClick(CCellID& cell)
- {
- if (!IsValid(cell))
- return;
- // if (m_bListMode && (GetItemState(cell.row, m_nFixedCols) & GVNI_SELECTED))
- // {
- // OnEditCell(cell.row, cell.col, VK_LBUTTON);
- // return;
- // }
- if (GetFixedColumnSelection())
- {
- if (cell.row < GetFixedRowCount())
- {
- m_MouseMode = MOUSE_SELECT_ALL;
- OnSelecting(cell);
- }
- else
- {
- m_MouseMode = MOUSE_SELECT_ROW;
- OnSelecting(cell);
- }
- }
- }
- // Gets the extent of the text pointed to by str (no CDC needed)
- // By default this uses the selected font (which is a bigger font)
- CSize CGridCtrl::GetTextExtent(int nRow, int nCol, LPCTSTR str)
- {
- CGridCellBase* pCell = GetCell(nRow, nCol);
- if (!pCell)
- return CSize(0, 0);
- else
- return pCell->GetTextExtent(str);
- }
- void CGridCtrl::OnEditCell(int nRow, int nCol, CPoint point, UINT nChar)
- {
- #ifndef GRIDCONTROL_NO_TITLETIPS
- m_TitleTip.Hide(); // hide any titletips
- #endif
- // Can we do it?
- CCellID cell(nRow, nCol);
- if (!IsValid(cell) || !IsCellEditable(nRow, nCol))
- return;
- // Can we see what we are doing?
- EnsureVisible(nRow, nCol);
- if (!IsCellVisible(nRow, nCol))
- return;
- // Where, exactly, are we gonna do it??
- CRect rect;
- if (!GetCellRect(cell, rect))
- return;
- // Tell Mum and Dad what we are doing
- SendMessageToParent(nRow, nCol, GVN_BEGINLABELEDIT);
- // Let's do it...
- CGridCellBase* pCell = GetCell(nRow, nCol);
- if (pCell)
- pCell->Edit(nRow, nCol, rect, point, IDC_INPLACE_CONTROL, nChar);
- }
- void CGridCtrl::EndEditing()
- {
- CCellID cell = GetFocusCell();
- if (!IsValid(cell)) return;
- CGridCellBase *pCell = GetCell(cell.row, cell.col);
- if (pCell)
- pCell->EndEdit();
- }
- void CGridCtrl::OnEndEditCell(int nRow, int nCol, CString str)
- {
- CString strCurrent = GetItemText(nRow, nCol);
- if (strCurrent != str)
- {
- SetModified(TRUE, nRow, nCol);
- SetItemText(nRow, nCol, str);
- }
- CGridCellBase* pCell = GetCell(nRow, nCol);
- if (pCell)
- pCell->OnEndEdit();
- }
- CString CGridCtrl::GetItemText(int nRow, int nCol) const
- {
- if (nRow < 0 || nRow >= m_nRows || nCol < 0 || nCol >= m_nCols)
- return _T("");
- CGridCellBase* pCell = GetCell(nRow, nCol);
- ASSERT(pCell);
- if (!pCell)
- return _T("");
- return pCell->GetText();
- }