// Here is the SketcherView.cpp file that I put together
// It is for the completed version but the solution is
// probably still in it.
#include "PrintData.h"
#include <math.h>
#include "SketcherView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CSketcherView
IMPLEMENT_DYNCREATE(CSketcherView, CScrollView)
BEGIN_MESSAGE_MAP(CSketcherView, CScrollView)
//{{AFX_MSG_MAP(CSketcherView)
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_COMMAND(ID_MOVE, OnMove)
ON_COMMAND(ID_DELETE, OnDelete)
ON_WM_RBUTTONUP()
ON_WM_RBUTTONDOWN()
ON_COMMAND(ID_SENDTOBACK, OnSendtoback)
ON_COMMAND(ID_VIEW_SCALE, OnViewScale)
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CSketcherView construction/destruction
CSketcherView::CSketcherView()
{
// TODO: add construction code here
m_FirstPoint = CPoint(0,0); // Set 1st recorded point to 0,0
m_SecondPoint = CPoint(0,0); // Set 2nd recorded point to 0,0
m_pTempElement = NULL; // Set temporary element pointer to 0
m_pSelected = NULL; // No element initial selected
m_MoveMode = FALSE; // Set move mode to off
m_CursorPos = CPoint(0,0); // Initialize as 0
m_FirstPos = CPoint(0,0); // Initialize to 0
m_Scale = 1; // Set scale to 1-to-1 ratio
SetScrollSizes(MM_TEXT, CSize(0,0)); // Set arbitrary scrollers
}
CSketcherView::~CSketcherView()
{
}
BOOL CSketcherView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CSketcherView drawing
void CSketcherView::OnDraw(CDC* pDC)
{
CSketcherDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
// This calls GetListHeadPosition( ) which is in SketcherDoc.h
POSITION aPos = pDoc->GetListHeadPosition();
CElement* pElement = 0; // Storage for an element pointer
while(aPos)
{
// pDoc->GetNext() gets a pointer to an element from the document
pElement = pDoc->GetNext(aPos); // Get the current element pointer
// If the element is visible draw it - Only elements that overlap
// the area that Windows has identified as invalid will be drawn.
if(pDC->RectVisible(pElement->GetBoundRect()))
pElement->Draw(pDC, m_pSelected); // Draw the element
}
}
/////////////////////////////////////////////////////////////////////////////
// CSketcherView printing
BOOL CSketcherView::OnPreparePrinting(CPrintInfo* pInfo)
{
// Create a print data object
CPrintData* pPrintData;
pInfo->m_lpUserData = pPrintData = new CPrintData;
CSketcherDoc* pDoc = GetDocument(); // Get a document pointer
// Get the rectangle enclosing the elements in the document area
CRect DocExtent = pDoc->GetDocExtent();
// Store the corner of the rectangle in m_DocRefPoint
pPrintData->m_DocRefPoint = CPoint(DocExtent.left, DocExtent.bottom);
// Get the name of the document file and save it
pPrintData->m_DocTitle = pDoc->GetTitle();
// Calculate how many printed page widths of 600 units are required
// to accommodate the width of the document
pPrintData->m_nWidths=(UINT)ceil(static_cast<double>(DocExten t.Width()) / 600.0);
// Calculate how many printed page lengths of 900 units are required
// to accommodate the document length
pPrintData->m_nLengths=(UINT)ceil(static_cast<double>(DocExte nt.Height()) / 900.0);
// Set the first page number as 1 and
// set the last page number as the total number of pages
pInfo->SetMinPage(1);
pInfo->SetMaxPage(pPrintData->m_nWidths * pPrintData->m_nLengths);
if(!DoPreparePrinting(pInfo))
{
delete static_cast<CPrintData*>(pInfo->m_lpUserData);
return FALSE;
}
return TRUE;
}
void CSketcherView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}
void CSketcherView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* pInfo)
{
// Because a CPrintData object was created on the heap, it must
// be deleted when the printing is completed. If pens are used
// during the printing process, they must be deleted also.
delete static_cast<CPrintData*>(pInfo->m_lpUserData);
}
/////////////////////////////////////////////////////////////////////////////
// CSketcherView diagnostics
#ifdef _DEBUG
void CSketcherView::AssertValid() const
{
CView::AssertValid();
}
void CSketcherView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CSketcherDoc* CSketcherView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CSketcherDoc)));
return (CSketcherDoc*)m_pDocument;
}
#endif //_DEBUG
//////////////////////////////////////////////////////////////
// CSketcherView message handlers
void CSketcherView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CClientDC aDC(this); // Create a device context for the current view
OnPrepareDC(&aDC); // Get origin adjusted
aDC.DPtoLP(&point); // convert from Device Points to Logical Points
if(m_MoveMode)
{ // This is for when the element move is complete
// In moving mode, so drop the element
m_MoveMode = FALSE; // Kill the move mode
m_pSelected = 0; // De-selected the element
GetDocument()->UpdateAllViews(0); // Redraw all the views
GetDocument()->SetModifiedFlag(); // for serialization
}
else
{ // Create the CTextDialog Object and move it
CSketcherDoc* pDoc = GetDocument(); // Get a document pointer
if(pDoc->GetElementType() == TEXT)
{
CTextDialog aDlg;
if(aDlg.DoModal() == IDOK)
{
// Exit OK so create a text element
CFont aFont;
aFont.CreatePointFont(100, "");
CFont* pOldFont = aDC.SelectObject(&aFont);
CSize TextExtent = aDC.GetTextExtent(aDlg.m_TextString);
// Get bottom right of text rectangle - MM_LOENGLISH
CPoint BottomRt(point.x+TextExtent.cx, point.y-TextExtent.cy);
CText* pTextElement = new CText(point, BottomRt, aDlg.m_TextString, pDoc->GetElementColor());
// Add the element to the document
pDoc->AddElement(pTextElement);
// Get all views updated
pDoc->UpdateAllViews(0,0,pTextElement);
aDC.SelectObject(pOldFont);
}
return;
}
// This is for not being in element move mode
m_FirstPoint = point; // Record-Store the cursor position
SetCapture(); // Capture subsequent mouse messages
}
}
void CSketcherView::OnLButtonUp(UINT nFlags, CPoint point)
{
if(this == GetCapture())
ReleaseCapture(); // Stop capturing mouse messages
// If there is an element add it to the document
// Make sure there is an element
if(m_pTempElement)
{
// Call a document class function to store the element
// pointed to by m_pTempElement in the document object
GetDocument()->AddElement(m_pTempElement);
GetDocument()->UpdateAllViews(0,0,m_pTempElement); // Update all views
// Redraw the current area
InvalidateRect(0); // 0 invalidates the whole client area
m_pTempElement = 0; // Reset the element pointer
}
}
void CSketcherView::OnMouseMove(UINT nFlags, CPoint point)
{
// Define a Device Context object for the view
CClientDC aDC(this);
// ERRATA aDC.SetROP2(R2_NOTXORPEN); // Set the drawing mode
OnPrepareDC(&aDC); // Get origin adjusted
// If the move mode is true, move the selected element
// and return
if(m_MoveMode)
{
aDC.DPtoLP(&point); // Convert to logical coordinates
MoveElement(aDC, point); // Move the element
return;
}
// This "if" works only if the left button is down and the
// left button down handler for the view has been called.
if((nFlags & MK_LBUTTON) && (this == GetCapture()))
{
aDC.DPtoLP(&point); // convert device point to Logical
m_SecondPoint = point; // Save the current cursor position
if(m_pTempElement)
{
if(CURVE==GetDocument()->GetElementType()) // Is it a curve
{
// We are drawing a curv
// so add a segment to the existing curve
(static_cast<CCurve*>(m_pTempElement))->AddSegment(m_SecondPoint);
m_pTempElement->Draw(&aDC); // Now draw it
return; // It is done
}
aDC.SetROP2(R2_NOTXORPEN); // Set drawing mode
// Redraw the old element so it disappears from the view
m_pTempElement->Draw(&aDC);
delete m_pTempElement; // Delete the old element
m_pTempElement = 0; // Reset the pointer to 0
}
// Create a temporary element of the type and color that
// is recorded in the document object, and draw it
m_pTempElement = CreateElement(); // Create a new element
m_pTempElement->Draw(&aDC); // Draw the element
}
else // We are not drawing an element
{ // so do highlighting
CRect aRect;
// Get current cursor position
CElement* pCurrentSelection = SelectElement(point);
if(pCurrentSelection != m_pSelected)
{
if(m_pSelected) // Old element selected
{ // Yes, so draw it unselected -- still in same rect
aRect = m_pSelected->GetBoundRect(); // Get bounding rect
aDC.LPtoDP(aRect); // Convert to device coordinates
aRect.NormalizeRect();
// Invalidate area - FALSE means do not redraw background
InvalidateRect(aRect, FALSE);
}
m_pSelected = pCurrentSelection; // Save element under cursom
if(m_pSelected)
{
aRect = m_pSelected->GetBoundRect(); // Get bounding rect
aDC.LPtoDP(aRect); // Convert to device coordinates
aRect.NormalizeRect();
InvalidateRect(aRect, FALSE);
}
}
}
}
// Create an element of the current type
CElement* CSketcherView::CreateElement()
{
// Get a pointer to the document for this view
CSketcherDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc); // Verify the pointer is good
/* This was replaced by If statement to accommodate changes in
the ExtDLLExample.dll.
Now select the element using the type stored in the document
switch(pDoc->GetElementType())
{
case RECTANGLE:
return new CRectangle(m_FirstPoint, m_SecondPoint, pDoc->GetElementColor(), pDoc->GetPenStyle(), pDoc->GetPenWidth());
case CIRCLE:
return new CCircle(m_FirstPoint, m_SecondPoint, pDoc->GetElementColor(), pDoc->GetPenStyle(), pDoc->GetPenWidth());
case CURVE:
return new CCurve(m_FirstPoint, m_SecondPoint, pDoc->GetElementColor(), pDoc->GetPenStyle(), pDoc->GetPenWidth());
case LINE:
return new CLine(m_FirstPoint, m_SecondPoint, pDoc->GetElementColor(), pDoc->GetPenStyle(), pDoc->GetPenWidth());
case ELLIPSE:
return new CEllipse(m_FirstPoint, m_SecondPoint, pDoc->GetElementColor(), pDoc->GetPenStyle(), pDoc->GetPenWidth());
default:
// Something's gone wrong
AfxMessageBox("Bad Element code", MB_OK);
AfxAbort();
return NULL;
} */
// Now select the element using the type stored in the document
WORD ElementType = pDoc->GetElementType();
if(ElementType==RECTANGLE)
return new CRectangle(m_FirstPoint, m_SecondPoint, pDoc->GetElementColor(), pDoc->GetPenStyle(), pDoc->GetPenWidth());
if(ElementType==CIRCLE)
return new CCircle(m_FirstPoint, m_SecondPoint, pDoc->GetElementColor(), pDoc->GetPenStyle(), pDoc->GetPenWidth());
if(ElementType==CURVE)
return new CCurve(m_FirstPoint, m_SecondPoint, pDoc->GetElementColor(), pDoc->GetPenStyle(), pDoc->GetPenWidth());
if(ElementType==ELLIPSE)
return new CEllipse(m_FirstPoint, m_SecondPoint, pDoc->GetElementColor(), pDoc->GetPenStyle(), pDoc->GetPenWidth());
else
// Always default to a line
return new CLine(m_FirstPoint, m_SecondPoint, pDoc->GetElementColor(), pDoc->GetPenStyle(), pDoc->GetPenWidth());
}
CElement* CSketcherView::SelectElement(CPoint aPoint)
{
// Convert parameter aPoint to logical coordinates
CClientDC aDC(this);
OnPrepareDC(&aDC);
aDC.DPtoLP(&aPoint);
CSketcherDoc* pDoc=GetDocument(); // Get a pointer to the document
CElement* pElement = 0; // Store and element pointer
CRect aRect(0,0,0,0); // Store a rectangle
POSITION aPos = pDoc->GetListTailPosition(); // Get last element position
while(aPos)
{
pElement=pDoc->GetPrev(aPos);
aRect = pElement->GetBoundRect();
// Select the first element that appears under the cursor
if(aRect.PtInRect(aPoint))
return pElement;
}
return 0;
}
void CSketcherView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)
{
// Invalidate the area corresponding to the element pointed to
// if there is one, otherwise invalidate the whole client area.
if(pHint)
{
CClientDC aDC(this); // Create a device context
OnPrepareDC(&aDC); // Get origin adjusted
// Get the enclosing rectangle and convert to client coordinates
CRect aRect=static_cast<CElement*>(pHint)->GetBoundRect();
aDC.LPtoDP(aRect);
// The code below was add due to changing from MM_TEXT to
// MM_LOENGLISH mapping mode.
aRect.NormalizeRect();
InvalidateRect(aRect); // Get the area redrawn
}
else
InvalidateRect(0);
}
void CSketcherView::OnInitialUpdate()
{
ResetScrollSizes(); // Set up the scrollbars
CScrollView::OnInitialUpdate();
// THESE ARE NO LONGER USED
// Define document size
//CSize DocSize(3000,3000);
// Set mapping mode and document size
//SetScrollSizes(MM_LOENGLISH,DocSize);
}
void CSketcherView::OnMove()
{
// Get the coordinate of the current position of the cursor
// Convert the cursor position to logical coords
// Remember the initial cursor positon
// Set the move mode flag ON
// GetCursonPos() is a WinAPI function
// ScreenToClient() is inherited from the view class
CClientDC aDC(this);
OnPrepareDC(&aDC); // Setup the device context
GetCursorPos(&m_CursorPos); // Get cursor position in screen coords
ScreenToClient(&m_CursorPos); // Convert to client coords
aDC.DPtoLP(&m_CursorPos); // Convert to logical coords
m_FirstPos = m_CursorPos; // Remember first position
m_MoveMode = TRUE; // Start move mode
}
void CSketcherView::OnDelete()
{
// The code to delete an element is only executed if m_pSelected contains
// a valid address indicating that there is an element to delete. It gets
// a pointer to the document and calls the function DeleteElement() for
// the document object. Then it updates the document wiht UpdateAllViews.
if(m_pSelected)
{
CSketcherDoc* pDoc = GetDocument(); // Get the document pointer
pDoc->DeleteElement(m_pSelected); // Delete the element
pDoc->UpdateAllViews(0); // Redraw all of the views
m_pSelected = 0; // Reset selected element pointer
}
}
void CSketcherView::OnRButtonUp(UINT nFlags, CPoint point)
{
// Find the element under the pointer
// Point is the client coordinates point.x and point.y
// NOLONGER NEEDED - m_pSelected = SelectElement(point);
// Create the cursor menu - all are inherited functions
CMenu aMenu; // CMenu is a built in class of MFC
aMenu.LoadMenu(IDR_CURSOR_MENU1); // Load the cursor menu
ClientToScreen(&point); // Convert to screen coordinates
// Display the pop-up at the cursor position
if(m_pSelected)
aMenu.GetSubMenu(0)->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON, point.x, point.y, this);
else
{ // These 2 sections of code are to check & uncheck the popup menus
// Check color menu items
COLORREF Color = GetDocument()->GetElementColor();
aMenu.CheckMenuItem(ID_COLOR_BLACK, (BLACK==Color?MF_CHECKED:MF_UNCHECKED)|MF_BYCOMMAN D);
aMenu.CheckMenuItem(ID_COLOR_RED, (RED==Color?MF_CHECKED:MF_UNCHECKED)|MF_BYCOMMAND) ;
aMenu.CheckMenuItem(ID_COLOR_GREEN, (GREEN==Color?MF_CHECKED:MF_UNCHECKED)|MF_BYCOMMAN D);
aMenu.CheckMenuItem(ID_COLOR_BLUE, (BLUE==Color?MF_CHECKED:MF_UNCHECKED)|MF_BYCOMMAND );
// Check element menu items
WORD ElementType = GetDocument()->GetElementType();
aMenu.CheckMenuItem(ID_ELEMENT_LINE, (LINE==ElementType?MF_CHECKED:MF_UNCHECKED)|MF_BYC OMMAND);
aMenu.CheckMenuItem(ID_ELEMENT_RECTANGLE, (RECTANGLE==ElementType?MF_CHECKED:MF_UNCHECKED)|M F_BYCOMMAND);
aMenu.CheckMenuItem(ID_ELEMENT_CIRCLE, (CIRCLE==ElementType?MF_CHECKED:MF_UNCHECKED)|MF_B YCOMMAND);
aMenu.CheckMenuItem(ID_ELEMENT_CURVE, (CURVE==ElementType?MF_CHECKED:MF_UNCHECKED)|MF_BY COMMAND);
aMenu.CheckMenuItem(ID_ELEMENT_ELLIPSE, (ELLIPSE==ElementType?MF_CHECKED:MF_UNCHECKED)|MF_ BYCOMMAND);
aMenu.CheckMenuItem(ID_ELEMENT_TEXT, (TEXT==ElementType?MF_CHECKED:MF_UNCHECKED) |MF_BYCOMMAND);
// Display the context pop-up
aMenu.GetSubMenu(1)->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON, point.x, point.y, this);
}
// The code below was automatically included.
// CScrollView::OnRButtonUp(nFlags, point);
}
void CSketcherView::MoveElement(CClientDC &aDC, const CPoint &point)
{
CSize Distance = point - m_CursorPos; // Obtain move distance
m_CursorPos = point; // Set current point as first point for next time
// If there is an element selected, move it
if(m_pSelected)
{
// If the element is text use this method
if(m_pSelected->IsKindOf(RUNTIME_CLASS(CText)))
{
CRect OldRect=m_pSelected->GetBoundRect(); // Get old bound rect
m_pSelected->Move(Distance); // Now move the element
CRect NewRect = m_pSelected->GetBoundRect(); // Get new bound rect
OldRect.UnionRect(&OldRect, &NewRect); // Combine the bound rects
aDC.LPtoDP(OldRect); // Convert to client coordinates
OldRect.NormalizeRect(); // Normalize combined area
InvalidateRect(&OldRect); // Invalidate combined area
UpdateWindow(); // Redraw immediately
m_pSelected->Draw(&aDC,m_pSelected); // Draw highlighted
return;
}
// Otherwise use this method
aDC.SetROP2(R2_NOTXORPEN);
m_pSelected->Draw(&aDC, m_pSelected); // Draw the element to erase
m_pSelected->Move(Distance); // Now move the element
m_pSelected->Draw(&aDC, m_pSelected); // Draw the moved element
}
}
void CSketcherView::OnRButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
// The move element mode has been aborted
if(m_MoveMode)
{
// In moving mode, so drop element back in original position
CClientDC aDC(this);
OnPrepareDC(&aDC); // Get origin adjusted
MoveElement(aDC, m_FirstPos); // Move element to original position
m_MoveMode = FALSE; // Kill the move mode
GetDocument()->UpdateAllViews(0); // Redraw the views
return; // It is done
}
}
void CSketcherView::OnSendtoback()
{ // Change the elements position in the list
// Pass the currently selected element pointer to SendToBack
// function which is implemented in the CSketcherDoc class.
GetDocument()->SendToBack(m_pSelected); // Move element in list
}
void CSketcherView::OnViewScale()
{
// TODO: Add your command handler code here
CScaleDialog aDlg; // Create a dialog object
aDlg.m_Scale = m_Scale; // Pass and store the view scale value in dialog
if(aDlg.DoModal() == IDOK)
{
m_Scale = 1 + aDlg.m_Scale; // Get the new scale and store it
// Get the frame window for this view
CChildFrame* viewFrame = static_cast<CChildFrame*>(GetParentFrame());
// Build the message string HE USED ...Msg("View Scale:")
CString StatusMsg("View Scale:");
StatusMsg += static_cast<char>('0' + m_Scale);
// Write the string to the status bar
viewFrame->m_StatusBar.GetStatusBarCtrl().SetText(StatusMs g, 0, 0);
ResetScrollSizes(); // Adjust the scrollbar scaling
InvalidateRect(0); // Invalidate the whole window
}
}
// This function is called by the framework for output to the printer as
// well as the screen. One must make sure that when printing a scale of
// 1 is used to set the mapping from logical coordinates to device
// coordinates. If left as is, the output would be at current view scale.
// This would not take into account how many pages are needed and setting
// the origin of each page.
void CSketcherView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
{
// TODO: Add your specialized code here and/or call the base class
int Scale = m_Scale; // Store the scale locally
if(pDC->IsPrinting())
Scale=1; // If we are printing, set scale to 1
CScrollView::OnPrepareDC(pDC, pInfo);
CSketcherDoc* pDoc = GetDocument();
pDC->SetMapMode(MM_ANISOTROPIC); // Set the map mode
CSize DocSize = pDoc->GetDocSize(); // Get the document size
// Y extent must be negative because we want MM_LOENGLISH
DocSize.cy = -DocSize.cy; // Change sign of Y
pDC->SetWindowExt(DocSize); // Now set the window extent
// Get the number of pixels per inch in X and Y
// for printer or screen
int xLogPixels = pDC->GetDeviceCaps(LOGPIXELSX);
int yLogPixels = pDC->GetDeviceCaps(LOGPIXELSY);
// Calculate the viewport extent in X and Y
int xExtent = DocSize.cx * Scale * xLogPixels / 100;
int yExtent = DocSize.cy * Scale * yLogPixels / 100;
pDC->SetViewportExt(xExtent, -yExtent); // Set viewport extent
}
void CSketcherView::ResetScrollSizes()
{
CClientDC aDC(this);
OnPrepareDC(&aDC); // Setup the device context
// Get the document size
CSize DocSize = GetDocument()->GetDocSize();
aDC.LPtoDP(&DocSize); // Get the size in pixels
// Setup the scrollbars
SetScrollSizes(MM_TEXT, DocSize);
}
BOOL CSketcherView::OnScroll(UINT nScrollCode, UINT nPos, BOOL bDoScroll)
{
// I put this function in. The book did not have it.
// TODO: Add your specialized code here and/or call the base class
// This code is necessary to solve the disappearing curves
// when the scrollbars are used.
GetDocument()->UpdateAllViews(0); // Redraw all the views
return CScrollView::OnScroll(nScrollCode, nPos, bDoScroll);
}
void CSketcherView::OnPrint(CDC* pDC, CPrintInfo* pInfo)
{
CPrintData* pPrintData = static_cast<CPrintData*>(pInfo->m_lpUserData);
// Output the document file name
pDC->SetTextAlign(TA_CENTER); // Center the following text
pDC->TextOut(pInfo->m_rectDraw.right/2, -05, pPrintData->m_DocTitle);
pDC->SetTextAlign(TA_LEFT); // Left justify the text
// Print the page number at the bottom of the page
CString PageNum;
PageNum.Format("Page %d", pInfo->m_nCurPage);
pDC->SetTextAlign(TA_RIGHT);
pDC->TextOut(pInfo->m_rectDraw.right/2, -1030, PageNum);
pDC->SetTextAlign(TA_LEFT);
// Calculate the origin point for the current page
int xOrg = pPrintData->m_DocRefPoint.x + 700 *
((pInfo->m_nCurPage-1) % (pPrintData->m_nWidths));
int yOrg = pPrintData->m_DocRefPoint.y - 1000 *
((pInfo->m_nCurPage - 1) / (pPrintData->m_nWidths));
// Calculate offsets to cente drawing area on page as positive values
int xOffset = (pInfo->m_rectDraw.right - 700) / 2;
int yOffset = -(pInfo->m_rectDraw.bottom + 1000) / 2;
// Change window origin to correspond to current page & save old origin
CPoint OldOrg=pDC->SetWindowOrg(xOrg-xOffset, yOrg+yOffset);
// Define a clip rectangle the size of the printed area
pDC->IntersectClipRect(xOrg, yOrg, xOrg+700, yOrg-1000);
OnDraw(pDC); // Draw the whole document
pDC->SelectClipRgn(NULL); // Remove the clip rectangle
pDC->SetWindowOrg(OldOrg); // Restore old window origin
// CScrollView::OnPrint(pDC, pInfo);
}
|