397 lines
13 KiB
C++
397 lines
13 KiB
C++
// printres.cpp : implementation of the CPrintResObj class
|
|
//
|
|
// #define PAGESETUP
|
|
|
|
#include "stdafx.h"
|
|
#include "pbrush.h"
|
|
#include "pbrusfrm.h"
|
|
#include "pbrusvw.h"
|
|
#include "pbrusdoc.h"
|
|
#include "imgwnd.h"
|
|
#include "bmobject.h"
|
|
#include "imgsuprt.h"
|
|
#include "printres.h"
|
|
#include "cmpmsg.h"
|
|
#include "imageatt.h"
|
|
#include "pgsetup.h"
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static CHAR BASED_CODE THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
IMPLEMENT_DYNAMIC( CPrintResObj, CObject )
|
|
|
|
#include "memtrace.h"
|
|
|
|
void MulDivRect(LPRECT r1, LPRECT r2, int num, int div)
|
|
{
|
|
r1->left = MulDiv(r2->left, num, div);
|
|
r1->top = MulDiv(r2->top, num, div);
|
|
r1->right = MulDiv(r2->right, num, div);
|
|
r1->bottom = MulDiv(r2->bottom, num, div);
|
|
}
|
|
|
|
/***************************************************************************/
|
|
// CPrintResObj implementation
|
|
|
|
CPrintResObj::CPrintResObj( CPBView* pView, CPrintInfo* pInfo )
|
|
{
|
|
m_pDIB = NULL;
|
|
m_pDIBpalette = NULL;
|
|
|
|
if (pInfo == NULL
|
|
|| pView == NULL
|
|
|| pView->m_pImgWnd == NULL
|
|
|| pView->m_pImgWnd->m_pImg == NULL
|
|
|| pView->m_pImgWnd->m_pImg->m_pBitmapObj == NULL)
|
|
return;
|
|
|
|
m_pView = pView;
|
|
|
|
m_iPicWidth = m_pView->m_pImgWnd->m_pImg->m_pBitmapObj->m_nWidth;
|
|
m_iPicHeight = m_pView->m_pImgWnd->m_pImg->m_pBitmapObj->m_nHeight;
|
|
|
|
// force the resource to save itself then use the dib to print
|
|
BOOL bOldFlag = m_pView->m_pImgWnd->m_pImg->m_pBitmapObj->m_bDirty;
|
|
m_pView->m_pImgWnd->m_pImg->m_pBitmapObj->m_bDirty = TRUE;
|
|
m_pView->m_pImgWnd->m_pImg->m_pBitmapObj->SaveResource( TRUE );
|
|
m_pView->m_pImgWnd->m_pImg->m_pBitmapObj->m_bDirty = bOldFlag;
|
|
|
|
m_pDIB = GlobalLock(m_pView->m_pImgWnd->m_pImg->m_pBitmapObj->m_hThing);
|
|
|
|
if (m_pDIB == NULL)
|
|
return;
|
|
|
|
m_pDIBpalette = CreateDIBPalette( (LPSTR)m_pDIB );
|
|
m_pDIBits = FindDIBBits ( (LPSTR)m_pDIB );
|
|
|
|
// save the scroll value off, then set to 0,0
|
|
m_cSizeScroll = m_pView->m_pImgWnd->GetScrollPos();
|
|
|
|
// save the zoom value off, then set to 100%
|
|
m_iZoom = m_pView->m_pImgWnd->GetZoom();
|
|
m_rtMargins.SetRectEmpty();
|
|
|
|
pInfo->m_nNumPreviewPages = 1;
|
|
pInfo->m_lpUserData = this;
|
|
}
|
|
|
|
/***************************************************************************/
|
|
|
|
CPrintResObj::~CPrintResObj()
|
|
{
|
|
GlobalUnlock(m_pView->m_pImgWnd->m_pImg->m_pBitmapObj->m_hThing);
|
|
}
|
|
|
|
/***************************************************************************/
|
|
|
|
void CPrintResObj::BeginPrinting( CDC* pDC, CPrintInfo* pInfo )
|
|
{
|
|
if (pDC == NULL
|
|
|| pDC->GetSafeHdc() == NULL)
|
|
return;
|
|
|
|
m_pView->m_pImgWnd->SetScroll( 0, 0 );
|
|
m_pView->m_pImgWnd->SetZoom ( 1 );
|
|
|
|
// get device sizes
|
|
|
|
int nHorzRes = pDC->GetDeviceCaps(HORZRES);
|
|
int nVertRes = pDC->GetDeviceCaps(VERTRES);
|
|
|
|
int nHorzSize = pDC->GetDeviceCaps(HORZSIZE);
|
|
int nVertSize = pDC->GetDeviceCaps(VERTSIZE);
|
|
|
|
int nPhysicalWidth = pDC->GetDeviceCaps(PHYSICALWIDTH);
|
|
int nPhysicalHeight = pDC->GetDeviceCaps(PHYSICALHEIGHT);
|
|
|
|
int nPhysicalOffsetX = pDC->GetDeviceCaps(PHYSICALOFFSETX);
|
|
int nPhysicalOffsetY = pDC->GetDeviceCaps(PHYSICALOFFSETY);
|
|
|
|
// calculate min margins in pixels
|
|
|
|
double cOutputXPelsPerMeter = (double) nHorzRes * 1000 / nHorzSize;
|
|
double cOutputYPelsPerMeter = (double) nVertRes * 1000 / nVertSize;
|
|
|
|
CRect rcMinMargins;
|
|
|
|
rcMinMargins.left = nPhysicalOffsetX;
|
|
rcMinMargins.top = nPhysicalOffsetY;
|
|
rcMinMargins.right = nPhysicalWidth - nHorzRes - nPhysicalOffsetX;
|
|
rcMinMargins.bottom = nPhysicalHeight - nVertRes - nPhysicalOffsetY;
|
|
|
|
m_rtMargins.left = max(0, (LONG) (theApp.m_rectMargins.left * cOutputXPelsPerMeter / 100000) - rcMinMargins.left );
|
|
m_rtMargins.top = max(0, (LONG) (theApp.m_rectMargins.top * cOutputYPelsPerMeter / 100000) - rcMinMargins.top );
|
|
m_rtMargins.right = max(0, (LONG) (theApp.m_rectMargins.right * cOutputXPelsPerMeter / 100000) - rcMinMargins.right );
|
|
m_rtMargins.bottom = max(0, (LONG) (theApp.m_rectMargins.bottom * cOutputYPelsPerMeter / 100000) - rcMinMargins.bottom);
|
|
|
|
// Quick sanity check
|
|
|
|
if (m_rtMargins.left + m_rtMargins.right >= nHorzRes)
|
|
{
|
|
m_rtMargins.left = m_rtMargins.right = 0;
|
|
}
|
|
|
|
if (m_rtMargins.top + m_rtMargins.bottom >= nVertRes)
|
|
{
|
|
m_rtMargins.top = m_rtMargins.bottom = 0;
|
|
}
|
|
|
|
CPageSetupData PageSetupData;
|
|
|
|
PageSetupData.bCenterHorizontally = theApp.m_bCenterHorizontally;
|
|
PageSetupData.bCenterVertically = theApp.m_bCenterVertically;
|
|
PageSetupData.bScaleFitTo = theApp.m_bScaleFitTo;
|
|
PageSetupData.nAdjustToPercent = theApp.m_nAdjustToPercent;
|
|
PageSetupData.nFitToPagesWide = theApp.m_nFitToPagesWide;
|
|
PageSetupData.nFitToPagesTall = theApp.m_nFitToPagesTall;
|
|
|
|
double cInputXPelsPerMeter = m_pView->m_pImgWnd->m_pImg->cXPelsPerMeter ?
|
|
m_pView->m_pImgWnd->m_pImg->cXPelsPerMeter : theApp.ScreenDeviceInfo.ixPelsPerDM * 10;
|
|
|
|
double cInputYPelsPerMeter = m_pView->m_pImgWnd->m_pImg->cYPelsPerMeter ?
|
|
m_pView->m_pImgWnd->m_pImg->cYPelsPerMeter : theApp.ScreenDeviceInfo.iyPelsPerDM * 10;
|
|
|
|
PageSetupData.fPhysicalImageWidth = (double) m_iPicWidth * cOutputXPelsPerMeter / cInputXPelsPerMeter;
|
|
PageSetupData.fPhysicalImageHeight = (double) m_iPicHeight * cOutputYPelsPerMeter / cInputYPelsPerMeter;
|
|
|
|
m_PhysicalPageSize.cx = pDC->GetDeviceCaps(HORZRES) - m_rtMargins.left - m_rtMargins.right;
|
|
m_PhysicalPageSize.cy = pDC->GetDeviceCaps(VERTRES) - m_rtMargins.top - m_rtMargins.bottom;
|
|
|
|
PageSetupData.CalculateImageRect(m_PhysicalPageSize, m_PhysicalOrigin, m_PhysicalScaledImageSize);
|
|
|
|
m_nPagesWide = PageSetupData.nFitToPagesWide;
|
|
|
|
int nPages = PageSetupData.nFitToPagesWide * PageSetupData.nFitToPagesTall;
|
|
|
|
pInfo->SetMaxPage(nPages);
|
|
|
|
// If only printing 1 page, should not be in 2 page mode
|
|
if (nPages == 1)
|
|
{
|
|
pInfo->m_nNumPreviewPages = 1;
|
|
}
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/* We not only move the window origin to allow us to print multiple pages */
|
|
/* wide but we also scale both the viewport and window extents to make them */
|
|
/* proportional (i.e. a line on the screen is the same size as on */
|
|
/* the printer). The pages to print are numbered across. For +---+---+ */
|
|
/* example, if there were 4 pages to print, then the first row | 1 | 2 | */
|
|
/* would have pages 1,2 and the second row would have pages 3,4. +---+---+ */
|
|
/* | 3 | 4 | */
|
|
/* +---+---+ */
|
|
/* */
|
|
/******************************************************************************/
|
|
|
|
void CPrintResObj::PrepareDC( CDC* pDC, CPrintInfo* pInfo )
|
|
{
|
|
if (pDC == NULL || pInfo == NULL)
|
|
return;
|
|
|
|
pDC->SetMapMode( MM_TEXT );
|
|
pDC->SetStretchBltMode( HALFTONE );
|
|
}
|
|
|
|
/***************************************************************************/
|
|
|
|
BOOL CPrintResObj::PrintPage( CDC* pDC, CPrintInfo* pInfo )
|
|
{
|
|
if (m_pDIB == NULL)
|
|
return FALSE;
|
|
|
|
int nPageCol = (pInfo->m_nCurPage - 1) % m_nPagesWide;
|
|
int nPageRow = (pInfo->m_nCurPage - 1) / m_nPagesWide;
|
|
|
|
int nX0 = m_PhysicalOrigin.x - nPageCol * m_PhysicalPageSize.cx;
|
|
int nY0 = m_PhysicalOrigin.y - nPageRow * m_PhysicalPageSize.cy;
|
|
|
|
CRect OutputImageRect;
|
|
|
|
OutputImageRect.left = max(nX0, 0);
|
|
OutputImageRect.top = max(nY0, 0);
|
|
OutputImageRect.right = min(nX0 + m_PhysicalScaledImageSize.cx, m_PhysicalPageSize.cx);
|
|
OutputImageRect.bottom = min(nY0 + m_PhysicalScaledImageSize.cy, m_PhysicalPageSize.cy);
|
|
|
|
if (OutputImageRect.right < 0 || OutputImageRect.bottom < 0)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
CRect InputImageRect;
|
|
|
|
InputImageRect.left = MulDiv(OutputImageRect.left - nX0, m_iPicWidth, m_PhysicalScaledImageSize.cx);
|
|
InputImageRect.top = MulDiv(OutputImageRect.top - nY0, m_iPicHeight, m_PhysicalScaledImageSize.cy);
|
|
InputImageRect.right = MulDiv(OutputImageRect.right - nX0, m_iPicWidth, m_PhysicalScaledImageSize.cx);
|
|
InputImageRect.bottom = MulDiv(OutputImageRect.bottom - nY0, m_iPicHeight, m_PhysicalScaledImageSize.cy);
|
|
|
|
if (InputImageRect.right < 0 || InputImageRect.bottom < 0)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
CPalette* ppalOld = NULL;
|
|
|
|
if (m_pDIBpalette != NULL)
|
|
{
|
|
ppalOld = pDC->SelectPalette( m_pDIBpalette, FALSE );
|
|
pDC->RealizePalette();
|
|
}
|
|
|
|
int nResult = StretchDIBits(
|
|
pDC->m_hDC,
|
|
m_rtMargins.left + OutputImageRect.left,
|
|
m_rtMargins.top + OutputImageRect.top,
|
|
OutputImageRect.Width(),
|
|
OutputImageRect.Height(),
|
|
InputImageRect.left,
|
|
m_iPicHeight - InputImageRect.bottom, // DIB's are upside down
|
|
InputImageRect.Width(),
|
|
InputImageRect.Height(),
|
|
m_pDIBits, (LPBITMAPINFO)m_pDIB,
|
|
DIB_RGB_COLORS, SRCCOPY
|
|
);
|
|
|
|
if (nResult == GDI_ERROR)
|
|
{
|
|
CmpMessageBox( IDS_ERROR_PRINTING, AFX_IDS_APP_TITLE, MB_OK | MB_ICONEXCLAMATION );
|
|
}
|
|
|
|
if (ppalOld != NULL)
|
|
{
|
|
pDC->SelectPalette( ppalOld, FALSE );
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/***************************************************************************/
|
|
|
|
void CPrintResObj::EndPrinting( CDC* pDC, CPrintInfo* pInfo )
|
|
{
|
|
if (pDC != NULL)
|
|
{
|
|
m_pView->m_pImgWnd->SetScroll( m_cSizeScroll.cx, m_cSizeScroll.cy );
|
|
|
|
// restore the zoom value
|
|
m_pView->m_pImgWnd->SetZoom( m_iZoom );
|
|
}
|
|
|
|
if (m_pDIBpalette != NULL)
|
|
delete m_pDIBpalette;
|
|
|
|
delete this;
|
|
}
|
|
|
|
/***************************************************************************/
|
|
|
|
inline int roundleast(int n)
|
|
{
|
|
int mod = n%10;
|
|
n -= mod;
|
|
if (mod >= 5)
|
|
n += 10;
|
|
else if (mod <= -5)
|
|
n -= 10;
|
|
return n;
|
|
}
|
|
|
|
static void RoundRect(LPRECT r1)
|
|
{
|
|
r1->left = roundleast(r1->left);
|
|
r1->right = roundleast(r1->right);
|
|
r1->top = roundleast(r1->top);
|
|
r1->bottom = roundleast(r1->bottom);
|
|
}
|
|
|
|
void CPBView::OnFilePageSetup()
|
|
{
|
|
CPageSetupDialog dlg;
|
|
PAGESETUPDLG& psd = dlg.m_psd;
|
|
TCHAR szMetric[2];
|
|
BOOL bMetric;
|
|
LCID lcidThread;
|
|
//
|
|
// We should use metric if the user has chosen CM in the
|
|
// Image Attributes dialog, OR if using Pels and the NLS
|
|
// setting is for metric
|
|
//
|
|
if (theApp.m_iCurrentUnits == ePIXELS)
|
|
{
|
|
lcidThread = GetThreadLocale();
|
|
GetLocaleInfo (lcidThread, LOCALE_IMEASURE, szMetric, 2);
|
|
bMetric = (szMetric[0] == TEXT('0'));
|
|
}
|
|
else
|
|
{
|
|
bMetric = ((eUNITS)theApp.m_iCurrentUnits == eCM); //centimeters
|
|
}
|
|
|
|
CPageSetupData PageSetupData;
|
|
|
|
PageSetupData.bCenterHorizontally = theApp.m_bCenterHorizontally;
|
|
PageSetupData.bCenterVertically = theApp.m_bCenterVertically;
|
|
PageSetupData.bScaleFitTo = theApp.m_bScaleFitTo;
|
|
PageSetupData.nAdjustToPercent = theApp.m_nAdjustToPercent;
|
|
PageSetupData.nFitToPagesWide = theApp.m_nFitToPagesWide;
|
|
PageSetupData.nFitToPagesTall = theApp.m_nFitToPagesTall;
|
|
|
|
double cXPelsPerMeter = m_pImgWnd->m_pImg->cXPelsPerMeter ?
|
|
m_pImgWnd->m_pImg->cXPelsPerMeter : theApp.ScreenDeviceInfo.ixPelsPerDM * 10;
|
|
double cYPelsPerMeter = m_pImgWnd->m_pImg->cYPelsPerMeter ?
|
|
m_pImgWnd->m_pImg->cYPelsPerMeter : theApp.ScreenDeviceInfo.iyPelsPerDM * 10;
|
|
|
|
PageSetupData.fPhysicalImageWidth = (double)m_pImgWnd->m_pImg->cxWidth * 100000 / cXPelsPerMeter;
|
|
PageSetupData.fPhysicalImageHeight = (double)m_pImgWnd->m_pImg->cyHeight * 100000 / cYPelsPerMeter;
|
|
|
|
if (!bMetric)
|
|
{
|
|
PageSetupData.fPhysicalImageWidth /= 2.54;
|
|
PageSetupData.fPhysicalImageHeight /= 2.54;
|
|
}
|
|
|
|
psd.Flags |= PSD_ENABLEPAGESETUPHOOK | PSD_ENABLEPAGEPAINTHOOK | PSD_ENABLEPAGESETUPTEMPLATE |
|
|
PSD_MARGINS | (bMetric ? PSD_INHUNDREDTHSOFMILLIMETERS : PSD_INTHOUSANDTHSOFINCHES);
|
|
int nUnitsPerInch = bMetric ? 2540 : 1000;
|
|
MulDivRect(&psd.rtMargin, theApp.m_rectMargins, nUnitsPerInch, MARGINS_UNITS);
|
|
RoundRect(&psd.rtMargin);
|
|
// get the current device from the app
|
|
PRINTDLG pd;
|
|
pd.hDevNames = NULL;
|
|
pd.hDevMode = NULL;
|
|
theApp.GetPrinterDeviceDefaults(&pd);
|
|
psd.hDevNames = pd.hDevNames;
|
|
psd.hDevMode = pd.hDevMode;
|
|
psd.hInstance = AfxGetInstanceHandle();
|
|
psd.lCustData = (LPARAM) &PageSetupData;
|
|
psd.lpfnPagePaintHook = CPageSetupData::PagePaintHook;
|
|
psd.lpfnPageSetupHook = CPageSetupData::PageSetupHook;
|
|
psd.lpPageSetupTemplateName = MAKEINTRESOURCE(IDD_PAGESETUPDLG);
|
|
|
|
if (dlg.DoModal() == IDOK)
|
|
{
|
|
RoundRect(&psd.rtMargin);
|
|
MulDivRect(theApp.m_rectMargins, &psd.rtMargin, MARGINS_UNITS, nUnitsPerInch);
|
|
//theApp.m_rectPageMargin = m_rectMargin;
|
|
theApp.SelectPrinter(psd.hDevNames, psd.hDevMode);
|
|
|
|
theApp.m_bCenterHorizontally = PageSetupData.bCenterHorizontally;
|
|
theApp.m_bCenterVertically = PageSetupData.bCenterVertically;
|
|
theApp.m_bScaleFitTo = PageSetupData.bScaleFitTo;
|
|
theApp.m_nAdjustToPercent = PageSetupData.nAdjustToPercent;
|
|
theApp.m_nFitToPagesWide = PageSetupData.nFitToPagesWide;
|
|
theApp.m_nFitToPagesTall = PageSetupData.nFitToPagesTall;
|
|
}
|
|
|
|
// PageSetupDlg failed
|
|
// if (CommDlgExtendedError() != 0)
|
|
// {
|
|
//
|
|
// nothing to handle this failure
|
|
//
|
|
// }
|
|
}
|
|
|