From: boca4711 <boc...@us...> - 2004-11-21 15:33:22
|
Update of /cvsroot/anyedit/AnyEditToolkit/GuiLib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv22147/GuiLib Added Files: MultiPagePreview.cpp MultiPagePreview.h Log Message: Class for mulitpage print preview --- NEW FILE: MultiPagePreview.cpp --- // 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 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 } CMultiPagePreviewView::~CMultiPagePreviewView() { } 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(_T("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; } // 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 && !(nFlags & MK_CONTROL)) { 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 = _T("Print the report"); break; case AFX_ID_PREVIEW_NEXT : pTTT->lpszText = _T("Move to next page"); break; case AFX_ID_PREVIEW_PREV : pTTT->lpszText = _T("Move to previous page"); break; case ID_PREVIEW_PAGES : pTTT->lpszText = _T("Select the number of pages to preview at a time"); break; case AFX_ID_PREVIEW_ZOOMIN : pTTT->lpszText = _T("Zoom in"); break; case AFX_ID_PREVIEW_ZOOMOUT : pTTT->lpszText = _T("Zoom out"); break; case AFX_ID_PREVIEW_CLOSE : pTTT->lpszText = _T("Close print preview mode"); break; case IDC_LANDSCAPE : pTTT->lpszText = _T("Switch between portrait and landscape print orientation"); break; case IDC_PRINT_SETUP: pTTT->lpszText = _T("Print setup"); break; default : pTTT->lpszText = _T("Unrecognised control ID"); break; } 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 } } } void CMultiPagePreviewView::OnDraw(CDC* pDC) { //Set the number of displayed pages to avoid MFC to display a blank page at the end... int OldnPages = m_nPages; m_nPages=min(m_nPages, max(1, m_pPreviewInfo->GetMaxPage() - m_nCurrentPage + 1)); CPreviewView::OnDraw(pDC); m_nPages = OldnPages; } --- NEW FILE: MultiPagePreview.h --- #if _MSC_VER >= 1000 #pragma once #endif // _MSC_VER >= 1000 #include "mappedbitmapbutton.h" #include "afxpriv.h" // #include <..\src\afximpl.h> // override MFC class class GUILIBDLLEXPORT CMultiPagePreviewView : public CPreviewView { DECLARE_DYNCREATE(CMultiPagePreviewView) protected: CMultiPagePreviewView(); virtual ~CMultiPagePreviewView(); public: // override private: // these variables are used in the page layout algorithm int m_Across; // number across the page, >= 1 int m_Down; // number down the page, >= 1 CPoint m_PageOffset; // amount to move the page from one position to the next // bitmapped buttons in toolbar CMappedBitmapButton m_print; CMappedBitmapButton m_printSetup; CMappedBitmapButton m_next; CMappedBitmapButton m_previous; CMappedBitmapButton m_zoomIn; CMappedBitmapButton m_zoomOut; CMappedBitmapButton m_pages; //{{AFX_VIRTUAL(CMultiPagePreviewView) protected: virtual BOOL PreCreateWindow(CREATESTRUCT& cs); virtual void OnDraw(CDC* pDC); //}}AFX_VIRTUAL protected: virtual void PositionPage(UINT nPage); void SetScaledSize(UINT nPage); void DoZoom(UINT nPage, CPoint point); void SetZoomState(UINT nNewState, UINT nPage, CPoint point); CSize CalcPageDisplaySize() ; void SetupScrollbar() ; int GetPrintOrientation() const; bool SetPrintOrientation(int mode) const; // note that is you change the maximum number of pages that can be displayed in preview mode // you have to increase the size of this array to make sure there is an entry available for every // possible page that can be shown at once. PAGE_INFO m_pageInfoArray2[9]; // Embedded array for the default implementation - replaces MFC one of size 2! #ifdef _DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) const; #endif protected: //{{AFX_MSG(CMultiPagePreviewView) afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); afx_msg void OnNumPageChange(); afx_msg void OnZoomIn(); afx_msg void OnZoomOut(); afx_msg void OnUpdateNumPageChange(CCmdUI* pCmdUI); afx_msg void OnUpdateZoomIn(CCmdUI* pCmdUI); afx_msg void OnUpdateZoomOut(CCmdUI* pCmdUI); afx_msg void OnLButtonDown(UINT nFlags, CPoint point); afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message); afx_msg void OnPreviewPages(); //}}AFX_MSG afx_msg BOOL OnToolTipNotify(UINT id, NMHDR *pNMHDR, LRESULT * pResult); afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) ; afx_msg void OnLandscape() ; afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt); afx_msg void OnPrintSetup(); DECLARE_MESSAGE_MAP() }; // the additional zoom level factors that we support when zoomed in // the default MFC range is 0 (ZOOMED_OUT), 1 and 2 #define ZOOM_IN_150 3 #define ZOOM_IN_200 4 #define ZOOM_IN_400 5 //{{AFX_INSERT_LOCATION}} |