www.pudn.com > uoth_src.zip > PrintOutput.cpp


//----------------------------------------------------------------------------- 
//  
// @doc 
// 
// @module	PrintOutput.cpp - Print support | 
// 
// This module contains the definition of the print support 
// 
// Copyright (c) 2002 - Descartes Systems Sciences, Inc. 
// 
// All rights reserved. 
// 
// Redistribution and use in source and binary forms, with or without  
// modification, are permitted provided that the following conditions are  
// met: 
//  
// 1. Redistributions of source code must retain the above copyright notice,  
//    this list of conditions and the following disclaimer.  
// 2. Neither the name of Descartes Systems Sciences, Inc nor the names of  
//    its contributors may be used to endorse or promote products derived  
//    from this software without specific prior written permission. 
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS  
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT  
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR  
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,  
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED  
// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR  
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING  
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS  
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
// 
// @end 
// 
// $History: PrintOutput.cpp $ 
//       
//----------------------------------------------------------------------------- 
 
#include "StdAfx.h" 
#include "PrintOutput.h" 
#include "PrintingDlg.h" 
#include "Treasure.h" 
#include "Region.h" 
#include "uoth.h" 
#include "PrintDlg.h" 
#include "Filter.h" 
#include "Scroll.h" 
 
// 
// Debug NEW 
// 
 
#if defined (_DEBUG) 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
// 
// Externals 
// 
 
extern TCHAR g_szAppName []; 
extern CPrinter g_sPrinter; 
extern CDevMode g_sDevMode; 
extern CSize g_sizeSmallMap; 
extern CSize g_sizeLargeMap; 
extern CRect g_rectPrintMargins; 
extern CFilter g_sFilter; 
 
// 
// Printing abort processor 
// 
 
