www.pudn.com > RichEditGrid_src.zip > GridCellRich.cpp
// GridCellRich.cpp: implementation of the CGridCellRich class.
//
// GridCellRich Demonstration
// **************************
//
// Written by Mathieu DUBAËLE (mathieu@appstmd.com)
//
// Feel free to send me all the changes you can made to this code.
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "gridctrl_src/gridctrl.h"
#include "RichEditGrid.h"
#include "GridCellRich.h"
#include "InPlaceRichEdit.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
IMPLEMENT_DYNCREATE(CGridCellRich, CGridCell)
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CGridCellRich::CGridCellRich()
{
m_pRichEditTemp=(CRichEditCtrl*) AfxGetMainWnd ()->GetDlgItem (IDC_RICHEDIT_TEMP);
ASSERT(m_pRichEditTemp!=NULL);
}
CGridCellRich::~CGridCellRich()
{
}
/////////////////////////////////////////////////////////////////////////////
// CallBack functions
static DWORD CALLBACK EditStreamCallBack(DWORD dwCookie, LPBYTE pbBuff, LONG cb,
LONG *pcb)
{
CString *pstr = (CString *)dwCookie;
if( pstr->GetLength() < cb )
{
*pcb = pstr->GetLength();
memcpy(pbBuff, (LPCSTR)*pstr, *pcb );
pstr->Empty();
}
else
{
*pcb = cb;
memcpy(pbBuff, (LPCSTR)*pstr, *pcb );
*pstr = pstr->Right( pstr->GetLength() - cb );
}
return 0;
}
/////////////////////////////////////////////////////////////////////////////
BOOL CGridCellRich::Draw(CDC* pDC, int nRow, int nCol, CRect rect, BOOL bEraseBkgnd /*=TRUE*/)
{
// Note - all through this function we totally brutalise 'rect'. Do not
// depend on it's value being that which was passed in.
CGridCtrl* pGrid = GetGrid();
ASSERT(pGrid);
if (!pGrid || !pDC)
return FALSE;
if( rect.Width() <= 0 || rect.Height() <= 0) // prevents imagelist item from drawing even
return FALSE; // though cell is hidden
//TRACE3("Drawing %scell %d, %d\n", IsFixed()? _T("Fixed ") : _T(""), nRow, nCol);
int nSavedDC = pDC->SaveDC();
pDC->SetBkMode(TRANSPARENT);
// Get the default cell implementation for this kind of cell. We use it if this cell
// has anything marked as "default"
CGridDefaultCell *pDefaultCell = (CGridDefaultCell*) GetDefaultCell();
if (!pDefaultCell)
return FALSE;
// Set up text and background colours
COLORREF TextClr, TextBkClr;
TextClr = (GetTextClr() == CLR_DEFAULT)? pDefaultCell->GetTextClr() : GetTextClr();
if (GetBackClr() == CLR_DEFAULT)
TextBkClr = pDefaultCell->GetBackClr();
else
{
bEraseBkgnd = TRUE;
TextBkClr = GetBackClr();
}
// Draw cell background and highlighting (if necessary)
if ( IsFocused() || IsDropHighlighted() )
{
// Always draw even in list mode so that we can tell where the
// cursor is at. Use the highlight colors though.
if(GetState() & GVIS_SELECTED)
{
TextBkClr = ::GetSysColor(COLOR_HIGHLIGHT);
TextClr = ::GetSysColor(COLOR_HIGHLIGHTTEXT);
bEraseBkgnd = TRUE;
}
rect.right++; rect.bottom++; // FillRect doesn't draw RHS or bottom
if (bEraseBkgnd)
{
TRY
{
CBrush brush(TextBkClr);
pDC->FillRect(rect, &brush);
}
CATCH(CResourceException, e)
{
//e->ReportError();
}
END_CATCH
}
// Don't adjust frame rect if no grid lines so that the
// whole cell is enclosed.
if(pGrid->GetGridLines() != GVL_NONE)
{
rect.right--;
rect.bottom--;
}
if (pGrid->GetFrameFocusCell())
{
// Use same color as text to outline the cell so that it shows
// up if the background is black.
TRY
{
CBrush brush(TextClr);
pDC->FrameRect(rect, &brush);
}
CATCH(CResourceException, e)
{
//e->ReportError();
}
END_CATCH
}
pDC->SetTextColor(TextClr);
// Adjust rect after frame draw if no grid lines
if(pGrid->GetGridLines() == GVL_NONE)
{
rect.right--;
rect.bottom--;
}
rect.DeflateRect(0,1,1,1);
}
else if ((GetState() & GVIS_SELECTED))
{
rect.right++; rect.bottom++; // FillRect doesn't draw RHS or bottom
pDC->FillSolidRect(rect, ::GetSysColor(COLOR_HIGHLIGHT));
rect.right--; rect.bottom--;
pDC->SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
}
else
{
if (bEraseBkgnd)
{
rect.right++; rect.bottom++; // FillRect doesn't draw RHS or bottom
CBrush brush(TextBkClr);
pDC->FillRect(rect, &brush);
rect.right--; rect.bottom--;
}
pDC->SetTextColor(TextClr);
}
// Draw lines only when wanted
if (IsFixed() && pGrid->GetGridLines() != GVL_NONE)
{
CCellID FocusCell = pGrid->GetFocusCell();
// As above, always show current location even in list mode so
// that we know where the cursor is at.
BOOL bHiliteFixed = pGrid->GetTrackFocusCell() && pGrid->IsValid(FocusCell) &&
(FocusCell.row == nRow || FocusCell.col == nCol);
// If this fixed cell is on the same row/col as the focus cell,
// highlight it.
if (bHiliteFixed)
{
rect.right++; rect.bottom++;
pDC->DrawEdge(rect, BDR_SUNKENINNER /*EDGE_RAISED*/, BF_RECT);
rect.DeflateRect(1,1);
}
else
{
CPen lightpen(PS_SOLID, 1, ::GetSysColor(COLOR_3DHIGHLIGHT)),
darkpen(PS_SOLID, 1, ::GetSysColor(COLOR_3DDKSHADOW)),
*pOldPen = pDC->GetCurrentPen();
pDC->SelectObject(&lightpen);
pDC->MoveTo(rect.right, rect.top);
pDC->LineTo(rect.left, rect.top);
pDC->LineTo(rect.left, rect.bottom);
pDC->SelectObject(&darkpen);
pDC->MoveTo(rect.right, rect.top);
pDC->LineTo(rect.right, rect.bottom);
pDC->LineTo(rect.left, rect.bottom);
pDC->SelectObject(pOldPen);
rect.DeflateRect(1,1);
}
}
// Draw Text and image
#if !defined(_WIN32_WCE_NO_PRINTING) && !defined(GRIDCONTROL_NO_PRINTING)
if (!pDC->m_bPrinting)
#endif
{
CFont *pFont = GetFontObject();
ASSERT(pFont);
if (pFont)
pDC->SelectObject(pFont);
}
rect.DeflateRect(GetMargin(), 0);
if (pGrid->GetImageList() && GetImage() >= 0)
{
IMAGEINFO Info;
if (pGrid->GetImageList()->GetImageInfo(GetImage(), &Info))
{
// would like to use a clipping region but seems to have issue
// working with CMemDC directly. Instead, don't display image
// if any part of it cut-off
//
// CRgn rgn;
// rgn.CreateRectRgnIndirect(rect);
// pDC->SelectClipRgn(&rgn);
// rgn.DeleteObject();
int nImageWidth = Info.rcImage.right-Info.rcImage.left+1;
int nImageHeight = Info.rcImage.bottom-Info.rcImage.top+1;
if( nImageWidth + rect.left <= rect.right + (int)(2*GetMargin())
&& nImageHeight + rect.top <= rect.bottom + (int)(2*GetMargin()) )
{
pGrid->GetImageList()->Draw(pDC, GetImage(), rect.TopLeft(), ILD_NORMAL);
}
//rect.left += nImageWidth+GetMargin();
}
}
// Draw sort arrow
if (pGrid->GetSortColumn() == nCol && nRow == 0)
{
CSize size = pDC->GetTextExtent(_T("M"));
int nOffset = 2;
// Base the size of the triangle on the smaller of the column
// height or text height with a slight offset top and bottom.
// Otherwise, it can get drawn outside the bounds of the cell.
size.cy -= (nOffset * 2);
if (size.cy >= rect.Height())
size.cy = rect.Height() - (nOffset * 2);
size.cx = size.cy; // Make the dimensions square
// Kludge for vertical text
BOOL bVertical = (GetFont()->lfEscapement == 900);
// Only draw if it'll fit!
if (size.cx + rect.left < rect.right + (int)(2*GetMargin()))
{
int nTriangleBase = rect.bottom - nOffset - size.cy; // Triangle bottom right
//int nTriangleBase = (rect.top + rect.bottom - size.cy)/2; // Triangle middle right
//int nTriangleBase = rect.top + nOffset; // Triangle top right
//int nTriangleLeft = rect.right - size.cx; // Triangle RHS
//int nTriangleLeft = (rect.right + rect.left - size.cx)/2; // Triangle middle
//int nTriangleLeft = rect.left; // Triangle LHS
int nTriangleLeft;
if (bVertical)
nTriangleLeft = (rect.right + rect.left - size.cx)/2; // Triangle middle
else
nTriangleLeft = rect.right - size.cx; // Triangle RHS
CPen penShadow(PS_SOLID, 0, ::GetSysColor(COLOR_3DSHADOW));
CPen penLight(PS_SOLID, 0, ::GetSysColor(COLOR_3DHILIGHT));
if (pGrid->GetSortAscending())
{
// Draw triangle pointing upwards
CPen *pOldPen = (CPen*) pDC->SelectObject(&penLight);
pDC->MoveTo( nTriangleLeft + 1, nTriangleBase + size.cy + 1);
pDC->LineTo( nTriangleLeft + (size.cx / 2) + 1, nTriangleBase + 1 );
pDC->LineTo( nTriangleLeft + size.cx + 1, nTriangleBase + size.cy + 1);
pDC->LineTo( nTriangleLeft + 1, nTriangleBase + size.cy + 1);
pDC->SelectObject(&penShadow);
pDC->MoveTo( nTriangleLeft, nTriangleBase + size.cy );
pDC->LineTo( nTriangleLeft + (size.cx / 2), nTriangleBase );
pDC->LineTo( nTriangleLeft + size.cx, nTriangleBase + size.cy );
pDC->LineTo( nTriangleLeft, nTriangleBase + size.cy );
pDC->SelectObject(pOldPen);
}
else
{
// Draw triangle pointing downwards
CPen *pOldPen = (CPen*) pDC->SelectObject(&penLight);
pDC->MoveTo( nTriangleLeft + 1, nTriangleBase + 1 );
pDC->LineTo( nTriangleLeft + (size.cx / 2) + 1, nTriangleBase + size.cy + 1 );
pDC->LineTo( nTriangleLeft + size.cx + 1, nTriangleBase + 1 );
pDC->LineTo( nTriangleLeft + 1, nTriangleBase + 1 );
pDC->SelectObject(&penShadow);
pDC->MoveTo( nTriangleLeft, nTriangleBase );
pDC->LineTo( nTriangleLeft + (size.cx / 2), nTriangleBase + size.cy );
pDC->LineTo( nTriangleLeft + size.cx, nTriangleBase );
pDC->LineTo( nTriangleLeft, nTriangleBase );
pDC->SelectObject(pOldPen);
}
if (!bVertical)
rect.right -= size.cy;
}
}
// Format the text and render it
GetTextRect(rect);
FORMATRANGE fr;
UINT Left=::MulDiv(rect.left, 1440, pDC->GetDeviceCaps(LOGPIXELSX));
UINT Top=::MulDiv(rect.top, 1440, pDC->GetDeviceCaps(LOGPIXELSY));
UINT Right=::MulDiv(rect.right, 1440, pDC->GetDeviceCaps(LOGPIXELSX));
UINT Bottom=::MulDiv(rect.bottom, 1440, pDC->GetDeviceCaps(LOGPIXELSY));
CRect Rect (Left,Top,Right,Bottom);
fr.hdc = pDC->m_hDC;
fr.hdcTarget = pDC->m_hDC;
fr.rc = Rect;
fr.rcPage = Rect;
fr.chrg.cpMin = 0;
fr.chrg.cpMax = -1;
CString Text=GetText ();
UINT StreamType;
if (Text.Left (6)=="{\\rtf1")
StreamType=SF_RTF;
else
StreamType=SF_TEXT;
EDITSTREAM es = {(DWORD)&Text, 0, EditStreamCallBack};
m_pRichEditTemp->SetSel (0,-1);
m_pRichEditTemp->SetBackgroundColor (FALSE,TextBkClr);
m_pRichEditTemp->Clear ();
m_pRichEditTemp->StreamIn(StreamType, es);
m_pRichEditTemp->FormatRange(&fr, TRUE);
// Update the display with the new formatting
m_pRichEditTemp->GetClientRect (&Rect);
m_pRichEditTemp->DisplayBand(&Rect);
pDC->RestoreDC(nSavedDC);
return TRUE;
}
BOOL CGridCellRich::Edit(int nRow, int nCol, CRect rect, CPoint /* point */, UINT nID, UINT nChar)
{
if ( m_bEditing )
{
if (m_pEditWnd)
m_pEditWnd->SendMessage ( WM_CHAR, nChar );
}
else
{
DWORD dwStyle = ES_LEFT;
if (GetFormat() & DT_RIGHT)
dwStyle = ES_RIGHT;
else if (GetFormat() & DT_CENTER)
dwStyle = ES_CENTER;
m_bEditing = TRUE;
// InPlaceEdit auto-deletes itself
CGridCtrl* pGrid = GetGrid();
m_pEditWnd = new CInPlaceRichEdit((CWnd*) pGrid, rect, dwStyle, nID, nRow, nCol, GetText(), nChar);
}
return TRUE;
}
void CGridCellRich::SetBold ()
{
if (!m_bEditing) return;
CHARFORMAT CharFormat;
CharFormat.cbSize=sizeof(CharFormat);
CharFormat.dwMask=CFM_BOLD;
CharFormat.dwEffects=CFE_BOLD;
CRichEditCtrl* pRich=(CRichEditCtrl*) m_pEditWnd;
pRich->SetSelectionCharFormat (CharFormat);
}
void CGridCellRich::SetItalic ()
{
if (!m_bEditing) return;
CHARFORMAT CharFormat;
CharFormat.cbSize=sizeof(CharFormat);
CharFormat.dwMask=CFM_ITALIC;
CharFormat.dwEffects=CFE_ITALIC;
CRichEditCtrl* pRich=(CRichEditCtrl*) m_pEditWnd;
pRich->SetSelectionCharFormat (CharFormat);
}
void CGridCellRich::SetUnderline ()
{
if (!m_bEditing) return;
CHARFORMAT CharFormat;
CharFormat.cbSize=sizeof(CharFormat);
CharFormat.dwMask=CFM_UNDERLINE;
CharFormat.dwEffects=CFE_UNDERLINE;
CRichEditCtrl* pRich=(CRichEditCtrl*) m_pEditWnd;
pRich->SetSelectionCharFormat (CharFormat);
}