home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / com / inole2 / chap13 / patron / pages.cpp < prev    next >
C/C++ Source or Header  |  1995-05-04  |  22KB  |  1,019 lines

  1. /*
  2.  * PAGES.CPP
  3.  * Patron Chapter 13
  4.  *
  5.  * Implementation of the CPages class.  See PAGEWIN.CPP and PRINT.CPP
  6.  * for additional member functions.
  7.  *
  8.  * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
  9.  *
  10.  * Kraig Brockschmidt, Microsoft
  11.  * Internet  :  kraigb@microsoft.com
  12.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  13.  */
  14.  
  15.  
  16. #include "patron.h"
  17.  
  18.  
  19. /*
  20.  * CPages:CPages
  21.  * CPages::~CPages
  22.  *
  23.  * Constructor Parameters:
  24.  *  hInst           HINSTANCE of the application we're in.
  25.  *  cf              UINT application clipboard format.
  26.  */
  27.  
  28. CPages::CPages(HINSTANCE hInst, UINT cf)
  29.     : CWindow(hInst)
  30.     {
  31.     m_pPageCur=NULL;
  32.     m_iPageCur=NOVALUE;  //Pages are 0 indexed, this is one before
  33.     m_cPages=0;
  34.     m_hWndPageList=NULL;
  35.     m_hFont=NULL;
  36.     m_fSystemFont=FALSE;
  37.  
  38.     //Initialize to 8.5*11 inch with .25 inch margins as a default.
  39.     m_cx=(LOMETRIC_PER_INCH*17)/2;
  40.     m_cy=LOMETRIC_PER_INCH*11;
  41.  
  42.     m_xMarginLeft=LOMETRIC_PER_INCH/4;
  43.     m_xMarginRight=LOMETRIC_PER_INCH/4;
  44.     m_yMarginTop=LOMETRIC_PER_INCH/4;
  45.     m_yMarginBottom=LOMETRIC_PER_INCH/4;
  46.  
  47.     m_xPos=0L;
  48.     m_yPos=0L;
  49.  
  50.     m_dwIDNext=0;
  51.     m_pIStorage=NULL;
  52.  
  53.     m_fDirty=FALSE;
  54.     m_cf=cf;
  55.  
  56.     //CHAPTER13MOD
  57.     m_fDragSource=FALSE;
  58.     m_fMoveInPage=FALSE;
  59.  
  60.     m_fDragRectShown=FALSE;
  61.  
  62.     m_uScrollInset=GetProfileInt(TEXT("windows")
  63.         , TEXT("DragScrollInset"), DD_DEFSCROLLINSET);
  64.     m_uScrollDelay=GetProfileInt(TEXT("windows")
  65.         , TEXT("DragScrollDelay"), DD_DEFSCROLLDELAY);
  66.  
  67.     m_uHScrollCode=0;
  68.     m_uVScrollCode=0;
  69.     //End CHAPTER13MOD
  70.  
  71.     return;
  72.     }
  73.  
  74.  
  75. CPages::~CPages(void)
  76.     {
  77.     //Ensure memory cleaned up in list; do final IStorage::Release
  78.     StorageSet(NULL, FALSE, FALSE);
  79.  
  80.     if (NULL!=m_hFont && !m_fSystemFont)
  81.         DeleteObject(m_hFont);
  82.  
  83.     if (NULL!=m_hWndPageList)
  84.         DestroyWindow(m_hWndPageList);
  85.  
  86.     //m_hWnd destroyed with the document.
  87.     return;
  88.     }
  89.  
  90.  
  91.  
  92. /*
  93.  * CPages::FIsDirty
  94.  *
  95.  * Purpose:
  96.  *  Tells the caller (document) if anything's happened to dirty us.
  97.  *
  98.  * Parameters:
  99.  *  None
  100.  *
  101.  * Return Value:
  102.  *  None
  103.  */
  104.  
  105. BOOL CPages::FIsDirty(void)
  106.     {
  107.     return m_fDirty;
  108.     }
  109.  
  110.  
  111.  
  112. /*
  113.  * CPages::Init
  114.  *
  115.  * Purpose:
  116.  *  Instantiates a pages window within a given parent.  The
  117.  *  parent may be a main application window, could be an MDI child
  118.  *  window. We really do not care.
  119.  *
  120.  * Parameters:
  121.  *  hWndParent      HWND of the parent of this window
  122.  *  pRect           LPRECT that this window should occupy
  123.  *  dwStyle         DWORD containing the window's style flags.
  124.  *                  Should contain WS_CHILD | WS_VISIBLE in
  125.  *                  typical circumstances.
  126.  *  uID             UINT ID to associate with this window
  127.  *  pv              LPVOID unused for now.
  128.  *
  129.  * Return Value:
  130.  *  BOOL            TRUE if the function succeeded, FALSE otherwise.
  131.  */
  132.  
  133. BOOL CPages::Init(HWND hWndParent, LPRECT pRect, DWORD dwStyle
  134.     , UINT uID, LPVOID pv)
  135.     {
  136.     int     cy;
  137.  
  138.     m_hWnd=CreateWindowEx(WS_EX_NOPARENTNOTIFY, SZCLASSPAGES
  139.         , SZCLASSPAGES, dwStyle, pRect->left, pRect->top
  140.         , pRect->right-pRect->left, pRect->bottom-pRect->top
  141.         , hWndParent, (HMENU)uID, m_hInst, this);
  142.  
  143.     if (NULL==m_hWnd)
  144.         return FALSE;
  145.  
  146.     /*
  147.      * Create the hidden listbox we'll use to track pages.  We give
  148.      * it the owner-draw style so we can just store pointers in it.
  149.      */
  150.     m_hWndPageList=CreateWindow(TEXT("listbox"), TEXT("Page List")
  151.         , WS_POPUP | LBS_OWNERDRAWFIXED, 0, 0, 100, 100
  152.         , HWND_DESKTOP, NULL, m_hInst, NULL);
  153.  
  154.     if (NULL==m_hWndPageList)
  155.         return FALSE;
  156.  
  157.     //Create a 14 point Arial font, or use the system variable font.
  158.     cy=MulDiv(-14, LOMETRIC_PER_INCH, 72);
  159.     m_hFont=CreateFont(cy, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE
  160.         , ANSI_CHARSET, OUT_TT_PRECIS, CLIP_TT_ALWAYS, PROOF_QUALITY
  161.         , VARIABLE_PITCH | FF_SWISS, TEXT("Arial"));
  162.  
  163.     if (NULL==m_hFont)
  164.         {
  165.         m_hFont=(HFONT)GetStockObject(ANSI_VAR_FONT);
  166.         m_fSystemFont=TRUE;
  167.         }
  168.  
  169.     return TRUE;
  170.     }
  171.  
  172.  
  173.  
  174.  
  175.  
  176.  
  177. /*
  178.  * CPages::StorageSet
  179.  *
  180.  * Purpose:
  181.  *  Provides the document's IStorage to the pages for its own use.
  182.  *  If this is a new storage, we initalize it with streams that we
  183.  *  want to always exists.  If this is an open, then we create
  184.  *  our page list from the PageList string we wrote before.
  185.  *
  186.  * Parameters:
  187.  *  pIStorage       LPSTORAGE to the new or opened storage.  If
  188.  *                  NULL, we just clean up and exit.
  189.  *  fChange         BOOL indicating is this was a Save As operation,
  190.  *                  meaning that we have the structure already and
  191.  *                  just need to change the value of m_pIStorage.
  192.  *  fInitNew        BOOL indicating if this is a new storage or one
  193.  *                  opened from a previous save.
  194.  *
  195.  * Return Value:
  196.  *  BOOL            TRUE if successful, FALSE otherwise.
  197.  */
  198.  
  199. BOOL CPages::StorageSet(LPSTORAGE pIStorage, BOOL fChange
  200.     , BOOL fInitNew)
  201.     {
  202.     DWORD           dwMode=STGM_DIRECT | STGM_READWRITE
  203.                         | STGM_SHARE_EXCLUSIVE;
  204.     HRESULT         hr;
  205.     PCPage          pPage;
  206.     BOOL            fRet=FALSE;
  207.     ULONG           cbRead;
  208.     PAGELIST        pgList;
  209.     LPSTREAM        pIStream;
  210.     LPMALLOC        pIMalloc;
  211.     LPDWORD         pdwID;
  212.     UINT            i;
  213.  
  214.     //If we're changing saved roots, simply open current page again
  215.     if (fChange)
  216.         {
  217.         if (NULL==pIStorage)
  218.             return FALSE;
  219.  
  220.         m_pIStorage->Release();
  221.         m_pIStorage=pIStorage;
  222.         m_pIStorage->AddRef();
  223.  
  224.         PageGet(m_iPageCur, &m_pPageCur, TRUE);
  225.         m_fDirty=FALSE;
  226.         return TRUE;
  227.         }
  228.  
  229.     if (NULL!=m_hWndPageList)
  230.         {
  231.         //On new or open, clean out whatever it is we have.
  232.         for (i=0; i < m_cPages; i++)
  233.             {
  234.             if (PageGet(i, &pPage, FALSE))
  235.                 delete pPage;
  236.             }
  237.  
  238.         SendMessage(m_hWndPageList, LB_RESETCONTENT, 0, 0L);
  239.         }
  240.  
  241.     if (NULL!=m_pIStorage)
  242.         m_pIStorage->Release();
  243.  
  244.     m_pIStorage=NULL;
  245.  
  246.     //If we're just cleaning up, then we're done.
  247.     if (NULL==pIStorage)
  248.         return TRUE;
  249.  
  250.     m_pIStorage=pIStorage;
  251.     m_pIStorage->AddRef();
  252.  
  253.     //If this is a new storage, create the streams we require
  254.     if (fInitNew)
  255.         {
  256.         //Page list header.
  257.         hr=m_pIStorage->CreateStream(SZSTREAMPAGELIST, dwMode
  258.             | STGM_CREATE, 0, 0, &pIStream);
  259.  
  260.         if (FAILED(hr))
  261.             return FALSE;
  262.  
  263.         pIStream->Release();
  264.  
  265.         //Device Configuration
  266.         hr=m_pIStorage->CreateStream(SZSTREAMDEVICECONFIG, dwMode
  267.             | STGM_CREATE, 0, 0, &pIStream);
  268.  
  269.         if (FAILED(hr))
  270.             return FALSE;
  271.  
  272.         pIStream->Release();
  273.         return TRUE;
  274.         }
  275.  
  276.  
  277.     /*
  278.      * We're opening an existing file:
  279.      *  1)  Configure for the device we're on
  280.      *  2)  Read the Page List and create page entries for each.
  281.      */
  282.  
  283.     ConfigureForDevice();
  284.  
  285.     //Read the page list.
  286.     hr=m_pIStorage->OpenStream(SZSTREAMPAGELIST, NULL, dwMode, 0
  287.         , &pIStream);
  288.  
  289.     if (FAILED(hr))
  290.         return FALSE;
  291.  
  292.     if (SUCCEEDED(CoGetMalloc(MEMCTX_TASK, &pIMalloc)))
  293.         {
  294.         pIStream->Read(&pgList, sizeof(PAGELIST), &cbRead);
  295.         m_cPages  =(UINT)pgList.cPages;
  296.         m_iPageCur=(UINT)pgList.iPageCur;
  297.         m_dwIDNext=pgList.dwIDNext;
  298.  
  299.         fRet=TRUE;
  300.         cbRead=pgList.cPages*sizeof(DWORD);
  301.  
  302.         if (0!=cbRead)
  303.             {
  304.             pdwID=(LPDWORD)pIMalloc->Alloc(cbRead);
  305.  
  306.             if (NULL!=pdwID)
  307.                 {
  308.                 pIStream->Read(pdwID, cbRead, &cbRead);
  309.  
  310.                 for (i=0; i < m_cPages; i++)
  311.                     fRet &=PageAdd(NOVALUE, *(pdwID+i), FALSE);
  312.  
  313.                 pIMalloc->Free(pdwID);
  314.                 }
  315.             }
  316.  
  317.         pIMalloc->Release();
  318.         }
  319.  
  320.     pIStream->Release();
  321.  
  322.     if (!fRet)
  323.         return FALSE;
  324.  
  325.     PageGet(m_iPageCur, &m_pPageCur, TRUE);
  326.     m_fDirty=FALSE;
  327.  
  328.     InvalidateRect(m_hWnd, NULL, FALSE);
  329.     UpdateWindow(m_hWnd);
  330.  
  331.     return TRUE;
  332.     }
  333.  
  334.  
  335.  
  336.  
  337.  
  338. /*
  339.  * CPages::StorageUpdate
  340.  *
  341.  * Purpose:
  342.  *  Insures that all pages are committed before a root save.
  343.  *
  344.  * Parameters:
  345.  *  fCloseAll       BOOL directing us to close all open storages
  346.  *                  and streams.
  347.  *
  348.  * Return Value:
  349.  *  BOOL            TRUE if successful, FALSE otherwise.
  350.  */
  351.  
  352. BOOL CPages::StorageUpdate(BOOL fCloseAll)
  353.     {
  354.     PCPage          pPage;
  355.     LPSTREAM        pIStream;
  356.     LPMALLOC        pIMalloc;
  357.     LPDWORD         pdwID;
  358.     ULONG           cb;
  359.     HRESULT         hr;
  360.     PAGELIST        pgList;
  361.     BOOL            fRet=FALSE;
  362.     UINT            i;
  363.  
  364.     //We only need to close the current page--nothing else is open.
  365.     if (NULL!=m_pPageCur)
  366.         {
  367.         m_pPageCur->Update();
  368.  
  369.         if (fCloseAll)
  370.             m_pPageCur->Close(FALSE);
  371.         }
  372.  
  373.     //We don't hold anything else open, so write the page list.
  374.     hr=m_pIStorage->OpenStream(SZSTREAMPAGELIST, NULL, STGM_DIRECT
  375.         | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &pIStream);
  376.  
  377.     if (FAILED(hr))
  378.         return FALSE;
  379.  
  380.     if (SUCCEEDED(CoGetMalloc(MEMCTX_TASK, &pIMalloc)))
  381.         {
  382.         pgList.cPages=m_cPages;
  383.         pgList.iPageCur=m_iPageCur;
  384.         pgList.dwIDNext=m_dwIDNext;
  385.  
  386.         pIStream->Write(&pgList, sizeof(PAGELIST), &cb);
  387.  
  388.         cb=m_cPages*sizeof(DWORD);
  389.         pdwID=(LPDWORD)pIMalloc->Alloc(cb);
  390.  
  391.         if (NULL!=pdwID)
  392.             {
  393.             for (i=0; i < m_cPages; i++)
  394.                 {
  395.                 PageGet(i, &pPage, FALSE);
  396.                 *(pdwID+i)=pPage->GetID();
  397.                 }
  398.  
  399.             pIStream->Write(pdwID, cb, &cb);
  400.             pIMalloc->Free(pdwID);
  401.             fRet=TRUE;
  402.             }
  403.         pIMalloc->Release();
  404.         }
  405.  
  406.     pIStream->Release();
  407.  
  408.     //Clean up the dirty flag when we do an update.
  409.     m_fDirty=!fRet;
  410.     return fRet;
  411.     }
  412.  
  413.  
  414.  
  415.  
  416.  
  417.  
  418.  
  419. /*
  420.  * CPages::RectGet
  421.  *
  422.  * Purpose:
  423.  *  Returns the rectangle of the Pages window in parent coordinates.
  424.  *
  425.  * Parameters:
  426.  *  pRect           LPRECT in which to return the rectangle.
  427.  *
  428.  * Return Value:
  429.  *  None
  430.  */
  431.  
  432. void CPages::RectGet(LPRECT pRect)
  433.     {
  434.     RECT        rc;
  435.     POINT       pt;
  436.  
  437.     //Retrieve the size of our rectangle in parent coordinates.
  438.     GetWindowRect(m_hWnd, &rc);
  439.     SETPOINT(pt, rc.left, rc.top);
  440.     ScreenToClient(GetParent(m_hWnd), &pt);
  441.  
  442.     SetRect(pRect, pt.x, pt.y, pt.x+(rc.right-rc.left)
  443.         , pt.y+(rc.bottom-rc.top));
  444.  
  445.     return;
  446.     }
  447.  
  448.  
  449.  
  450.  
  451.  
  452.  
  453. /*
  454.  * CPages::RectSet
  455.  *
  456.  * Purpose:
  457.  *  Sets a new rectangle for the Pages window which sizes to fit.
  458.  *  Coordinates are given in parent terms.
  459.  *
  460.  * Parameters:
  461.  *  pRect           LPRECT containing the new rectangle.
  462.  *  fNotify         BOOL indicating if we're to notify anyone of
  463.  *                  the change.
  464.  *
  465.  * Return Value:
  466.  *  None
  467.  */
  468.  
  469. void CPages::RectSet(LPRECT pRect, BOOL fNotify)
  470.     {
  471.     UINT        cx, cy;
  472.  
  473.     if (NULL==pRect)
  474.         return;
  475.  
  476.     cx=pRect->right-pRect->left;
  477.     cy=pRect->bottom-pRect->top;
  478.  
  479.     SetWindowPos(m_hWnd, NULL, pRect->left, pRect->top
  480.         , (UINT)cx, (UINT)cy, SWP_NOZORDER);
  481.  
  482.     UpdateScrollRanges();
  483.     return;
  484.     }
  485.  
  486.  
  487.  
  488.  
  489. /*
  490.  * CPages::SizeGet
  491.  *
  492.  * Purpose:
  493.  *  Retrieves the size of the pages window in parent coordinates.
  494.  *
  495.  * Parameters:
  496.  *  pRect           LPRECT in which to return the size.  The right
  497.  *                  and bottom fields will contain the dimensions.
  498.  *
  499.  * Return Value:
  500.  *  None
  501.  */
  502.  
  503. void CPages::SizeGet(LPRECT pRect)
  504.     {
  505.     RectGet(pRect);
  506.     return;
  507.     }
  508.  
  509.  
  510.  
  511.  
  512.  
  513.  
  514.  
  515. /*
  516.  * CPages::SizeSet
  517.  *
  518.  * Purpose:
  519.  *  Sets a new size in parent coordinates for the Pages window.
  520.  *
  521.  * Parameters:
  522.  *  pRect           LPRECT containing the new rectangle.
  523.  *  fNotify         BOOL indicating if we're to notify anyone of
  524.  *                  the change.
  525.  *
  526.  * Return Value:
  527.  *  None
  528.  */
  529.  
  530. void CPages::SizeSet(LPRECT pRect, BOOL fNotify)
  531.     {
  532.     UINT        cx, cy;
  533.  
  534.     if (NULL==pRect)
  535.         return;
  536.  
  537.     cx=pRect->right-pRect->left;
  538.     cy=pRect->bottom-pRect->top;
  539.  
  540.     SetWindowPos(m_hWnd, NULL, 0, 0, (UINT)cx, (UINT)cy
  541.         , SWP_NOMOVE | SWP_NOZORDER);
  542.  
  543.     UpdateScrollRanges();
  544.     return;
  545.     }
  546.  
  547.  
  548.  
  549.  
  550.  
  551.  
  552. /*
  553.  * CPages::ActivePage
  554.  *
  555.  * Purpose:
  556.  *  Returns a CPage pointer to the current page.
  557.  *
  558.  * Parameters:
  559.  *  None
  560.  *
  561.  * Return Value:
  562.  *  PCPage          Pointer to the current page.
  563.  */
  564.  
  565. PCPage CPages::ActivePage(void)
  566.     {
  567.     PCPage      pPage;
  568.     BOOL        fRet;
  569.  
  570.     fRet=PageGet(m_iPageCur, &pPage, FALSE);
  571.     return fRet ? pPage : NULL;
  572.     }
  573.  
  574.  
  575.  
  576.  
  577.  
  578. /*
  579.  * CPages::PageInsert
  580.  *
  581.  * Purpose:
  582.  *  Creates a new page immediately after the current page.  If
  583.  *  there are no pages then this creates page 1.
  584.  *
  585.  * Parameters:
  586.  *  uReserved       UINT unused
  587.  *
  588.  * Return Value:
  589.  *  UINT            Index of the new page, 0 on failure.
  590.  */
  591.  
  592. UINT CPages::PageInsert(UINT uReserved)
  593.     {
  594.     if (0!=m_cPages && NULL!=m_pPageCur)
  595.         {
  596.         //Close the current page, committing changes.
  597.         m_pPageCur->Close(TRUE);
  598.         }
  599.  
  600.     //Create and open the new page.
  601.     if (!PageAdd(m_iPageCur, m_dwIDNext, TRUE))
  602.         return 0;
  603.  
  604.     m_dwIDNext++;
  605.     m_iPageCur++;
  606.     m_cPages++;
  607.  
  608.     InvalidateRect(m_hWnd, NULL, FALSE);
  609.     UpdateWindow(m_hWnd);
  610.  
  611.     PageGet(m_iPageCur, &m_pPageCur, FALSE);
  612.     return m_iPageCur;
  613.     }
  614.  
  615.  
  616.  
  617.  
  618.  
  619.  
  620.  
  621. /*
  622.  * CPages::PageDelete
  623.  *
  624.  * Removes the current page from the page list.
  625.  *
  626.  * Parameters:
  627.  *  uReserved       UINT unused
  628.  *
  629.  * Return Value:
  630.  *  UINT            Index to the now current page from the page
  631.  *                  list, NOVALUE on error.
  632.  */
  633.  
  634. UINT CPages::PageDelete(UINT uReserved)
  635.     {
  636.     PCPage      pPage;
  637.  
  638.     if (!PageGet(m_iPageCur, &pPage, FALSE))
  639.         return NOVALUE;
  640.  
  641.     //Delete the page in both the storage and in memory.
  642.     SendMessage(m_hWndPageList, LB_DELETESTRING, m_iPageCur, 0L);
  643.  
  644.     m_pPageCur->Destroy(m_pIStorage);
  645.  
  646.     delete m_pPageCur;   //Does final pPage->Close
  647.     m_pPageCur=NULL;
  648.  
  649.     /*
  650.      * If this is the last page then the current is one less.  If
  651.      * it's the only page the current is zero.  Otherwise the
  652.      * current is the next page.
  653.      */
  654.  
  655.     if (m_iPageCur==m_cPages-1)   //Covers last or only page.
  656.         m_iPageCur--;
  657.  
  658.     m_cPages--;
  659.  
  660.     //Insure the new visible page is open.
  661.     if (0!=m_cPages)
  662.         {
  663.         PageGet(m_iPageCur, &m_pPageCur, TRUE);
  664.         InvalidateRect(m_hWnd, NULL, FALSE);
  665.         }
  666.     else
  667.         InvalidateRect(m_hWnd, NULL, TRUE);
  668.  
  669.     UpdateWindow(m_hWnd);
  670.     return m_iPageCur;
  671.     }
  672.  
  673.  
  674.  
  675.  
  676.  
  677.  
  678. /*
  679.  * CPages::CurPageGet
  680.  *
  681.  * Purpose:
  682.  *  Retrieves the index of the current page we're viewing.
  683.  *
  684.  * Parameters:
  685.  *  None
  686.  *
  687.  * Return Value:
  688.  *  UINT            Index of the current page.
  689.  */
  690.  
  691. UINT CPages::CurPageGet(void)
  692.     {
  693.     return m_iPageCur;
  694.     }
  695.  
  696.  
  697.  
  698.  
  699.  
  700. /*
  701.  * CPages::CurPageSet
  702.  *
  703.  * Purpose:
  704.  *  Sets the index of the current page to view.
  705.  *
  706.  * Parameters:
  707.  *  iPage           UINT index of the page to view. 0 means first
  708.  *                  page, NOVALUE means last page.
  709.  *
  710.  * Return Value:
  711.  *  UINT            Index of the previous current page, NOVALUE on
  712.  *                  error.
  713.  */
  714.  
  715. UINT CPages::CurPageSet(UINT iPage)
  716.     {
  717.     UINT    iPageNew;
  718.     UINT    iPagePrev=m_iPageCur;
  719.     PCPage  pPage;
  720.  
  721.     switch (iPage)
  722.         {
  723.         case 0:
  724.             iPageNew=0;
  725.             break;
  726.  
  727.         case NOVALUE:
  728.             iPageNew=m_cPages-1;
  729.             break;
  730.  
  731.         default:
  732.             if (iPage >= m_cPages)
  733.                 iPage=0;
  734.  
  735.             iPageNew=iPage;
  736.             break;
  737.         }
  738.  
  739.     //No reason to switch to the same page.
  740.     if (iPagePrev==iPageNew)
  741.         return iPage;
  742.  
  743.     //Close the old page committing changes.
  744.     if (!PageGet(iPagePrev, &pPage, FALSE))
  745.         return NOVALUE;
  746.  
  747.     pPage->Close(TRUE);
  748.  
  749.     m_iPageCur=iPageNew;
  750.  
  751.     //Open the new page.
  752.     PageGet(m_iPageCur, &m_pPageCur, TRUE);
  753.  
  754.     InvalidateRect(m_hWnd, NULL, FALSE);
  755.     UpdateWindow(m_hWnd);
  756.     return iPagePrev;
  757.     }
  758.  
  759.  
  760.  
  761.  
  762.  
  763. /*
  764.  * CPages::NumPagesGet
  765.  *
  766.  * Purpose:
  767.  *  Returns the number of pages this object current contains.
  768.  *
  769.  * Parameters:
  770.  *  None
  771.  *
  772.  * Return Value:
  773.  *  UINT            Number of pages we contain.
  774.  */
  775.  
  776. UINT CPages::NumPagesGet(void)
  777.     {
  778.     return m_cPages;
  779.     }
  780.  
  781.  
  782.  
  783.  
  784.  
  785. /*
  786.  * CPages::TenantCreate
  787.  * CPages::TenantDestroy
  788.  *
  789.  * Purpose:
  790.  *  Pass-throughs for CPage members on the current page.
  791.  */
  792.  
  793. BOOL CPages::TenantCreate(TENANTTYPE tType, LPVOID pv
  794.     , LPFORMATETC pFE, PPATRONOBJECT ppo, DWORD dwData)
  795.     {
  796.     BOOL    fRet;
  797.  
  798.     if (NULL==m_pPageCur)
  799.         return FALSE;
  800.  
  801.     fRet=m_pPageCur->TenantCreate(tType, pv, pFE, ppo, dwData);
  802.     m_fDirty |= fRet;
  803.     return fRet;
  804.     }
  805.  
  806.  
  807. BOOL CPages::TenantDestroy(void)
  808.     {
  809.     BOOL    fRet;
  810.  
  811.     if (NULL==m_pPageCur)
  812.         return FALSE;
  813.  
  814.     fRet=m_pPageCur->TenantDestroy();
  815.     m_fDirty |= fRet;
  816.     return fRet;
  817.     }
  818.  
  819.  
  820.  
  821. /*
  822.  * CPages::TenantClip
  823.  *
  824.  * Purpose:
  825.  *  Copies or cuts the currently selected tenant to the clipoard.
  826.  *
  827.  * Parameters:
  828.  *  fCut            BOOL TRUE to cut the object, FALSE to copy.
  829.  *
  830.  * Return Value:
  831.  *  BOOL            TRUE if successful, FALSE otherwise.
  832.  */
  833.  
  834. BOOL CPages::TenantClip(BOOL fCut)
  835.     {
  836.     BOOL    fRet;
  837.  
  838.     if (NULL==m_pPageCur)
  839.         return FALSE;
  840.  
  841.     fRet=m_pPageCur->TenantClip(fCut);
  842.     m_fDirty |= (fRet && fCut);
  843.     return fRet;
  844.     }
  845.  
  846.  
  847.  
  848.  
  849.  
  850.  
  851. /*
  852.  * CPages::FQueryObjectSelected
  853.  *
  854.  * Purpose:
  855.  *  Returns whether or not there is an object selected on this
  856.  *  page for Cut, Copy, Delete functions.
  857.  *
  858.  * Parameters:
  859.  *  hMenu           HMENU of the Edit menu.
  860.  *
  861.  * Return Value:
  862.  *  BOOL            TRUE if we have an object, FALSE otherwise.
  863.  */
  864.  
  865. BOOL CPages::FQueryObjectSelected(HMENU hMenu)
  866.     {
  867.     if (NULL==m_pPageCur)
  868.         return FALSE;
  869.  
  870.     return m_pPageCur->FQueryObjectSelected(hMenu);
  871.     }
  872.  
  873.  
  874.  
  875.  
  876. /*
  877.  * CPages::CalcBoundingRect
  878.  * (Protected)
  879.  *
  880.  * Purpose:
  881.  *  Calculates a rectangle that bounds the printed page and the
  882.  *  current scroll state of the window.
  883.  *
  884.  * Parameters:
  885.  *  prc             LPRECT to fill with window (device) coordinates.
  886.  *  fWindow         BOOL indicating to include the window in this
  887.  *                  calculation or return only the printed page
  888.  *                  coordinates.
  889.  *
  890.  * Return Value:
  891.  *  None
  892.  */
  893.  
  894. void CPages::CalcBoundingRect(LPRECT prc, BOOL fWindow)
  895.     {
  896.     RECT        rc, rcT;
  897.  
  898.     if (NULL==prc)
  899.         return;
  900.  
  901.     //Calculate the boundaries for sizing: intersect page & screen
  902.     rc.left=LOMETRIC_BORDER+m_xMarginLeft;
  903.     rc.top =-LOMETRIC_BORDER-m_yMarginTop;
  904.     rc.right =rc.left+(UINT)m_cx;
  905.     rc.bottom=rc.top -(UINT)m_cy;
  906.     RectConvertMappings(&rc, NULL, TRUE);
  907.     OffsetRect(&rc, -(int)m_xPos, -(int)m_yPos);
  908.  
  909.     if (!fWindow)
  910.         {
  911.         *prc=rc;
  912.         return;
  913.         }
  914.  
  915.     //Intersect with window to make the size bounds.
  916.     GetClientRect(m_hWnd, &rcT);
  917.     IntersectRect(prc, &rc, &rcT);
  918.     return;
  919.     }
  920.  
  921.  
  922.  
  923.  
  924.  
  925.  
  926. /*
  927.  * CPages::PageGet
  928.  * (Protected)
  929.  *
  930.  * Purpose:
  931.  *  Returns a page of a given index returning a BOOL so it's simple
  932.  *  to use this function inside if statements.
  933.  *
  934.  * Parameters:
  935.  *  iPage           UINT page to retrieve 0 based.
  936.  *  ppPage          PCPage * in which to return the page pointer
  937.  *  fOpen           BOOL indicating if we should open this page as
  938.  *                  well.
  939.  *
  940.  * Return Value:
  941.  *  BOOL            TRUE if successful, FALSE otherwise.
  942.  */
  943.  
  944. BOOL CPages::PageGet(UINT iPage, PCPage *ppPage, BOOL fOpen)
  945.     {
  946.     if (NULL==ppPage)
  947.         return FALSE;
  948.  
  949.     if (LB_ERR!=SendMessage(m_hWndPageList, LB_GETTEXT
  950.         , iPage, (LONG)ppPage))
  951.         {
  952.         if (fOpen)
  953.             (*ppPage)->Open(m_pIStorage);
  954.  
  955.         return TRUE;
  956.         }
  957.  
  958.     return FALSE;
  959.     }
  960.  
  961.  
  962.  
  963.  
  964.  
  965.  
  966. /*
  967.  * CPages::PageAdd
  968.  * (Protected)
  969.  *
  970.  * Purpose:
  971.  *  Creates a new page initialized to the given values.  The new
  972.  *  page's storage is created if it does not already exist.  If
  973.  *  fOpenStorage is set the page's storage is opened and left
  974.  *  opened.
  975.  *
  976.  * Parameters:
  977.  *  iPage           UINT Location at which to insert page; new page
  978.  *                  is inserted after this position.  NOVALUE for
  979.  *                  the end.
  980.  *  dwID            DWORD ID for this page.
  981.  *  fOpenStorage    BOOL indicating if we're to leave the storage
  982.  *                  open.
  983.  *
  984.  * Return Value:
  985.  *  BOOL            TRUE if the function succeeded, FALSE otherwise.
  986.  */
  987.  
  988. BOOL CPages::PageAdd(UINT iPage, DWORD dwID, BOOL fOpenStorage)
  989.     {
  990.     PCPage      pPage;
  991.     LRESULT     lr;
  992.  
  993.     pPage=new CPage(dwID, m_hWnd, this);
  994.  
  995.     if (NULL==pPage)
  996.         return FALSE;
  997.  
  998.     if (fOpenStorage)
  999.         pPage->Open(m_pIStorage);
  1000.  
  1001.     if (NOVALUE==iPage)
  1002.         iPage--;
  1003.  
  1004.     //Now try to add to the listbox.
  1005.     lr=SendMessage(m_hWndPageList, LB_INSERTSTRING, iPage+1
  1006.         , (LONG)pPage);
  1007.  
  1008.     if (LB_ERRSPACE==lr)
  1009.         {
  1010.         if (fOpenStorage)
  1011.             pPage->Close(FALSE);
  1012.  
  1013.         delete pPage;
  1014.         return FALSE;
  1015.         }
  1016.  
  1017.     return TRUE;
  1018.     }
  1019.