CGXWndWrapper and printing
By default the CGXWndWrapper class does not support printing. This is because CGXWndWrapper only knows the CWnd interface and there is no generic way to force a window to render its contents to a device context.
However, you have the possibility to add support for printing a window if this window provides a method for rendering its device context to a device context. In the following example we show you how to subclass CGXWndWrapper and add support for printing CGXGridWnd cells.
Example:
class CMyGridWndWrapper: public CGXWndWrapper
{
public:
CMyGridWndWrapper(CGXGridCore* pGrid, CWnd* pWnd, BOOL bNeedDestroy, BOOL bCanActivate, BOOL bInvertBorders);
CMyGridWndWrapper(CGXGridCore* pGrid);
virtual void Draw(CDC* pDC, CRect rect, ROWCOL nRow, ROWCOL nCol, const CGXStyle& style, const CGXStyle* pStandardStyle);
virtual void OnNotifyMsg(MSG* pMsg);
};
class CMyGrid: public CGXGridWnd
{
friend class CMyGridWndWrapper;
};
CMyGridWndWrapper::CMyGridWndWrapper(CGXGridCore* pGrid, CWnd* pWnd, BOOL bNeedDestroy, BOOL bCanActivate, BOOL bInvertBorders)
: CGXWndWrapper(pGrid, pWnd, bNeedDestroy, bCanActivate, bInvertBorders)
{
}
CMyGridWndWrapper::CMyGridWndWrapper(CGXGridCore* pGrid)
: CGXWndWrapper(pGrid)
{
}
void CMyGridWndWrapper::OnNotifyMsg(MSG* pMsg)
{
// Called from CGXGridCore::OnVScroll, OnHScroll
pMsg;
// deactivate the current cell when the user scrolls
if (pMsg->message == WM_VSCROLL
|| pMsg->message == WM_HSCROLL)
{
SetActive(FALSE);
Refresh();
}
}
void CMyGridWndWrapper::Draw(CDC* pDC, CRect rect, ROWCOL nRow, ROWCOL nCol, const CGXStyle& style, const CGXStyle* pStandardStyle)
{
// Only let the base class draw the active current cell
if (m_pWnd == NULL
|| !m_pWnd->IsKindOf(RUNTIME_CLASS(CGXGridWnd))
|| !Grid()->IsPrinting() && nRow == m_nRow && nCol == m_nCol && m_bIsActive)
{
CGXWndWrapper::Draw(pDC, rect, nRow, nCol, style, pStandardStyle);
}
else // render a CGXGridWnd object to the device context
{
ASSERT(::IsWindow(m_pWnd->m_hWnd));
// ASSERTION-> Did you forget to call Create? ->END
ASSERT(pDC != NULL && pDC->IsKindOf(RUNTIME_CLASS(CDC)));
// ASSERTION-> Invalid Device Context ->END
ASSERT(nRow <= Grid()->GetRowCount() && nCol <= Grid()->GetColCount());
// ASSERTION-> Cell coordinates out of range ->END
ASSERT_VALID(pDC);
CMyGrid* pGrid = (CMyGrid*) m_pWnd;
// Erase Frame around the cell
DrawFrame(pDC, rect, style);
rect = GetCellRect(nRow, nCol, &rect, &style);
CRect rectDisplay = CRect(0, 0, rect.Width(), rect.Height());
// The grid below only prints to CRect(0,0,x,y) -
// Therefore I have to change the mapping mode so that
// rectDisplay maps to (0,0,x,y)
pDC->SaveDC();
CPoint pt = pDC->OffsetWindowOrg(-rect.left, -rect.top);
pDC->IntersectClipRect(rectDisplay);
pGrid->SetGridRect(TRUE, rectDisplay);
pGrid->DrawDirectToDC(pDC);
pGrid->SetGridRect(FALSE, rectDisplay);
// Reset device context
pDC->RestoreDC(-1);
// child Controls: spin-buttons, hotspot, combobox btn, ...
// CGXControl::Draw(pDC, rect, nRow, nCol, style, pStandardStyle);
}
// Unreferenced:
pStandardStyle;
}
and in OninitialUpdate add
CGXGridWnd* pGridWnd = new CGXGridWnd();
VERIFY(pGridWnd->Create(WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_VISIBLE, CRect(0,0,1,1), this, IDS_CTRL_GRIDCHILD));
pGridWnd->Initialize();
pGridWnd->SetRowCount(32);
pGridWnd->SetColCount(16);
RegisterControl(IDS_CTRL_GRIDCHILD,
new CMyGridWndWrapper(this,
pGridWnd,
TRUE, // must delete
TRUE, // can activate
FALSE // no invert borders
));
SetCoveredCellsRowCol(5, 1, 10, 5);
SetStyleRange(CGXRange(5,1), CGXStyle()
.SetControl(IDS_CTRL_GRIDCHILD)
.SetDraw3dFrame(gxFrameInset)
//.SetBorders(gxBorderAll, CGXPen().SetWidth(2))
);