PAGES.CPP
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:22k
源码类别:

Windows编程

开发平台:

Visual C++

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