// MultiPagePreview.cpp
#include "stdafx.h"
#include "MultiPagePreview.h"
#include "resource.h"
#include "MyDialogBar.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
extern HINSTANCE hDLLInstance;
IMPLEMENT_DYNCREATE(CMultiPagePreviewView, CPreviewView)
CMultiPagePreviewView::CMultiPagePreviewView()
{
// replace the PAGE_INFO array with our one to make sure its large enough
m_pPageInfo = m_pageInfoArray2;
m_Across = 2; // default number of pages across the screen
m_Down = 1; // default number of pages down the screen
m_nPages = 2;
// NOTE : If you change m_nPages outside of this code you will also need to modify
// the m_Across and m_Down member vars to get the pages to show correctly
m_pMaps = NULL;
m_MapCount = 0;
CPlugInApp *pApp = static_cast<CPlugInApp*>(AfxGetApp());
// get our pointers to any plug in maps
m_pMaps = pApp->GetMessageMaps(this, m_MapCount);
}
CMultiPagePreviewView::~CMultiPagePreviewView()
{
// release message map pointers
for (int i = 0; i < m_MapCount; ++i)
{
delete m_pMaps[i];
m_pMaps[i] = NULL;
}
delete []m_pMaps;
m_pMaps = NULL;
m_state.SetDestroyed();
}
BEGIN_MESSAGE_MAP(CMultiPagePreviewView, CPreviewView)
//{{AFX_MSG_MAP(CMultiPagePreviewView)
ON_COMMAND(AFX_ID_PREVIEW_NUMPAGE, OnNumPageChange)
ON_COMMAND(AFX_ID_PREVIEW_ZOOMIN, OnZoomIn)
ON_COMMAND(AFX_ID_PREVIEW_ZOOMOUT, OnZoomOut)
ON_UPDATE_COMMAND_UI(AFX_ID_PREVIEW_NUMPAGE, OnUpdateNumPageChange)
ON_UPDATE_COMMAND_UI(AFX_ID_PREVIEW_ZOOMIN, OnUpdateZoomIn)
ON_UPDATE_COMMAND_UI(AFX_ID_PREVIEW_ZOOMOUT, OnUpdateZoomOut)
ON_WM_CREATE()
ON_WM_LBUTTONDOWN()
ON_WM_SETCURSOR()
ON_WM_MOUSEWHEEL()
//}}AFX_MSG_MAP
ON_WM_VSCROLL()
ON_COMMAND(ID_PREVIEW_PAGES, OnPreviewPages)
ON_COMMAND(IDC_LANDSCAPE, OnLandscape)
ON_NOTIFY_EX(TTN_NEEDTEXT, 0, OnToolTipNotify)
ON_COMMAND(IDC_PRINT_SETUP, OnPrintSetup)
END_MESSAGE_MAP()
BOOL CMultiPagePreviewView::PreCreateWindow(CREATESTRUCT& cs)
{
if (cs.lpszClass == NULL)
{
cs.lpszClass = AfxRegisterWndClass(CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW|CS_BYTEALIGNCLIENT);
}
return CView::PreCreateWindow(cs);
}
#ifdef _DEBUG
void CMultiPagePreviewView::AssertValid() const
{
// Bug nearby Article ID: Q192853
// CPreviewView::AssertValid();
}
void CMultiPagePreviewView::Dump(CDumpContext& dc) const
{
TRACE("Dump\n");
CPreviewView::Dump(dc);
}
#endif //_DEBUG
BOOL CMultiPagePreviewView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
if (nHitTest != HTCLIENT)
{
return CScrollView::OnSetCursor(pWnd, nHitTest, message);
}
CPoint point;
::GetCursorPos(&point);
ScreenToClient(&point); // client coordinates of mouse position
UINT nPage;
if (m_nZoomState != ZOOM_IN_400 &&
FindPageRect(point, nPage))
{ // On a page and not zoomed all the way in
if (m_hMagnifyCursor == NULL)
{
HINSTANCE hInst = AfxFindResourceHandle(MAKEINTRESOURCE(AFX_IDC_MAGNIFY), RT_GROUP_CURSOR);
m_hMagnifyCursor = ::LoadCursor(hInst,MAKEINTRESOURCE(AFX_IDC_MAGNIFY));
}
::SetCursor(m_hMagnifyCursor);
}
else
{
::SetCursor(::LoadCursor(NULL, IDC_ARROW));
}
return 0;
}
void CMultiPagePreviewView::OnLButtonDown(UINT, CPoint point)
{
UINT nPage;
if (!FindPageRect(point, nPage))
{
return; // Didn't click on a page
}
// Set new zoom state
SetZoomState((m_nZoomState == ZOOM_IN_400) ? ZOOM_OUT : m_nZoomState + 1, nPage, point);
if (m_nZoomState == ZOOM_OUT)
{
// make sure the current page does not cause blank pages to be shown
if (m_nCurrentPage >= m_pPreviewInfo->GetMaxPage() - m_nPages)
{
m_nCurrentPage = m_pPreviewInfo->GetMaxPage() - m_nPages + 1;
}
if (m_nCurrentPage < 0)
{
m_nCurrentPage = 0;
}
}
}
void CMultiPagePreviewView::SetZoomState(UINT nNewState, UINT nPage, CPoint point)
{
if (m_nZoomState != nNewState)
{
m_nZoomState = nNewState;
DoZoom(nPage, point);
}
}
// Actual zoom code.
void CMultiPagePreviewView::DoZoom(UINT nPage, CPoint point)
{
if (m_nZoomState == ZOOM_OUT)
{
// taking over scroll bars
m_nPages = m_nZoomOutPages;
ShowScrollBar(SB_HORZ, FALSE); // hide the horizontal bar
BOOL bShowBar = m_pPreviewInfo->GetMaxPage() < 0x8000 &&
m_pPreviewInfo->GetMaxPage() -
m_pPreviewInfo->GetMinPage() <= 32767U;
ShowScrollBar(SB_VERT, bShowBar); // Show the vertical bar
if (bShowBar)
{
SCROLLINFO info;
info.fMask = SIF_PAGE | SIF_RANGE;
info.nMin = m_pPreviewInfo->GetMinPage();
info.nMax = m_pPreviewInfo->GetMaxPage();
info.nPage = 1;
if (!SetScrollInfo(SB_VERT, &info, FALSE))
{
SetScrollRange(SB_VERT, info.nMin, info.nMax, FALSE);
}
}
SetCurrentPage(m_nCurrentPage, TRUE);
SetupScrollbar();
}
else
{
m_nPages = 1; // only one page in zoomed states
m_pPageInfo[0].sizeZoomOutRatio = m_pPageInfo[nPage].sizeZoomOutRatio;
m_pPageInfo[0].sizeUnscaled = m_pPageInfo[nPage].sizeUnscaled;
// Sets the printer page
SetCurrentPage(m_nCurrentPage + nPage, FALSE);
SetScaledSize(0);
CSize* pRatio = &m_pPageInfo[nPage].sizeScaleRatio;
// convert Hit Point from screen 1:1
point.x = MulDiv(point.x, pRatio->cx, pRatio->cy);
point.y = MulDiv(point.y, pRatio->cx, pRatio->cy);
// Adjust point for page position
point += (CSize)m_pPageInfo[0].rectScreen.TopLeft();
// Scroll to center
CenterOnPoint(point);
}
}
void CMultiPagePreviewView::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);
}
#define PREVIEW_MARGIN 8
#define PREVIEW_PAGEGAP 8
void CMultiPagePreviewView::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;
case ZOOM_IN_150:
pRatio->cx = 15;
pRatio->cy = 10;
break;
case ZOOM_IN_200:
pRatio->cx = 25;
pRatio->cy = 10;
break;
case ZOOM_IN_400:
pRatio->cx = 4;
pRatio->cy = 1;
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);
// we need to offste the page multiple times
int local = nPage % m_Across;
while (local-- >= 1)
{
pRect->OffsetRect(m_PageOffset.x, 0);
}
local = nPage / m_Across;
while (local-- > 0)
{
pRect->OffsetRect(0, m_PageOffset.y);
}
}
else
{
// set up scroll size
SetScrollSizes(MM_TEXT, pRect->Size() +
CSize(PREVIEW_MARGIN * 2, PREVIEW_MARGIN * 2), windowSize);
}
}
/////////////////////////////////////////////////////////////////////////////
// CMultiPagePreviewView
void CMultiPagePreviewView::OnUpdateNumPageChange(CCmdUI* pCmdUI)
{
// button has been removed from toolbar
//UINT nPages = m_nZoomState == ZOOM_OUT ? m_nPages : m_nZoomOutPages;
//pCmdUI->Enable(m_nZoomState == ZOOM_OUT && m_nMaxPages != 1 && (m_pPreviewInfo->GetMaxPage() > 1 || m_nPages > 1));
// CPreviewView::OnUpdateNumPageChange(pCmdUI);
}
void CMultiPagePreviewView::OnUpdateZoomIn(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_nZoomState != ZOOM_IN_400);
}
void CMultiPagePreviewView::OnUpdateZoomOut(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_nZoomState != ZOOM_OUT);
}
void CMultiPagePreviewView::OnNumPageChange()
{
// doesn't do anything any more
// button has been removed from toolbar
}
void CMultiPagePreviewView::OnZoomIn()
{
if (m_nZoomState != ZOOM_IN_400)
{
SetZoomState(m_nZoomState + 1, 0, CPoint(0, 0));
}
}
void CMultiPagePreviewView::OnZoomOut()
{
if (m_nZoomState != ZOOM_OUT)
{
SetZoomState(m_nZoomState - 1, 0, CPoint(0, 0));
}
if (m_nZoomState == ZOOM_OUT)
{
// make sure the current page does not cause blank pages to be shown
if (m_nCurrentPage >= m_pPreviewInfo->GetMaxPage() - m_nPages)
m_nCurrentPage = m_pPreviewInfo->GetMaxPage() - m_nPages + 1;
if (m_nCurrentPage < 0)
m_nCurrentPage = 0;
}
}
int CMultiPagePreviewView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CPreviewView::OnCreate(lpCreateStruct) == -1)
{
return -1;
}
CWinApp *pApp = AfxGetApp();
CPlugInApp *pOurApp = static_cast<CPlugInApp*>(pApp);
ASSERT(pOurApp);
// Switch to our CDialogBar derived class to get the mouse wheel working
m_pToolBar->DestroyWindow();
m_pToolBar = NULL;
m_pToolBar = new CMyDialogBar;
CFrameWnd* pParent = STATIC_DOWNCAST(CFrameWnd, AfxGetMainWnd());
if (!m_pToolBar->Create(pParent, MAKEINTRESOURCE(IDD_PREVIEW), CBRS_TOP, AFX_IDW_PREVIEW_BAR))
{
TRACE0("Error: Preview could not create toolbar dialog.\n");
delete m_pToolBar; // not autodestruct yet
m_pToolBar = NULL;
return FALSE;
}
CMyDialogBar *pMyDialogBar = static_cast<CMyDialogBar*>(m_pToolBar);
ASSERT(pMyDialogBar);
pMyDialogBar->SetViewPointer(this); // so we can get mouse wheel messages
m_pToolBar->m_bAutoDelete = TRUE; // automatic cleanup
m_pToolBar->EnableToolTips( TRUE );
// make the buttons on the dialog bar bitmap buttons
m_print.AutoLoad(AFX_ID_PREVIEW_PRINT, m_pToolBar, IDB_PREV_PRINT);
m_printSetup.AutoLoad(IDC_PRINT_SETUP, m_pToolBar, IDB_PREV_PRINT_SETUP);
m_next.AutoLoad(AFX_ID_PREVIEW_NEXT, m_pToolBar, IDB_PREV_NEXT);
m_previous.AutoLoad(AFX_ID_PREVIEW_PREV, m_pToolBar, IDB_PREV_PREVIOUS);
m_zoomIn.AutoLoad(AFX_ID_PREVIEW_ZOOMIN, m_pToolBar, IDB_PREV_ZOOMIN);
m_zoomOut.AutoLoad(AFX_ID_PREVIEW_ZOOMOUT, m_pToolBar, IDB_PREV_ZOOMOUT);
m_pages.AutoLoad(ID_PREVIEW_PAGES, m_pToolBar, IDB_PAGES );
if (GetPrintOrientation() == DMORIENT_LANDSCAPE)
{
// check the landscape button
CWnd *pWnd = m_pToolBar->GetDlgItem(IDC_LANDSCAPE);
ASSERT(pWnd); // the item should exist in the toolbar. If this assert check your resources
CButton *pButton = static_cast<CButton*>(pWnd); // get a pointer to the button
ASSERT(pButton); // not a button object? If it asserts, then wrong control type in toolbar resource
pButton->SetCheck(1); // set the check mark
}
return 0;
}
CSize CMultiPagePreviewView::CalcPageDisplaySize()
// calculate the current page size
// MFC used to set 'm_nSecondPageOffset' to start of second page
// as we have multiple pages we use m_PageOffset which holds the
// diferences across and down the pages
// return size of current page less margins
{
// just checking...
ASSERT(m_Down >= 1);
ASSERT(m_Across >= 1);
ASSERT(m_nPages >= 1);
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_PageOffset.y = 0;
if (m_Down > 1)
{
// we need to make room for more pages under the first
windowSize.cy = (windowSize.cy - (PREVIEW_MARGIN * (m_Down - 1))) / m_Down;
m_PageOffset.y = windowSize.cy + PREVIEW_MARGIN;
}
else
{
// its a single page down, it uses all the area previouslyy calculated
}
if (m_Across <= 2)
{
m_PageOffset.x = (windowSize.cx - PREVIEW_MARGIN) / 2;
}
else
{
m_PageOffset.x = (windowSize.cx - PREVIEW_MARGIN) / m_Across;
}
// make sure all pages across fit in the screen area
windowSize.cx = (windowSize.cx - ((m_Across + 1) * PREVIEW_MARGIN)) / m_Across;
//windowSize.cx = (m_nPages == 2) ? (windowSize.cx - 3*PREVIEW_MARGIN) / 2 :
// windowSize.cx - 2*PREVIEW_MARGIN;
windowSize.cy -= 2*PREVIEW_MARGIN;
return windowSize;
}
void CMultiPagePreviewView::OnPreviewPages()
{
CPoint point;
CRect rect;
CWnd *pWnd = m_pToolBar->GetDlgItem(ID_PREVIEW_PAGES);
if (pWnd != NULL)
{
// place the menu just below the button
pWnd->GetWindowRect(&rect);
point = CPoint(rect.left, rect.bottom);
}
else
{
::GetCursorPos(&point); // failed to get window, use the mouse position
}
CMenu menu;
CMenu *pSub;
// popup a menu to get the number of pages to display
VERIFY(menu.LoadMenu(IDR_PREVIEW_PAGES));
pSub = menu.GetSubMenu(0);
// NOTE : If you need to enable or disable the menu items in this list based on the number of
// pages in your printout, you can either do it here before the menu is diaplyed, or write a handler
// for the WM_INITMENUPOPUP message and configure the enabled/disabled state at that point.
int command = pSub->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RETURNCMD, point.x, point.y, this);
switch (command)
{
case ID_PAGES_1PAGE :
m_Across = 1;
m_Down = 1;
m_nPages = 1;
break;
case ID_PAGES_2PAGES :
m_Across = 2;
m_Down = 1;
m_nPages = 2;
break;
case ID_PAGES_3PAGES :
m_Across = 3;
m_Down = 1;
m_nPages = 3;
break;
case ID_PAGES_4PAGES :
m_Across = 2;
m_Down = 2;
m_nPages = 4;
break;
case ID_PAGES_6PAGES :
m_Across = 3;
m_Down = 2;
m_nPages = 6;
break;
case ID_PAGES_9PAGES :
m_Across = 3;
m_Down = 3;
m_nPages = 9;
break;
default :
return;
}
AfxGetApp()->m_nNumPreviewPages = m_nPages;
m_nZoomOutPages = m_nPages;
m_nMaxPages = m_nPages;
if (m_nZoomState == ZOOM_OUT)
{
// make sure the current page does not cause blank pages to be shown
if (m_nCurrentPage >= m_pPreviewInfo->GetMaxPage() - m_nPages)
{
m_nCurrentPage = m_pPreviewInfo->GetMaxPage() - m_nPages + 1;
}
if (m_nCurrentPage < 0)
{
m_nCurrentPage = 0;
}
}
// Just do this to set the status correctly and invalidate
SetCurrentPage(m_nCurrentPage, TRUE);
SetupScrollbar();
}
void CMultiPagePreviewView::SetupScrollbar()
{
// this procedure makes sure that the scroll bar does not allow us to scroll the window
// such that we end up displaying blank pages
// correctly range the scroll bars
if (m_pPreviewInfo->GetMaxPage() < 0x8000 && m_pPreviewInfo->GetMaxPage() - m_pPreviewInfo->GetMinPage() <= 32767U)
{
SCROLLINFO info;
info.fMask = SIF_PAGE|SIF_RANGE;
info.nMin = m_pPreviewInfo->GetMinPage();
info.nMax = m_pPreviewInfo->GetMaxPage() - (m_nPages - 1);
info.nPage = 1;
if (!SetScrollInfo(SB_VERT, &info, FALSE))
{
SetScrollRange(SB_VERT, info.nMin, info.nMax, FALSE);
}
}
else
{
ShowScrollBar(SB_VERT, FALSE); // if no range specified, or too
}
}
void CMultiPagePreviewView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
if (m_nZoomState != ZOOM_OUT)
{
CScrollView::OnVScroll(nSBCode, nPos, pScrollBar);
return;
}
SetupScrollbar();
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:
if (m_nCurrentPage <= m_pPreviewInfo->GetMaxPage() - m_nPages)
SetCurrentPage(m_nCurrentPage + 1, TRUE);
break;
case SB_LINEUP:
if (m_nCurrentPage > 0)
SetCurrentPage(m_nCurrentPage - 1, TRUE);
break;
case SB_THUMBPOSITION:
SetCurrentPage(nPos, TRUE);
break;
}
}
void CMultiPagePreviewView::OnLandscape()
{
// switch the preview DC between lanscape and portrait mode.
// we also need to setup the app printer defaults to switch between portrait and
// landscape, so any print action will use the correct settings
// we need to delete the current printer DC and setup a new one after changing the print mode bewteen landscape / portrait
CWnd *pWnd = m_pToolBar->GetDlgItem(IDC_LANDSCAPE);
ASSERT(pWnd); // the item should exist in the toolbar. If this assert check your resources
CButton *pButton = static_cast<CButton*>(pWnd); // get a pointer to the button
ASSERT(pButton); // not a button object? If it asserts, then wrong control type in toolbar resource
int state = pButton->GetCheck(); // portrait or landscape mode?
int old_page = m_nCurrentPage; // save page number as it gets reset
// call the OnEndPrinting as required
// m_pPrintView->OnEndPrinting(m_pPreviewDC, m_pPreviewInfo);
// get the current CPrintInfo object
m_dcPrint.Detach(); // print DC is deleted by CPrintInfo destructor
delete m_pPreviewInfo;
m_pPreviewInfo = NULL;
delete m_pPreviewDC;
m_pPreviewDC = NULL;
// switch the print mode
SetPrintOrientation(state ? DMORIENT_LANDSCAPE : DMORIENT_PORTRAIT);
SetPrintView(m_pPrintView); // sets up new DC's and print info structure
m_nCurrentPage = old_page; // restore as gets reset
SetupScrollbar();
}
// use the mouse wheel to scroll either through the pages
// or scroll through the zoomed in page.
BOOL CMultiPagePreviewView::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
CPoint position;
if (m_nZoomState != ZOOM_OUT)
{
position = GetScrollPosition();
// scrolling up / down
position -= CPoint(0, zDelta);
CPreviewView::ScrollToPosition(position);
}
else
{
// scroll selected pages
if (zDelta > 0 && m_nCurrentPage > 1)
{
OnPrevPage();
}
else if (zDelta < 0 && m_nCurrentPage < m_pPreviewInfo->GetMaxPage() - (m_nPages - 1))
{
OnNextPage();
}
}
return TRUE;
}
BOOL CMultiPagePreviewView::OnToolTipNotify(UINT, NMHDR *pNMHDR, LRESULT*)
{
TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pNMHDR;
if (pTTT->uFlags & TTF_IDISHWND)
{
// idFrom is actually the HWND of the tool
UINT nID = ::GetDlgCtrlID((HWND)pNMHDR->idFrom);
pTTT->lpszText = NULL;
switch (nID)
{
case AFX_ID_PREVIEW_PRINT :
pTTT->lpszText = "Print the report";
break;
case AFX_ID_PREVIEW_NEXT :
pTTT->lpszText = "Move to next page";
break;
case AFX_ID_PREVIEW_PREV :
pTTT->lpszText = "Move to previous page";
break;
case ID_PREVIEW_PAGES :
pTTT->lpszText = "Select the number of pages to preview at a time";
break;
case AFX_ID_PREVIEW_ZOOMIN :
pTTT->lpszText = "Zoom in";
break;
case AFX_ID_PREVIEW_ZOOMOUT :
pTTT->lpszText = "Zoom out";
break;
case AFX_ID_PREVIEW_CLOSE :
pTTT->lpszText = "Close print preview mode";
break;
case IDC_LANDSCAPE :
pTTT->lpszText = "Switch between portrait and landscape print orientation";
break;
case IDC_PRINT_SETUP:
pTTT->lpszText = "Print setup";
break;
default :
pTTT->lpszText = "Unrecognised control ID";
break;
}
return TRUE;
}
return FALSE;
}
BOOL CMultiPagePreviewView::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)
{
// check to see whether any of the plug-in DLL's
// want to intercept this message and process it before the application class
CPlugInApp *pApp = static_cast<CPlugInApp*>(AfxGetApp());
CPIState stateCopy(m_state);
ASSERT(pApp);
BOOL ret_pre = FALSE;
BOOL ret_app = FALSE;
BOOL ret_post = FALSE;
m_bSuppressThisMessage = false;
// allow DLL's to process this message before the exe
ret_pre = pApp->ProcessCommandMessageMaps(stateCopy, true, &m_bSuppressThisMessage, m_pMaps, m_MapCount, nID, nCode, pExtra, pHandlerInfo);
if (!m_bSuppressThisMessage)
{
// allow the exe to process the message is it hasn't been suppressed by a DLL
ret_app = CPreviewView::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}
// allow DLL to process the message after the exe
// note that DLLs get to do this whether the message has been supressed or not
if (!stateCopy.IsDestroyed())
{
ret_post = pApp->ProcessCommandMessageMaps(stateCopy, false, &m_bSuppressThisMessage, m_pMaps, m_MapCount, nID, nCode, pExtra, pHandlerInfo);
}
if (ret_pre || ret_app || ret_post)
return TRUE;
return FALSE;
}
BOOL CMultiPagePreviewView::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
LRESULT lResult;
// special case for commands
if (message == WM_COMMAND)
{
if (OnCommand(wParam, lParam))
{
lResult = 1;
if (pResult != NULL)
*pResult = lResult;
return TRUE;
}
return FALSE;
}
// special case for notifies
if (message == WM_NOTIFY)
{
NMHDR* pNMHDR = (NMHDR*)lParam;
if (pNMHDR->hwndFrom != NULL && OnNotify(wParam, lParam, &lResult))
{
if (pResult != NULL)
*pResult = lResult;
return TRUE;
}
return FALSE;
}
// check to see whether any of the plug-in DLL's
// want to intercept this message and process it before the application class
CPlugInApp *pApp = static_cast<CPlugInApp*>(AfxGetApp());
ASSERT(pApp);
CPIState stateCopy(m_state);
BOOL ret_pre = FALSE;
BOOL ret_app = FALSE;
BOOL ret_post = FALSE;
m_bSuppressThisMessage = false;
// allow DLL's to process this message before the exe
ret_pre = pApp->ProcessWindowMessageMaps(stateCopy, true, &m_bSuppressThisMessage, m_pMaps, m_MapCount, message, wParam, lParam, pResult);
if (!m_bSuppressThisMessage)
{
// allow the exe to process the message is it hasn't been suppressed by a DLL
ret_app = CPreviewView::OnWndMsg(message, wParam, lParam, pResult);
}
if (!stateCopy.IsDestroyed())
{
// allow DLL to process the message after the exe
// note that DLLs get to do this whether the message has been supressed or not
ret_pre = pApp->ProcessWindowMessageMaps(stateCopy, false, &m_bSuppressThisMessage, m_pMaps, m_MapCount, message, wParam, lParam, pResult);
}
if (ret_pre || ret_app || ret_post)
return TRUE;
return FALSE;
}
int CMultiPagePreviewView::GetPrintOrientation() const
{
PRINTDLG pd;
int orientation;
pd.lStructSize = (DWORD)sizeof(PRINTDLG);
BOOL bRet = AfxGetApp()->GetPrinterDeviceDefaults(&pd);
if (bRet)
{
// protect memory handle with ::GlobalLock and ::GlobalUnlock
DEVMODE *pDevMode = (DEVMODE*)::GlobalLock(pd.hDevMode);
orientation = pDevMode->dmOrientation;
::GlobalUnlock(pd.hDevMode);
}
return orientation;
}
bool CMultiPagePreviewView::SetPrintOrientation(int mode) const
{
PRINTDLG pd;
pd.lStructSize = (DWORD)sizeof(PRINTDLG);
BOOL bRet = AfxGetApp()->GetPrinterDeviceDefaults(&pd);
if (bRet)
{
switch (mode)
{
case DMORIENT_PORTRAIT :
{
// portrait mode
LPDEVMODE pDevMode = (LPDEVMODE)::GlobalLock(pd.hDevMode) ;
// set orientation to portrait
pDevMode->dmOrientation = DMORIENT_PORTRAIT ;
::GlobalUnlock(pd.hDevMode) ;
}
break ;
case DMORIENT_LANDSCAPE :
{
// landscape mode
LPDEVMODE pDevMode = (LPDEVMODE)::GlobalLock(pd.hDevMode) ;
// set orientation to landscape
pDevMode->dmOrientation = DMORIENT_LANDSCAPE ;
::GlobalUnlock(pd.hDevMode) ;
}
break ;
default :
ASSERT(FALSE) ; // invalid parameter
return false ;
}
return true ;
}
return false;
}
void CMultiPagePreviewView::OnPrintSetup()
{
CWinApp *pApp = AfxGetApp();
CPrintDialog pd(TRUE);
if (pApp->DoPrintDialog(&pd))
{
// call the OnEndPrinting as required
// m_pPrintView->OnEndPrinting(m_pPreviewDC, m_pPreviewInfo);
CPrintInfo *pInfo = m_pPreviewInfo;
m_pPreviewInfo = NULL;
m_dcPrint.Detach(); // print DC is deleted by CPrintInfo destructor
delete pInfo;
SetPrintView(m_pPrintView);
CWnd *pWnd = m_pToolBar->GetDlgItem(IDC_LANDSCAPE);
ASSERT(pWnd); // the item should exist in the toolbar. If this assert check your resources
CButton *pButton = static_cast<CButton*>(pWnd); // get a pointer to the button
ASSERT(pButton); // not a button object? If it asserts, then wrong control type in toolbar resource
if (GetPrintOrientation() == DMORIENT_LANDSCAPE)
{
// check the landscape button
pButton->SetCheck(1); // set the check mark
}
else
{
pButton->SetCheck(0); // clear the check mark
}
}
}