📄 viewprev.cpp
字号:
{
m_pToolBar->DestroyWindow();
m_pToolBar = NULL;
m_pPreviewInfo->m_nCurPage = m_nCurrentPage;
m_pOrigView->OnEndPrintPreview(m_pPreviewDC, m_pPreviewInfo,
CPoint(0, 0), this);
}
#define PREVIEW_MARGIN 8
#define PREVIEW_PAGEGAP 8
// Return is actually the fraction cx/cy. Simply using CSize for convenience
CSize CPreviewView::CalcScaleRatio(CSize screenSize, CSize actualSize)
{
// Test ratio based on vertical dimension to see if it is the one to use
int nNum = screenSize.cy;
int nDen = actualSize.cy;
// If scaled width too large, choose width as primary dimension
if (MulDiv(actualSize.cx, nNum, nDen) > screenSize.cx)
{
// wrong ratio--base on width
nNum = screenSize.cx;
nDen = actualSize.cx;
}
CSize ratio(nNum, nDen);
return ratio;
}
// Position Page...
// Generate a Screen MM_TEXT rectangle to enclose each page. Dimensions
// of the rectangle must be 1 pixel Above and Left of the top/left corner
// of the page and the rectangle width and height must be THREE pixels
// larger than page in order to provide the correct placement of the
// two pixel border.
//
// This routine is called once for each page with the preview DC set up for
// that page
void CPreviewView::PositionPage(UINT nPage)
{
CSize windowSize = CalcPageDisplaySize();
VERIFY(m_dcPrint.Escape(GETPHYSPAGESIZE, 0, NULL,
(LPVOID)&m_pPageInfo[nPage].sizeUnscaled));
CSize* pSize = &m_pPageInfo[nPage].sizeUnscaled;
// Convert page size to screen coordinates
pSize->cx = MulDiv(pSize->cx, afxData.cxPixelsPerInch, m_sizePrinterPPI.cx);
pSize->cy = MulDiv(pSize->cy, afxData.cyPixelsPerInch, m_sizePrinterPPI.cy);
m_pPageInfo[nPage].sizeZoomOutRatio = CalcScaleRatio(windowSize, *pSize);
SetScaledSize(nPage);
}
CSize CPreviewView::CalcPageDisplaySize()
// calculate the current page size
// set 'm_nSecondPageOffset' to start of second page
// return size of current page less margins
{
CSize windowSize, scrollSize;
GetTrueClientSize(windowSize, scrollSize);
// subtract out vertical scrollbar if zoomed out and page range is known
// and there is more than one page.
if (m_nZoomState == ZOOM_OUT && (m_pPreviewInfo->GetMaxPage() != 0xffff) &&
(m_pPreviewInfo->GetMaxPage() - m_pPreviewInfo->GetMinPage() != 0))
windowSize.cx -= scrollSize.cx;
m_nSecondPageOffset = (windowSize.cx - PREVIEW_MARGIN) / 2;
windowSize.cx = (m_nPages == 2) ? (windowSize.cx - 3*PREVIEW_MARGIN) / 2 :
windowSize.cx - 2*PREVIEW_MARGIN;
windowSize.cy -= 2*PREVIEW_MARGIN;
return windowSize;
}
void CPreviewView::SetScaledSize(UINT nPage)
{
CSize* pSize = &m_pPageInfo[nPage].sizeUnscaled;
CSize* pRatio = &m_pPageInfo[nPage].sizeScaleRatio;
CSize* pZoomOutRatio = &m_pPageInfo[nPage].sizeZoomOutRatio;
CSize windowSize = CalcPageDisplaySize();
BOOL bPaperLarger = pZoomOutRatio->cx < pZoomOutRatio->cy;
// whether the paper is larger than the screen, or vice versa
switch (m_nZoomState)
{
case ZOOM_OUT:
*pRatio = *pZoomOutRatio;
break;
case ZOOM_MIDDLE:
// the middle zoom state is a ratio between cx/cy and
// 1/1 (or cy/cy). It is, therefore:
//
// (cx + cy)/2
// -----------
// cy
//
// if the paper is larger than the screen, or
//
// (3*cx - cy)/2
// -------------
// cy
//
// if the paper is smaller than the screen.
if (bPaperLarger)
{
pRatio->cy = pZoomOutRatio->cy;
pRatio->cx = (pZoomOutRatio->cx + pRatio->cy) / 2;
}
else
{
pRatio->cy = pZoomOutRatio->cy;
pRatio->cx = (3*pZoomOutRatio->cx - pRatio->cy) / 2;
}
break;
case ZOOM_IN:
if (bPaperLarger)
pRatio->cx = pRatio->cy = 1;
else
{
// if the paper is smaller than the screen space we're displaying
// it in, then using a ratio of 1/1 will result in a smaller image
// on the screen, not a larger one. To get a larger image in this
// case we double the zoom out ratio.
pRatio->cy = pZoomOutRatio->cy;
pRatio->cx = 2*pZoomOutRatio->cx - pZoomOutRatio->cy;
}
break;
default:
ASSERT(FALSE);
}
// Convert to scaled size
CSize scaledSize;
scaledSize.cx = MulDiv(pSize->cx, pRatio->cx, pRatio->cy);
scaledSize.cy = MulDiv(pSize->cy, pRatio->cx, pRatio->cy);
CRect* pRect = &m_pPageInfo[nPage].rectScreen;
pRect->SetRect(PREVIEW_MARGIN, PREVIEW_MARGIN,
scaledSize.cx + PREVIEW_MARGIN + 3,
scaledSize.cy + PREVIEW_MARGIN + 3);
if (m_nZoomState == ZOOM_OUT)
{
pRect->OffsetRect((windowSize.cx - pRect->Size().cx) / 2 - 1,
(windowSize.cy - pRect->Size().cy) / 2 - 1);
if (nPage == 1)
pRect->OffsetRect(m_nSecondPageOffset, 0);
}
else
{
// set up scroll size
SetScrollSizes(MM_TEXT, pRect->Size() +
CSize(PREVIEW_MARGIN * 2, PREVIEW_MARGIN * 2), windowSize);
}
}
// Only use the PrepareDC from CScrollView if we are zoomed in
void CPreviewView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
{
ASSERT_VALID(pDC);
if (m_nZoomState == ZOOM_OUT)
CView::OnPrepareDC(pDC, pInfo);
else if (m_pPageInfo[0].sizeScaleRatio.cx != 0)
CScrollView::OnPrepareDC(pDC, pInfo);
}
BOOL CPreviewView::OnEraseBkgnd(CDC* pDC)
{
ASSERT_VALID(pDC);
// Fill background with APPWORKSPACE
CBrush backBrush(GetSysColor(COLOR_APPWORKSPACE));
CBrush* pOldBrush = pDC->SelectObject(&backBrush);
CRect rect;
pDC->GetClipBox(&rect); // Erase the area needed
pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATCOPY);
pDC->SelectObject(pOldBrush);
return TRUE;
}
void CPreviewView::OnDraw(CDC* pDC)
{
ASSERT_VALID(pDC);
// don't do anything if not fully initialized
if (m_pPrintView == NULL || m_dcPrint.m_hDC == NULL)
return;
CPoint ViewportOrg = pDC->GetViewportOrg();
CPen rectPen;
rectPen.CreatePen(PS_SOLID, 2, GetSysColor(COLOR_WINDOWFRAME));
CPen shadowPen;
shadowPen.CreatePen(PS_SOLID, 3, GetSysColor(COLOR_BTNSHADOW));
m_pPreviewInfo->m_bContinuePrinting = TRUE; // do this once each paint
for (UINT nPage = 0; nPage < m_nPages; nPage++)
{
int nSavedState = m_dcPrint.SaveDC(); // Save pristine state of DC
// Use paint DC for print preview output
m_pPreviewDC->SetOutputDC(pDC->GetSafeHdc());
m_pPreviewInfo->m_nCurPage = m_nCurrentPage + nPage;
// Only call PrepareDC if within page range, otherwise use default
// rect to draw page rectangle
if (m_nCurrentPage + nPage <= m_pPreviewInfo->GetMaxPage())
m_pPrintView->OnPrepareDC(m_pPreviewDC, m_pPreviewInfo);
// Set up drawing rect to entire page (in logical coordinates)
m_pPreviewInfo->m_rectDraw.SetRect(0, 0,
m_pPreviewDC->GetDeviceCaps(HORZRES),
m_pPreviewDC->GetDeviceCaps(VERTRES));
m_pPreviewDC->DPtoLP(&m_pPreviewInfo->m_rectDraw);
// Draw empty page on screen
pDC->SaveDC(); // save the output dc state
CSize* pRatio = &m_pPageInfo[nPage].sizeScaleRatio;
CRect* pRect = &m_pPageInfo[nPage].rectScreen;
if (pRatio->cx == 0)
{ // page position has not been determined
PositionPage(nPage); // compute page position
if (m_nZoomState != ZOOM_OUT)
ViewportOrg = -GetDeviceScrollPosition();
}
pDC->SetMapMode(MM_TEXT); // Page Rectangle is in screen device coords
pDC->SetViewportOrg(ViewportOrg);
pDC->SetWindowOrg(0, 0);
pDC->SelectStockObject(HOLLOW_BRUSH);
pDC->SelectObject(&rectPen);
pDC->Rectangle(pRect);
pDC->SelectObject(&shadowPen);
pDC->MoveTo(pRect->right + 1, pRect->top + 3);
pDC->LineTo(pRect->right + 1, pRect->bottom + 1);
pDC->MoveTo(pRect->left + 3, pRect->bottom + 1);
pDC->LineTo(pRect->right + 1, pRect->bottom + 1);
// erase background to white (most paper is white)
CRect rectFill = *pRect;
rectFill.left += 1;
rectFill.top += 1;
rectFill.right -= 2;
rectFill.bottom -= 2;
::FillRect(pDC->m_hDC, rectFill, (HBRUSH)GetStockObject(WHITE_BRUSH));
pDC->RestoreDC(-1); // restore to synchronized state
if (!m_pPreviewInfo->m_bContinuePrinting ||
m_nCurrentPage + nPage > m_pPreviewInfo->GetMaxPage())
{
m_pPreviewDC->ReleaseOutputDC();
m_dcPrint.RestoreDC(nSavedState); // restore to untouched state
// if the first page is not displayable, back up one page
// but never go below 1
if (nPage == 0 && m_nCurrentPage > 1)
SetCurrentPage(m_nCurrentPage - 1, TRUE);
break;
}
// Display page number
OnDisplayPageNumber(m_nCurrentPage, nPage + 1);
// Set scale ratio for this page
m_pPreviewDC->SetScaleRatio(pRatio->cx, pRatio->cy);
CSize PrintOffset;
VERIFY(m_pPreviewDC->Escape(GETPRINTINGOFFSET, 0, NULL, (LPVOID)&PrintOffset));
m_pPreviewDC->PrinterDPtoScreenDP((LPPOINT)&PrintOffset);
PrintOffset += (CSize)pRect->TopLeft();
PrintOffset += CSize(1, 1);
PrintOffset += (CSize)ViewportOrg; // For Scrolling
m_pPreviewDC->SetTopLeftOffset(PrintOffset);
m_pPreviewDC->ClipToPage();
m_pPrintView->OnPrint(m_pPreviewDC, m_pPreviewInfo);
m_pPreviewDC->ReleaseOutputDC();
m_dcPrint.RestoreDC(nSavedState); // restore to untouched state
}
rectPen.DeleteObject();
shadowPen.DeleteObject();
}
void CPreviewView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
if (m_nZoomState != ZOOM_OUT)
CScrollView::OnHScroll(nSBCode, nPos, pScrollBar);
}
void CPreviewView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
if (m_nZoomState != ZOOM_OUT)
{
CScrollView::OnVScroll(nSBCode, nPos, pScrollBar);
return;
}
switch (nSBCode)
{
case SB_BOTTOM:
SetCurrentPage(m_pPreviewInfo->GetMaxPage(), TRUE);
break;
case SB_TOP:
SetCurrentPage(m_pPreviewInfo->GetMinPage(), TRUE);
break;
case SB_PAGEDOWN:
SetCurrentPage(m_nCurrentPage +
(m_pPreviewInfo->GetMaxPage() - m_pPreviewInfo->GetMinPage() + 9) / 10, TRUE);
break;
case SB_PAGEUP:
SetCurrentPage(m_nCurrentPage -
(m_pPreviewInfo->GetMaxPage() - m_pPreviewInfo->GetMinPage() + 9) / 10, TRUE);
break;
case SB_LINEDOWN:
SetCurrentPage(m_nCurrentPage + 1, TRUE);
break;
case SB_LINEUP:
SetCurrentPage(m_nCurrentPage - 1, TRUE);
break;
case SB_THUMBPOSITION:
SetCurrentPage(nPos, TRUE);
break;
}
}
void CPreviewView::OnNumPageChange()
{
ASSERT(m_nPages == 1 || m_nPages == 2);
m_nPages = 3 - m_nPages; // Toggle between 1 and 2
AfxGetApp()->m_nNumPreviewPages = m_nPages;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -