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

Windows编程

开发平台:

Visual C++

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