BOOL CALLBACK PrintingAbortProc (HDC, int) 
{ 
	MSG   msg; 
	while (!CPrintingDlg::gm_fPrintAborted &&  
		PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) 
	{ 
		TranslateMessage (&msg); 
		DispatchMessage (&msg); 
	} 
	return !CPrintingDlg::gm_fPrintAborted; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc  constructor. 
// 
// @rdesc None. 
// 
//----------------------------------------------------------------------------- 
 
CPrintOutput::CPrintOutput () 
{ 
 
	// 
	// Perform basic initialization 
	// 
 
	m_hdc = NULL; 
	m_nCurPage = 0; 
	m_tmHeight = 0; 
	m_tmAveCharWidth = 0; 
	m_fError = false; 
	m_nPageUsed = INT_MAX; 
	return; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc  Destructor. 
// 
// @rdesc None. 
// 
//----------------------------------------------------------------------------- 
 
CPrintOutput::~CPrintOutput () 
{ 
	return; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Print a centered string 
// 
// @parm LPCTSTR | pszString | String to print 
// 
// @parm int | y | Y position on page 
// 
// @rdesc None. 
// 
//----------------------------------------------------------------------------- 
 
void CPrintOutput::PrintCentered (LPCTSTR pszString, int y) 
{ 
	// 
	// Get the length of the string 
	// 
 
	int nLength = (int) _tcslen (pszString); 
 
	// 
	// Get the text size 
	// 
 
	CSize sizeText; 
	::GetTextExtentPoint32 (m_hdc, pszString, nLength, &sizeText); 
 
	// 
	// Compute the x position 
	// 
 
	int x = (m_rectPage .Width () - sizeText .cx) / 2 + m_rectPage .left; 
 
	// 
	// Print string 
	// 
 
	::TextOut (m_hdc, x, y, pszString, nLength); 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Print a page header 
// 
// @rdesc None. 
// 
//----------------------------------------------------------------------------- 
 
void CPrintOutput::PrintPageHeader () 
{ 
	USES_CONVERSION; 
	TCHAR szBuffer [256]; 
 
	// 
	// Generate the title 
	// 
 
	PrintCentered (g_szAppName, m_rectPage .top); 
 
	// 
	// Format the second line 
	// 
 
	::GetDateFormat (LOCALE_USER_DEFAULT, DATE_SHORTDATE,  
		&m_stStart, NULL, szBuffer, _countof (szBuffer)); 
	LPTSTR p = szBuffer + _tcslen (szBuffer); 
	*p++ = ' '; 
	::GetTimeFormat (LOCALE_USER_DEFAULT, 0, &m_stStart, NULL,  
		p, _countof (szBuffer) - (p - szBuffer)); 
	PrintCentered (szBuffer, m_rectPage .top + m_tmHeight * 2); 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Print a page footer 
// 
// @rdesc None. 
// 
//----------------------------------------------------------------------------- 
 
void CPrintOutput::PrintPageFooter () 
{ 
	// 
	// Format the page number at the bottom 
	// 
 
	CString str; 
	str .Format (IDS_PRINT_PAGENUM, m_nCurPage); 
	PrintCentered (str, m_rectPage .bottom - m_tmHeight); 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Print configuration 
// 
// @parm HWND | hWnd | Window requesting print 
// 
// @rdesc None 
// 
//----------------------------------------------------------------------------- 
 
void CPrintOutput::Print (HWND hWnd) 
{ 
	bool fDrawImages = true; 
	bool fDrawImageBackground = false; 
	bool fDrawSimpleMap = true; 
	ScrollBorder nScrollBorder; 
	bool fImageHalfSize = true; 
	CString str; 
 
	// 
	// Create a temp filter 
	// 
 
	CFilter sFilter; 
	sFilter = g_sFilter; 
 
	// 
	// Display the print dialog 
	// 
 
	CPrintDlg dlg (&sFilter); 
	if (dlg .DoModal (hWnd) != IDOK) 
		return; 
 
	// 
	// Update the filter 
	// 
 
	sFilter .Update (); 
 
	// 
	// Set the flags 
	// 
 
	switch (dlg .m_nMapImage) 
	{ 
		case CPrintDlg::NoImage: 
			fDrawImages = false; 
			fDrawImageBackground = false; 
			fDrawSimpleMap = false; 
			fImageHalfSize = false; 
			break; 
		case CPrintDlg::BW_Small: 
			fDrawImages = true; 
			fDrawImageBackground = false; 
			fDrawSimpleMap = true; 
			fImageHalfSize = true; 
			break; 
		case CPrintDlg::BW_Large: 
			fDrawImages = true; 
			fDrawImageBackground = false; 
			fDrawSimpleMap = true; 
			fImageHalfSize = false; 
			break; 
		case CPrintDlg::Color_Small: 
			fDrawImages = true; 
			fDrawImageBackground = true; 
			fDrawSimpleMap = false; 
			fImageHalfSize = true; 
			break; 
		case CPrintDlg::Color_Large: 
			fDrawImages = true; 
			fDrawImageBackground = true; 
			fDrawSimpleMap = false; 
			fImageHalfSize = false; 
			break; 
		default: 
			assert (false); 
			return; 
	} 
 
	// 
	// Get the current time 
	// 
 
	::GetLocalTime (&m_stStart); 
 
	// 
	// Open the printer 
	// 
 
	m_hdc = g_sPrinter .CreatePrinterDC (g_sDevMode .m_pDevMode); 
	if (m_hdc == NULL) 
		return; 
 
	// 
	// Get the device name 
	// 
 
	CString strDeviceName; 
	CString strPortName; 
	{ 
		CPrinterInfo <5> pinfo5; 
		CPrinterInfo <2> pinfo2; 
		//Some printers fail for PRINTER_INFO_5 in some situations 
		if (pinfo5 .GetPrinterInfo (g_sPrinter)) 
		{ 
			strDeviceName = pinfo5 .m_pi ->pPrinterName; 
			strPortName = pinfo5 .m_pi ->pPortName; 
		} 
		else if (pinfo2 .GetPrinterInfo (g_sPrinter)) 
		{ 
			strDeviceName = pinfo2 .m_pi ->pPrinterName; 
			strPortName = pinfo2 .m_pi ->pPortName; 
		} 
	} 
 
	// 
	// Get the border style 
	// 
 
	nScrollBorder = fDrawSimpleMap ? ScrollBorder_Thin : ScrollBorder_Thick; 
 
	// 
	// Get the rect for the image including the scroll size 
	// 
 
	CRect rectImage (CPoint (0, 0), dlg .m_nContent == CPrintDlg::Treasures  
		? g_sizeSmallMap : g_sizeLargeMap ); 
	CScroll::DeflateRect (ScrollBorder_Thick, &rectImage); 
	CScroll::InflateRect (nScrollBorder, &rectImage); 
	rectImage .OffsetRect (- rectImage .left, - rectImage .top); 
	CScroll scroll (nScrollBorder, fDrawImageBackground,  
		RGB (255, 255, 255), rectImage); 
 
	// 
	// Create the temp destination bitmap 
	// 
 
	BITMAPINFOHEADER BMI; 
	BMI .biSize = sizeof (BITMAPINFOHEADER); 
	BMI .biWidth = rectImage .Width (); 
	BMI .biHeight = rectImage .Height (); 
	BMI .biPlanes = 1; 
	BMI .biBitCount = 32; 
	BMI .biCompression = BI_RGB; 
	BMI .biSizeImage = 0; 
	BMI .biXPelsPerMeter = 0; 
	BMI .biYPelsPerMeter = 0; 
	BMI .biClrUsed = 0; 
	BMI .biClrImportant = 0; 
	BYTE *pDstBits; 
	CBitmap bmImage; 
	bmImage = ::CreateDIBSection (m_hdc, (BITMAPINFO *) &BMI,  
		DIB_RGB_COLORS, (void **) &pDstBits, 0, 0l); 
	CDC dcImage; 
	dcImage .CreateCompatibleDC (NULL); 
	HBITMAP hbmOld = dcImage .SelectBitmap (bmImage); 
 
	// 
	// Pixel size 
	// 
 
	CSize sizePixel ( 
		::GetDeviceCaps (m_hdc, LOGPIXELSX), 
		::GetDeviceCaps (m_hdc, LOGPIXELSY) 
		); 
	CSize sizeImagePrint ( 
		MulDiv (rectImage .Width (), sizePixel .cx, fImageHalfSize ? 200 : 100), 
		MulDiv (rectImage .Height (), sizePixel .cy, fImageHalfSize ? 200 : 100) 
		); 
 
	// 
	// Get the metrics of the dc 
	// 
 
	TEXTMETRIC tm;	 
	::GetTextMetrics (m_hdc, &tm); 
	m_tmHeight = tm .tmHeight; 
	m_tmAveCharWidth = tm .tmAveCharWidth; 
 
	// 
	// Get the page drawing rect 
	// 
 
	GetDrawingArea (m_hdc, &g_rectPrintMargins, &m_rectPage); 
 
	// 
	// Compute draw size from page size 
	// 
 
	int nLines = (m_rectPage .Height ()) / m_tmHeight; 
	m_rectDraw .left   = m_rectPage .left; 
	m_rectDraw .top    = m_rectPage .top + m_tmHeight * 4; 
	m_rectDraw .right  = m_rectPage .right; 
	m_rectDraw .bottom = m_rectDraw .top + m_tmHeight * (nLines - 6); 
 
	// 
	// Create the document information block (since we don't 
	//	support the selection of a printer at print time, then 
	//  we don't need to support printing to file.) 
	// 
 
	DOCINFO docInfo; 
	memset (&docInfo, 0, sizeof (DOCINFO)); 
	docInfo .cbSize = sizeof (DOCINFO); 
	docInfo .lpszDocName = g_szAppName; 
	docInfo .lpszOutput = NULL; 
 
	// 
	// Setup the printing DC 
	// 
 
	::SetAbortProc (m_hdc, PrintingAbortProc); 
 
	// 
	// Disable main window while printing 
	// 
 
	::EnableWindow (hWnd, FALSE); 
 
	// 
	// Initialize the contents of the dialog box 
	// 
 
	CPrintingDlg dlgPrintStatus; 
	dlgPrintStatus .Create (hWnd); 
	str .Format (IDS_PRINT_ON, (LPCTSTR) strPortName); 
	dlgPrintStatus .SetWindowText (g_szAppName); 
	dlgPrintStatus .SetDlgItemText (IDC_PRINT_PRINTERNAME, strDeviceName); 
	dlgPrintStatus .SetDlgItemText (IDC_PRINT_PORTNAME, str); 
	dlgPrintStatus .SetDlgItemText (IDC_PRINT_APPNAME, g_szAppName); 
	dlgPrintStatus .ShowWindow (SW_SHOW); 
	dlgPrintStatus .UpdateWindow (); 
 
	// 
	// Start document printing process, if failed 
	// 
 
	if (::StartDoc (m_hdc, &docInfo) == SP_ERROR) 
	{ 
 
		// 
		// Enable main window before proceeding 
		// 
 
		::EnableWindow (hWnd, TRUE); 
 
		// 
		// Cleanup and show error message 
		// 
 
		dlgPrintStatus .DestroyWindow(); 
		str .LoadString (IDS_ERR_PRINT_START); 
		::MessageBox (hWnd, str, g_szAppName, MB_OK); 
		::DeleteDC (m_hdc); 
		dcImage .SelectBitmap (hbmOld); 
		return; 
	} 
 
	// 
	// Allocate space for the treasure draw array 
	// 
 
	int *panTreasures = (int *) alloca ( 
		CTreasure::gm_vTreasures .GetCount () * sizeof (int)); 
 
	// 
	// Loop through the objects 
	// 
 
	m_nPageUsed = INT_MAX; 
	m_nCurPage = 0; 
	m_fError = false; 
	bool fContinue = true; 
	for (int nIndex = 0;; ++nIndex) 
	{ 
 
		// 
		// Locals 
		// 
 
		CString str; 
 
		// 
		// If we are doing treasures 
		// 
 
		if (dlg .m_nContent == CPrintDlg::Treasures) 
		{ 
 
			// 
			// Validate the treasure 
			// 
 
			if (nIndex >= CTreasure::gm_vTreasures .GetCount ()) 
				break; 
			CTreasure *pTreasure = &CTreasure::gm_vTreasures [nIndex]; 
			if (!pTreasure ->IsValid ()) 
				continue; 
 
			// 
			// Get the treasure data 
			// 
 
			if (sFilter .IsMineFilterEnabled () && 
				!sFilter .DoesTreasureHaveMap (pTreasure ->m_nIndex)) 
				continue; 
			str = pTreasure ->GetInformation (dlg .m_fTerse); 
 
			// 
			// If we are drawing images, then draw 
			// 
 
			if (fDrawImages) 
			{ 
 
				// 
				// Get the map rect 
				// 
 
				CRect rectMap; 
				CPoint pt (pTreasure ->m_x, pTreasure ->m_y); 
				scroll .GetMapAt (pt, &rectMap); 
 
				// 
				// Draw the map 
				// 
 
				scroll .DrawMap (dcImage, rectMap, &pTreasure ->m_nIndex,  
					1, false, &sFilter, fDrawSimpleMap);	 
			} 
		} 
 
		// 
		// Otherwise, this is a region 
		// 
 
		else 
		{ 
 
			// 
			// Validate the region 
			// 
 
			if (nIndex >= CRegion::gm_vRegions .GetCount ()) 
				break; 
			CRegion *pRegion = &CRegion::gm_vRegions [nIndex]; 
			if (!pRegion ->IsValid ()) 
				continue; 
 
			// 
			// Get the treasure data 
			// 
 
			if (sFilter .IsMineFilterEnabled () && 
				!sFilter .DoesRegionHaveMap (pRegion ->m_nIndex)) 
				continue; 
			str = pRegion ->GetInformation (dlg .m_fTerse); 
 
			// 
			// If we are drawing images, then draw 
			// 
 
			if (fDrawImages) 
			{ 
 
				// 
				// Get the map rect 
				// 
 
				int nTreasures; 
				CRect rectMap; 
				scroll .GetRegionMap (nIndex, &nTreasures,  
					panTreasures, &rectMap); 
 
				// 
				// Draw the map 
				// 
 
				scroll .DrawMap (dcImage, rectMap, panTreasures,  
					nTreasures, true, &sFilter, fDrawSimpleMap);	 
			} 
		} 
 
		// 
		// Write current page 
		// 
 
		{ 
			CString strPage; 
			strPage .Format (IDS_PRINT_PAGENUM, m_nCurPage < 1 ? 1 : m_nCurPage); 
			dlgPrintStatus .SetDlgItemText (IDC_PRINT_PAGENUM, strPage); 
		} 
 
		// 
		// Compute the length of a section 
		// 
 
		CRect rectAll; 
		CRect rectText (m_rectDraw); 
		if (fDrawImages) 
			rectText .right -= sizeImagePrint .cx + m_tmAveCharWidth * 4; 
		::DrawText (m_hdc, str, str .GetLength (),  
			&rectText, DT_CALCRECT | DT_WORDBREAK); 
 
		// 
		// Compute the size of the while thing including the optional image 
		// 
 
		rectAll = rectText; 
		if (fDrawImages) 
		{ 
			if (rectAll .Height () < sizeImagePrint .cy + m_tmHeight) 
				rectAll .bottom = rectAll .top + sizeImagePrint .cy + m_tmHeight; 
		} 
 
		// 
		// If there isn't enough room on the page, start a new page 
		// 
 
		if (m_rectDraw .Height () - m_nPageUsed < rectAll .Height ()) 
		{ 
 
			// 
			// End the old page 
			// 
 
			if (m_nCurPage > 0) 
			{ 
				PrintPageFooter (); 
				if (::EndPage (m_hdc) < 0) 
				{ 
					m_fError = true; 
					break; 
				} 
			} 
 
			// 
			// Start new page 
			// 
 
			if (::StartPage (m_hdc) < 0) 
			{ 
				m_fError = true; 
				break; 
			} 
 
			// 
			// Generate header and footer 
			// 
 
			PrintPageHeader (); 
 
			// 
			// Reset values 
			// 
 
			m_nPageUsed = 0; 
			m_nCurPage++; 
		} 
 
		// 
		// Draw the rect 
		// 
 
		CRect rectText2 (rectText); 
		rectText2 .OffsetRect (0, m_nPageUsed); 
		::DrawText (m_hdc, str, str .GetLength (), 
			&rectText2, DT_WORDBREAK); 
 
		// 
		// Draw the image 
		// 
 
		if (fDrawImages) 
		{ 
 
			// 
			// Compute the rectangle 
			// 
 
			CRect rectImageOut; 
			rectImageOut .left = m_rectDraw .right - sizeImagePrint .cx; 
			rectImageOut .top = m_rectDraw .top + m_nPageUsed; 
			rectImageOut .right = m_rectDraw .right; 
			rectImageOut .bottom = rectImageOut .top + sizeImagePrint .cy; 
 
			// 
			// Blt the image 
			// 
 
			::StretchBlt (m_hdc, rectImageOut .left, rectImageOut .top, 
				rectImageOut .Width (), rectImageOut .Height (), dcImage, 
				0, 0, rectImage .Width (), rectImage .Height (), 
				SRCCOPY); 
		} 
 
		// 
		// Adjust the amount of the page used 
		// 
 
		m_nPageUsed += rectAll .Height (); 
 
		// 
		// Test for user termination 
		// 
 
		if (!PrintingAbortProc (m_hdc, 0)) 
			m_fError = true; 
	} 
 
	// 
	// End the page if need be 
	// 
 
	if (!m_fError && m_nCurPage > 0 && m_nPageUsed > 0) 
	{ 
		PrintPageFooter (); 
		if (::EndPage (m_hdc) < 0) 
			m_fError = true; 
	} 
 
	// 
	// Finish the document printing process 
	// 
 
	if (!m_fError) 
		::EndDoc (m_hdc); 
	else 
		::AbortDoc (m_hdc); 
 
	// 
	// Enable the main window 
	// 
 
	::EnableWindow (hWnd, TRUE); 
 
	// 
	// Destroy the printing dialog 
	// 
 
	dlgPrintStatus .DestroyWindow (); 
 
	// 
	// Delete the DC 
	// 
 
	::DeleteDC (m_hdc); 
	dcImage .SelectBitmap (hbmOld); 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Get the print rect based on the given margins 
// 
// @parm HDC | hDC | Printer DC 
// 
// @parm const RECT * | prectMargins | Margins in 1000th of an inch. 
// 
// @parm RECT * | pRect | Drawing area 
// 
// @rdesc None 
// 
//----------------------------------------------------------------------------- 
 
void CPrintOutput::GetDrawingArea (HDC hDC,  
	const RECT *prectMargins, RECT *pRect) 
{ 
 
	// 
	// Get the physical offset 
	// 
 
	CPoint ptPhysicalOffset ( 
		::GetDeviceCaps (hDC, PHYSICALOFFSETX), 
		::GetDeviceCaps (hDC, PHYSICALOFFSETY) 
		); 
 
	// 
	// Get the physical page size 
	// 
 
	CSize sizePhysical ( 
		::GetDeviceCaps (hDC, PHYSICALWIDTH), 
		::GetDeviceCaps (hDC, PHYSICALHEIGHT) 
		); 
 
	// 
	// Get the drawing size 
	// 
 
	CSize sizeDrawing ( 
		::GetDeviceCaps (hDC, HORZRES), 
		::GetDeviceCaps (hDC, VERTRES) 
		); 
 
	// 
	// Pixel size 
	// 
 
	CSize sizePixel ( 
		::GetDeviceCaps (hDC, LOGPIXELSX), 
		::GetDeviceCaps (hDC, LOGPIXELSY) 
		); 
 
	// 
	// Compute the actual drawing rect 
	// 
	 
	CRect rectDraw (ptPhysicalOffset, sizeDrawing); 
 
	// 
	// Compute the physical page rect 
	// 
 
	CRect rectPhysical (CPoint (0, 0), sizePhysical); 
 
	// 
	// Compute the margins in pixels 
	// 
 
	int nLeftMargin = ::MulDiv (sizePixel .cx, prectMargins ->left, 1000); 
	int nTopMargin = ::MulDiv (sizePixel .cy, prectMargins ->top, 1000); 
	int nRightMargin = ::MulDiv (sizePixel .cx, prectMargins ->right, 1000); 
	int nBottomMargin = ::MulDiv (sizePixel .cy, prectMargins ->bottom, 1000); 
 
	// 
	// Adjust the physical rect by the margins 
	// 
 
	pRect ->left = rectPhysical .left + nLeftMargin; 
	pRect ->top = rectPhysical .top + nTopMargin; 
	pRect ->right = rectPhysical .right - nRightMargin; 
	pRect ->bottom = rectPhysical .bottom - nBottomMargin; 
 
	// 
	// Make sure the rect is inside the drawing rect 
	// 
 
	if (pRect ->left < rectDraw .left) 
		pRect ->left = rectDraw .left; 
	if (pRect ->top < rectDraw .top) 
		pRect ->top = rectDraw .top; 
	if (pRect ->right > rectDraw .right) 
		pRect ->right = rectDraw .right; 
	if (pRect ->bottom > rectDraw .bottom) 
		pRect ->bottom = rectDraw .bottom; 
 
	// 
	// Adjust the rect (remember, the REAL drawing rect is 0,0 based 
	// on the drawing area and NOT the physical area.  Our computations 
	// are all based on the phyical area.) 
	// 
 
	::OffsetRect (pRect, - ptPhysicalOffset .x, - ptPhysicalOffset .y); 
	return; 
}