GridCellBase.cpp
上传用户:jzscgs158
上传日期:2022-05-25
资源大小:8709k
文件大小:24k
源码类别:

百货/超市行业

开发平台:

Visual C++

  1. // GridCellBase.cpp : implementation file
  2. //
  3. // MFC Grid Control - Main grid cell base class
  4. //
  5. // Provides the implementation for the base cell type of the
  6. // grid control. No data is stored (except for state) but default
  7. // implementations of drawing, printingetc provided. MUST be derived
  8. // from to be used.
  9. //
  10. // Written by Chris Maunder <cmaunder@mail.com>
  11. // Copyright (c) 1998-2000. All Rights Reserved.
  12. //
  13. // This code may be used in compiled form in any way you desire. This
  14. // file may be redistributed unmodified by any means PROVIDING it is 
  15. // not sold for profit without the authors written consent, and 
  16. // providing that this notice and the authors name and all copyright 
  17. // notices remains intact. 
  18. //
  19. // An email letting me know how you are using it would be nice as well. 
  20. //
  21. // This file is provided "as is" with no expressed or implied warranty.
  22. // The author accepts no liability for any damage/loss of business that
  23. // this product may cause.
  24. //
  25. // For use with CGridCtrl v2.20
  26. //
  27. // History:
  28. // Ken Bertelson - 12 Apr 2000 - Split CGridCell into CGridCell and CGridCellBase
  29. // C Maunder     - 19 May 2000 - Fixed sort arrow drawing (Ivan Ilinov)
  30. //
  31. // NOTES: Each grid cell should take care of it's own drawing, though the Draw()
  32. //        method takes an "erase background" paramter that is called if the grid
  33. //        decides to draw the entire grid background in on hit. Certain ambient
  34. //        properties such as the default font to use, and hints on how to draw
  35. //        fixed cells should be fetched from the parent grid. The grid trusts the
  36. //        cells will behave in a certain way, and the cells trust the grid will
  37. //        supply accurate information.
  38. //        
  39. /////////////////////////////////////////////////////////////////////////////
  40. #include "stdafx.h"
  41. #include "GridCtrl.h"
  42. #include "GridCellBase.h"
  43. #ifdef _DEBUG
  44. #define new DEBUG_NEW
  45. #undef THIS_FILE
  46. static char THIS_FILE[] = __FILE__;
  47. #endif
  48. IMPLEMENT_DYNCREATE(CGridCellBase, CObject)
  49. /////////////////////////////////////////////////////////////////////////////
  50. // GridCellBase
  51. CGridCellBase::CGridCellBase()
  52. {
  53.     Reset();
  54. }
  55. CGridCellBase::~CGridCellBase()
  56. {
  57. }
  58. /////////////////////////////////////////////////////////////////////////////
  59. // GridCellBase Operations
  60. void CGridCellBase::Reset()
  61. {
  62.     m_nState  = 0;
  63. }
  64. void CGridCellBase::operator=(const CGridCellBase& cell)
  65. {
  66.     SetGrid(cell.GetGrid());    // do first in case of dependencies
  67.     SetText(cell.GetText());
  68.     SetImage(cell.GetImage());
  69.     SetData(cell.GetData());
  70.     SetState(cell.GetState());
  71.     SetFormat(cell.GetFormat());
  72.     SetTextClr(cell.GetTextClr());
  73.     SetBackClr(cell.GetBackClr());
  74.     SetFont(cell.GetFont());
  75.     SetMargin(cell.GetMargin());
  76. }
  77. /////////////////////////////////////////////////////////////////////////////
  78. // GridCell Attributes
  79. // Returns a pointer to a cell that holds default values for this particular type of cell
  80. CGridCellBase* CGridCellBase::GetDefaultCell() const
  81. {
  82.     if (GetGrid())
  83.         return GetGrid()->GetDefaultCell(IsFixedRow(), IsFixedCol());
  84.     return NULL;
  85. }
  86. /////////////////////////////////////////////////////////////////////////////
  87. // GridCell Operations
  88. // EFW - Various changes to make it draw cells better when using alternate
  89. // color schemes.  Also removed printing references as that's now done
  90. // by PrintCell() and fixed the sort marker so that it doesn't draw out
  91. // of bounds.
  92. BOOL CGridCellBase::Draw(CDC* pDC, int nRow, int nCol, CRect rect,  BOOL bEraseBkgnd /*=TRUE*/)
  93. {
  94.     CGridCtrl* pGrid = GetGrid();
  95.     ASSERT(pGrid);
  96.     if (!pGrid || !pDC)
  97.         return FALSE;
  98.     if( rect.Width() <= 0 || rect.Height() <= 0)  // prevents imagelist item from drawing even
  99.         return FALSE;                             //  though cell is hidden
  100.     //TRACE3("Drawing %scell %d, %dn", IsFixed()? _T("Fixed ") : _T(""), nRow, nCol);
  101.     int nSavedDC = pDC->SaveDC();
  102.     pDC->SetBkMode(TRANSPARENT);
  103.     // Get the default cell implementation for this kind of cell. We use it if this cell
  104.     // has anything marked as "default"
  105.     CGridDefaultCell *pDefaultCell = (CGridDefaultCell*) GetDefaultCell();
  106.     if (!pDefaultCell)
  107.         return FALSE;
  108.     // Set up text and background colours
  109.     COLORREF TextClr, TextBkClr;
  110.     TextClr = (GetTextClr() == CLR_DEFAULT)? pDefaultCell->GetTextClr() : GetTextClr();
  111.     if (GetBackClr() == CLR_DEFAULT)
  112.         TextBkClr = pDefaultCell->GetBackClr();
  113.     else
  114.     {
  115.         bEraseBkgnd = TRUE;
  116.         TextBkClr = GetBackClr();
  117.     }
  118.     // Draw cell background and highlighting (if necessary)
  119.     if ( IsFocused() || IsDropHighlighted() )
  120.     {
  121.         // Always draw even in list mode so that we can tell where the
  122.         // cursor is at.  Use the highlight colors though.
  123.         if(GetState() & GVIS_SELECTED)
  124.         {
  125.             TextBkClr = ::GetSysColor(COLOR_HIGHLIGHT);
  126.             TextClr = ::GetSysColor(COLOR_HIGHLIGHTTEXT);
  127.             bEraseBkgnd = TRUE;
  128.         }
  129.         rect.right++; rect.bottom++;    // FillRect doesn't draw RHS or bottom
  130.         if (bEraseBkgnd)
  131.         {
  132.             TRY 
  133.             {
  134.                 CBrush brush(TextBkClr);
  135.                 pDC->FillRect(rect, &brush);
  136.             } 
  137.             CATCH(CResourceException, e)
  138.             {
  139.                 //e->ReportError();
  140.             }
  141.             END_CATCH
  142.         }
  143.         // Don't adjust frame rect if no grid lines so that the
  144.         // whole cell is enclosed.
  145.         if(pGrid->GetGridLines() != GVL_NONE)
  146.         {
  147.             rect.right--;
  148.             rect.bottom--;
  149.         }
  150.         if (pGrid->GetFrameFocusCell())
  151.         {
  152.                 // Use same color as text to outline the cell so that it shows
  153.                 // up if the background is black.
  154.             TRY 
  155.             {
  156.                 CBrush brush(TextClr);
  157.                 pDC->FrameRect(rect, &brush);
  158.             }
  159.             CATCH(CResourceException, e)
  160.             {
  161.                 //e->ReportError();
  162.             }
  163.             END_CATCH
  164.         }
  165.         pDC->SetTextColor(TextClr);
  166.         // Adjust rect after frame draw if no grid lines
  167.         if(pGrid->GetGridLines() == GVL_NONE)
  168.         {
  169.             rect.right--;
  170.             rect.bottom--;
  171.         }
  172.         rect.DeflateRect(1,1);
  173.     }
  174.     else if ((GetState() & GVIS_SELECTED))
  175.     {
  176.         rect.right++; rect.bottom++;    // FillRect doesn't draw RHS or bottom
  177.         pDC->FillSolidRect(rect, ::GetSysColor(COLOR_HIGHLIGHT));
  178.         rect.right--; rect.bottom--;
  179.         pDC->SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
  180.     }
  181.     else
  182.     {
  183.         if (bEraseBkgnd)
  184.         {
  185.             rect.right++; rect.bottom++;    // FillRect doesn't draw RHS or bottom
  186.             CBrush brush(TextBkClr);
  187.             pDC->FillRect(rect, &brush);
  188.             rect.right--; rect.bottom--;
  189.         }
  190.         pDC->SetTextColor(TextClr);
  191.     }
  192.     // Draw lines only when wanted
  193.     if (IsFixed() && pGrid->GetGridLines() != GVL_NONE)
  194.     {
  195.         CCellID FocusCell = pGrid->GetFocusCell();
  196.         // As above, always show current location even in list mode so
  197.         // that we know where the cursor is at.
  198.         BOOL bHiliteFixed = pGrid->GetTrackFocusCell() && pGrid->IsValid(FocusCell) &&
  199.                             (FocusCell.row == nRow || FocusCell.col == nCol);
  200.         // If this fixed cell is on the same row/col as the focus cell,
  201.         // highlight it.
  202.         if (bHiliteFixed)
  203.         {
  204.             rect.right++; rect.bottom++;
  205.             pDC->DrawEdge(rect, BDR_SUNKENINNER /*EDGE_RAISED*/, BF_RECT);
  206.             rect.DeflateRect(1,1);
  207.         }
  208.         else
  209.         {
  210.             CPen lightpen(PS_SOLID, 1,  ::GetSysColor(COLOR_3DHIGHLIGHT)),
  211.                 darkpen(PS_SOLID,  1, ::GetSysColor(COLOR_3DDKSHADOW)),
  212.                 *pOldPen = pDC->GetCurrentPen();
  213.             pDC->SelectObject(&lightpen);
  214.             pDC->MoveTo(rect.right, rect.top);
  215.             pDC->LineTo(rect.left, rect.top);
  216.             pDC->LineTo(rect.left, rect.bottom);
  217.             pDC->SelectObject(&darkpen);
  218.             pDC->MoveTo(rect.right, rect.top);
  219.             pDC->LineTo(rect.right, rect.bottom);
  220.             pDC->LineTo(rect.left, rect.bottom);
  221.             pDC->SelectObject(pOldPen);
  222.             rect.DeflateRect(1,1);
  223.         }
  224.     }
  225.     // Draw Text and image
  226.     CFont* pFont = GetFontObject();
  227.     ASSERT(pFont);
  228.     if (pFont)
  229.         pDC->SelectObject(pFont);
  230.     rect.DeflateRect(GetMargin(), 0);
  231.     if (pGrid->GetImageList() && GetImage() >= 0)
  232.     {
  233.         IMAGEINFO Info;
  234.         if (pGrid->GetImageList()->GetImageInfo(GetImage(), &Info))
  235.         {
  236.             //  would like to use a clipping region but seems to have issue
  237.             //  working with CMemDC directly.  Instead, don't display image
  238.             //  if any part of it cut-off
  239.             //
  240.             // CRgn rgn;
  241.             // rgn.CreateRectRgnIndirect(rect);
  242.             // pDC->SelectClipRgn(&rgn);
  243.             // rgn.DeleteObject();
  244.             int nImageWidth = Info.rcImage.right-Info.rcImage.left+1;
  245.             int nImageHeight = Info.rcImage.bottom-Info.rcImage.top+1;
  246.             if( nImageWidth + rect.left <= rect.right + (int)(2*GetMargin())
  247.                 && nImageHeight + rect.top <= rect.bottom + (int)(2*GetMargin())  )
  248.             {
  249.                 pGrid->GetImageList()->Draw(pDC, GetImage(), rect.TopLeft(), ILD_NORMAL);
  250.             }
  251.             rect.left += nImageWidth+GetMargin();
  252.         }
  253.     }
  254.     // Draw sort arrow
  255.     if (pGrid->GetSortColumn() == nCol && nRow == 0)
  256.     {
  257.         CSize size = pDC->GetTextExtent(_T("M"));
  258.         int nOffset = 2;
  259.         // Base the size of the triangle on the smaller of the column
  260.         // height or text height with a slight offset top and bottom.
  261.         // Otherwise, it can get drawn outside the bounds of the cell.
  262.         size.cy -= (nOffset * 2);
  263.         if (size.cy >= rect.Height())
  264.             size.cy = rect.Height() - (nOffset * 2);
  265.         size.cx = size.cy;      // Make the dimensions square
  266.         // Kludge for vertical text
  267.         BOOL bVertical = (GetFont()->lfEscapement == 900);
  268.         // Only draw if it'll fit!
  269.         if (size.cx + rect.left < rect.right + (int)(2*GetMargin()))
  270.         {
  271.             int nTriangleBase = rect.bottom - nOffset - size.cy;    // Triangle bottom right
  272.             //int nTriangleBase = (rect.top + rect.bottom - size.cy)/2; // Triangle middle right
  273.             //int nTriangleBase = rect.top + nOffset;                 // Triangle top right
  274.             //int nTriangleLeft = rect.right - size.cx;                 // Triangle RHS
  275.             //int nTriangleLeft = (rect.right + rect.left - size.cx)/2; // Triangle middle
  276.             //int nTriangleLeft = rect.left;                            // Triangle LHS
  277.             int nTriangleLeft;
  278.             if (bVertical)
  279.                 nTriangleLeft = (rect.right + rect.left - size.cx)/2; // Triangle middle
  280.             else
  281.                 nTriangleLeft = rect.right - size.cx;               // Triangle RHS
  282.             CPen penShadow(PS_SOLID, 0, ::GetSysColor(COLOR_3DSHADOW));
  283.             CPen penLight(PS_SOLID, 0, ::GetSysColor(COLOR_3DHILIGHT));
  284.             if (pGrid->GetSortAscending())
  285.             {
  286.                 // Draw triangle pointing upwards
  287.                 CPen *pOldPen = (CPen*) pDC->SelectObject(&penLight);
  288.                 pDC->MoveTo( nTriangleLeft + 1, nTriangleBase + size.cy + 1);
  289.                 pDC->LineTo( nTriangleLeft + (size.cx / 2) + 1, nTriangleBase + 1 );
  290.                 pDC->LineTo( nTriangleLeft + size.cx + 1, nTriangleBase + size.cy + 1);
  291.                 pDC->LineTo( nTriangleLeft + 1, nTriangleBase + size.cy + 1);
  292.                 pDC->SelectObject(&penShadow);
  293.                 pDC->MoveTo( nTriangleLeft, nTriangleBase + size.cy );
  294.                 pDC->LineTo( nTriangleLeft + (size.cx / 2), nTriangleBase );
  295.                 pDC->LineTo( nTriangleLeft + size.cx, nTriangleBase + size.cy );
  296.                 pDC->LineTo( nTriangleLeft, nTriangleBase + size.cy );
  297.                 pDC->SelectObject(pOldPen);
  298.             }
  299.             else
  300.             {
  301.                 // Draw triangle pointing downwards
  302.                 CPen *pOldPen = (CPen*) pDC->SelectObject(&penLight);
  303.                 pDC->MoveTo( nTriangleLeft + 1, nTriangleBase + 1 );
  304.                 pDC->LineTo( nTriangleLeft + (size.cx / 2) + 1, nTriangleBase + size.cy + 1 );
  305.                 pDC->LineTo( nTriangleLeft + size.cx + 1, nTriangleBase + 1 );
  306.                 pDC->LineTo( nTriangleLeft + 1, nTriangleBase + 1 );
  307.     
  308.                 pDC->SelectObject(&penShadow);
  309.                 pDC->MoveTo( nTriangleLeft, nTriangleBase );
  310.                 pDC->LineTo( nTriangleLeft + (size.cx / 2), nTriangleBase + size.cy );
  311.                 pDC->LineTo( nTriangleLeft + size.cx, nTriangleBase );
  312.                 pDC->LineTo( nTriangleLeft, nTriangleBase );
  313.                 pDC->SelectObject(pOldPen);
  314.             }
  315.             
  316.             if (!bVertical)
  317.                 rect.right -= size.cy;
  318.         }
  319.     }
  320.     // We want to see '&' characters so use DT_NOPREFIX
  321.     DrawText(pDC->m_hDC, GetText(), -1, rect, GetFormat() | DT_NOPREFIX);
  322.     pDC->RestoreDC(nSavedDC);
  323.     return TRUE;
  324. }
  325. /////////////////////////////////////////////////////////////////////////////
  326. // GridCell Mouse and Cursor events
  327. // Not yet implemented
  328. void CGridCellBase::OnMouseEnter()
  329. {
  330.     TRACE0("Mouse entered celln");
  331. }
  332. void CGridCellBase::OnMouseOver()
  333. {
  334.     //TRACE0("Mouse over celln");
  335. }
  336. // Not Yet Implemented
  337. void CGridCellBase::OnMouseLeave()
  338. {
  339.     TRACE0("Mouse left celln");
  340. }
  341. void CGridCellBase::OnClick( CPoint PointCellRelative)
  342. {
  343.     UNUSED_ALWAYS(PointCellRelative);
  344.     TRACE2("Mouse Left btn up in cell at x=%i y=%in", PointCellRelative.x, PointCellRelative.y);
  345. }
  346. void CGridCellBase::OnClickDown( CPoint PointCellRelative)
  347. {
  348.     UNUSED_ALWAYS(PointCellRelative);
  349.     TRACE2("Mouse Left btn down in cell at x=%i y=%in", PointCellRelative.x, PointCellRelative.y);
  350. }
  351. void CGridCellBase::OnRClick( CPoint PointCellRelative)
  352. {
  353.     UNUSED_ALWAYS(PointCellRelative);
  354.     TRACE2("Mouse right-clicked in cell at x=%i y=%in", PointCellRelative.x, PointCellRelative.y);
  355. }
  356. void CGridCellBase::OnDblClick( CPoint PointCellRelative)
  357. {
  358.     UNUSED_ALWAYS(PointCellRelative);
  359.     TRACE2("Mouse double-clicked in cell at x=%i y=%in", PointCellRelative.x, PointCellRelative.y);
  360. }
  361. // Return TRUE if you set the cursor
  362. BOOL CGridCellBase::OnSetCursor()
  363. {
  364. #ifndef _WIN32_WCE_NO_CURSOR
  365.     SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
  366. #endif
  367.     return TRUE;
  368. }
  369. /////////////////////////////////////////////////////////////////////////////
  370. // GridCell Sizing
  371. BOOL CGridCellBase::GetTextRect( LPRECT pRect)  // i/o:  i=dims of cell rect; o=dims of text rect
  372. {
  373.     if (GetImage() >= 0)
  374.     {
  375.         IMAGEINFO Info;
  376.         CGridCtrl* pGrid = GetGrid();
  377.         CImageList* pImageList = pGrid->GetImageList();
  378.         
  379.         if (pImageList->GetImageInfo( GetImage(), &Info))
  380.         {
  381.             int nImageWidth = Info.rcImage.right-Info.rcImage.left+1;
  382.             pRect->left += nImageWidth + GetMargin();
  383.         }
  384.     }
  385.     return TRUE;
  386. }
  387. // By default this uses the selected font (which is a bigger font)
  388. CSize CGridCellBase::GetTextExtent(LPCTSTR szText, CDC* pDC /*= NULL*/)
  389. {
  390.     CGridCtrl* pGrid = GetGrid();
  391.     ASSERT(pGrid);
  392.     BOOL bReleaseDC = FALSE;
  393.     if (pDC == NULL)
  394.     {
  395.         pDC = pGrid->GetDC();
  396.         if (!pDC) 
  397.         {
  398.             CGridDefaultCell* pDefCell = (CGridDefaultCell*) GetDefaultCell();
  399.             ASSERT(pDefCell);
  400.             return CSize(pDefCell->GetWidth(), pDefCell->GetHeight());
  401.         }
  402.         bReleaseDC = TRUE;
  403.     }
  404.     CFont *pOldFont = NULL,
  405.           *pFont = GetFontObject();
  406.     if (pFont)
  407.         pOldFont = pDC->SelectObject(pFont);
  408.     CSize size;
  409.     int nFormat = GetFormat();
  410.     // If the cell is a multiline cell, then use the width of the cell
  411.     // to get the height
  412.     if ((nFormat & DT_WORDBREAK) && !(nFormat & DT_SINGLELINE))
  413.     {
  414.         CString str = szText;
  415.         int nMaxWidth = 0;
  416.         while (TRUE)
  417.         {
  418.             int nPos = str.Find(_T('n'));
  419.             CString TempStr = (nPos < 0)? str : str.Left(nPos);
  420.             int nTempWidth = pDC->GetTextExtent(TempStr).cx;
  421.             if (nTempWidth > nMaxWidth)
  422.                 nMaxWidth = nTempWidth;
  423.             if (nPos < 0)
  424.                 break;
  425.             str = str.Mid(nPos + 1);    // Bug fix by Thomas Steinborn
  426.         }
  427.         
  428.         CRect rect;
  429.         rect.SetRect(0,0, nMaxWidth, 0);
  430.         pDC->DrawText(szText, -1, rect, nFormat | DT_CALCRECT);
  431.         size = rect.Size();
  432.     }
  433.     else
  434.         size = pDC->GetTextExtent(szText, _tcslen(szText));
  435.     TEXTMETRIC tm;
  436.     pDC->GetTextMetrics(&tm);
  437.     size.cx += (tm.tmOverhang);
  438.     if (pOldFont)
  439.         pDC->SelectObject(pOldFont);
  440.     
  441.     size += CSize(4*GetMargin(), 2*GetMargin());
  442.     // Kludge for vertical text
  443.     LOGFONT *pLF = GetFont();
  444.     if (pLF->lfEscapement == 900 || pLF->lfEscapement == -900)
  445.     {
  446.         int nTemp = size.cx;
  447.         size.cx = size.cy;
  448.         size.cy = nTemp;
  449.         size += CSize(0, 4*GetMargin());
  450.     }
  451.     
  452.     if (bReleaseDC)
  453.         pGrid->ReleaseDC(pDC);
  454.     return size;
  455. }
  456. CSize CGridCellBase::GetCellExtent(CDC* pDC)
  457. {
  458.     CSize size = GetTextExtent(GetText(), pDC);
  459.     CSize ImageSize(0,0);
  460.     int nImage = GetImage();
  461.     if (nImage >= 0) 
  462.     {
  463.         CGridCtrl* pGrid = GetGrid();
  464.         ASSERT(pGrid);
  465.         if (pGrid->GetImageList()) 
  466.         {
  467.             IMAGEINFO Info;
  468.             if (pGrid->GetImageList()->GetImageInfo(nImage, &Info))
  469.                 ImageSize = CSize(Info.rcImage.right-Info.rcImage.left+1, 
  470.                                   Info.rcImage.bottom-Info.rcImage.top+1);
  471.         }
  472.     }
  473.     
  474.     return CSize(size.cx + ImageSize.cx, max(size.cy, ImageSize.cy));
  475. }
  476. // EFW - Added to print cells so that grids that use different colors are
  477. // printed correctly.
  478. BOOL CGridCellBase::PrintCell(CDC* pDC, int /*nRow*/, int /*nCol*/, CRect rect)
  479. {
  480. #if defined(_WIN32_WCE_NO_PRINTING) || defined(GRIDCONTROL_NO_PRINTING)
  481.     return FALSE;
  482. #else
  483.     COLORREF crFG, crBG;
  484.     GV_ITEM Item;
  485.     CGridCtrl* pGrid = GetGrid();
  486.     if (!pGrid || !pDC)
  487.         return FALSE;
  488.     if( rect.Width() <= 0
  489.         || rect.Height() <= 0)  // prevents imagelist item from drawing even
  490.         return FALSE;           //  though cell is hidden
  491.     int nSavedDC = pDC->SaveDC();
  492.     pDC->SetBkMode(TRANSPARENT);
  493.     if(pGrid->GetShadedPrintOut())
  494.     {
  495.         // Get the default cell implementation for this kind of cell. We use it if this cell
  496.         // has anything marked as "default"
  497.         CGridDefaultCell *pDefaultCell = (CGridDefaultCell*) GetDefaultCell();
  498.         if (!pDefaultCell)
  499.             return FALSE;
  500.         // Use custom color if it doesn't match the default color and the
  501.         // default grid background color.  If not, leave it alone.
  502.         if(IsFixed())
  503.             crBG = (GetBackClr() != CLR_DEFAULT) ? GetBackClr() : pDefaultCell->GetBackClr();
  504.         else
  505.             crBG = (GetBackClr() != CLR_DEFAULT && GetBackClr() != pDefaultCell->GetBackClr()) ?
  506.                 GetBackClr() : CLR_DEFAULT;
  507.         // Use custom color if the background is different or if it doesn't
  508.         // match the default color and the default grid text color.  If not,
  509.         // use black to guarantee the text is visible.
  510.         if(IsFixed())
  511.             crFG = (GetBackClr() != CLR_DEFAULT) ? GetTextClr() : pDefaultCell->GetTextClr();
  512.         else
  513.             crFG = (GetBackClr() != CLR_DEFAULT ||
  514.                 (GetTextClr() != CLR_DEFAULT && GetTextClr() != pDefaultCell->GetTextClr())) ?
  515.                     GetTextClr() : RGB(0, 0, 0);
  516.         // If not printing on a color printer, adjust the foreground color
  517.         // to a gray scale if the background color isn't used so that all
  518.         // colors will be visible.  If not, some colors turn to solid black
  519.         // or white when printed and may not show up.  This may be caused by
  520.         // coarse dithering by the printer driver too (see image note below).
  521.         if(pDC->GetDeviceCaps(NUMCOLORS) == 2 && crBG == CLR_DEFAULT)
  522.             crFG = RGB(GetRValue(crFG) * 0.30, GetGValue(crFG) * 0.59,
  523.                 GetBValue(crFG) * 0.11);
  524.         // Only erase the background if the color is not the default
  525.         // grid background color.
  526.         if(crBG != CLR_DEFAULT)
  527.         {
  528.             CBrush brush(crBG);
  529.             rect.right++; rect.bottom++;
  530.             pDC->FillRect(rect, &brush);
  531.             rect.right--; rect.bottom--;
  532.         }
  533.     }
  534.     else
  535.     {
  536.         crBG = CLR_DEFAULT;
  537.         crFG = RGB(0, 0, 0);
  538.     }
  539.     pDC->SetTextColor(crFG);
  540.     CFont *pFont = GetFontObject();
  541.     if (pFont)
  542.         pDC->SelectObject(pFont);
  543.     /*
  544.     // ***************************************************
  545.     // Disabled - if you need this functionality then you'll need to rewrite.
  546.     // Create the appropriate font and select into DC.
  547.     CFont Font;
  548.     // Bold the fixed cells if not shading the print out.  Use italic
  549.     // font it it is enabled.
  550.     const LOGFONT* plfFont = GetFont();
  551.     if(IsFixed() && !pGrid->GetShadedPrintOut())
  552.     {
  553.         Font.CreateFont(plfFont->lfHeight, 0, 0, 0, FW_BOLD, plfFont->lfItalic, 0, 0,
  554.             ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  555. #ifndef _WIN32_WCE
  556.             PROOF_QUALITY,
  557. #else
  558.             DEFAULT_QUALITY,
  559. #endif
  560.             VARIABLE_PITCH | FF_SWISS, plfFont->lfFaceName);
  561.     }
  562.     else
  563.         Font.CreateFontIndirect(plfFont);
  564.     pDC->SelectObject(&Font);
  565.     // ***************************************************
  566.     */
  567.     // Draw lines only when wanted on fixed cells.  Normal cell grid lines
  568.     // are handled in OnPrint.
  569.     if(pGrid->GetGridLines() != GVL_NONE && IsFixed())
  570.     {
  571.         CPen lightpen(PS_SOLID, 1,  ::GetSysColor(COLOR_3DHIGHLIGHT)),
  572.              darkpen(PS_SOLID,  1, ::GetSysColor(COLOR_3DDKSHADOW)),
  573.             *pOldPen = pDC->GetCurrentPen();
  574.         pDC->SelectObject(&lightpen);
  575.         pDC->MoveTo(rect.right, rect.top);
  576.         pDC->LineTo(rect.left, rect.top);
  577.         pDC->LineTo(rect.left, rect.bottom);
  578.         pDC->SelectObject(&darkpen);
  579.         pDC->MoveTo(rect.right, rect.top);
  580.         pDC->LineTo(rect.right, rect.bottom);
  581.         pDC->LineTo(rect.left, rect.bottom);
  582.         rect.DeflateRect(1,1);
  583.         pDC->SelectObject(pOldPen);
  584.     }
  585.     rect.DeflateRect(GetMargin(), 0);
  586.     if(pGrid->GetImageList() && GetImage() >= 0)
  587.     {
  588.         // NOTE: If your printed images look like fuzzy garbage, check the
  589.         //       settings on your printer driver.  If it's using coarse
  590.         //       dithering and/or vector graphics, they may print wrong.
  591.         //       Changing to fine dithering and raster graphics makes them
  592.         //       print properly.  My HP 4L had that problem.
  593.         IMAGEINFO Info;
  594.         if(pGrid->GetImageList()->GetImageInfo(GetImage(), &Info))
  595.         {
  596.             int nImageWidth = Info.rcImage.right-Info.rcImage.left;
  597.             pGrid->GetImageList()->Draw(pDC, GetImage(), rect.TopLeft(), ILD_NORMAL);
  598.             rect.left += nImageWidth+GetMargin();
  599.         }
  600.     }
  601.     // Draw without clipping so as not to lose text when printed for real
  602.     DrawText(pDC->m_hDC, GetText(), -1, rect,
  603.         GetFormat() | DT_NOCLIP | DT_NOPREFIX);
  604.     pDC->RestoreDC(nSavedDC);
  605.     return TRUE;
  606. #endif
  607. }
  608. /*****************************************************************************
  609. Callable by derived classes, only
  610. *****************************************************************************/
  611. LRESULT CGridCellBase::SendMessageToParent(int nRow, int nCol, int nMessage)
  612. {
  613.     CGridCtrl* pGrid = GetGrid();
  614.     if( pGrid)
  615.         return pGrid->SendMessageToParent(nRow, nCol, nMessage);
  616.     else
  617.         return 0;
  618. }