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))
      );