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

Windows编程

开发平台:

Visual C++

  1. /*
  2.  * DOCUMENT.CPP
  3.  * Cosmo Chapter 1
  4.  *
  5.  * Implementation of the CCosmoDoc derivation of CDocument as
  6.  * well as an implementation of CPolylineAdviseSink.
  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 "cosmo.h"
  15. /*
  16.  * CCosmoDoc::CCosmoDoc
  17.  * CCosmoDoc::~CCosmoDoc
  18.  *
  19.  * Constructor Parameters:
  20.  *  hInst           HINSTANCE of the application.
  21.  *  pFR             PCFrame of the frame object.
  22.  *  pAdv            PCDocumentAdviseSink to notify on events
  23.  */
  24. CCosmoDoc::CCosmoDoc(HINSTANCE hInst, PCFrame pFR
  25.     , PCDocumentAdviseSink pAdv)
  26.     : CDocument(hInst, pFR, pAdv)
  27.     {
  28.     m_pPL=NULL;
  29.     m_pPLAdv=NULL;
  30.     m_uPrevSize=SIZE_RESTORED;
  31.     return;
  32.     }
  33. CCosmoDoc::~CCosmoDoc(void)
  34.     {
  35.     //Clean up the allocations we did in Init
  36.     if (NULL!=m_pPL)
  37.         delete m_pPL;
  38.     if (NULL!=m_pPLAdv)
  39.         delete m_pPLAdv;
  40.     return;
  41.     }
  42. /*
  43.  * CCosmoDoc::Init
  44.  *
  45.  * Purpose:
  46.  *  Initializes an already created document window.  The client
  47.  *  actually creates the window for us, then passes that here for
  48.  *  further initialization.
  49.  *
  50.  * Parameters:
  51.  *  pDI             PDOCUMENTINIT containing initialization
  52.  *                  parameters.
  53.  *
  54.  * Return Value:
  55.  *  BOOL            TRUE if the function succeeded, FALSE otherwise.
  56.  */
  57. BOOL CCosmoDoc::Init(PDOCUMENTINIT pDI)
  58.     {
  59.     RECT        rc;
  60.     //Change the stringtable range to our customization.
  61.     pDI->idsMin=IDS_DOCUMENTMIN;
  62.     pDI->idsMax=IDS_DOCUMENTMAX;
  63.     //Do default initialization
  64.     if (!CDocument::Init(pDI))
  65.         return FALSE;
  66.     //Add the Polyline stuff we need.
  67.     m_pPLAdv=new CPolylineAdviseSink(this);
  68.     m_pPL   =new CPolyline(m_hInst);
  69.     //Attempt to create our contained Polyline.
  70.     GetClientRect(m_hWnd, &rc);
  71.     InflateRect(&rc, -8, -8);
  72.     if (!m_pPL->Init(m_hWnd, &rc, WS_CHILD | WS_VISIBLE
  73.         , ID_POLYLINE, m_pPLAdv))
  74.         return FALSE;
  75.     return TRUE;
  76.     }
  77. /*
  78.  * CCosmoDoc::FMessageHook
  79.  *
  80.  * Purpose:
  81.  *  Processes WM_SIZE for the document so we can resize
  82.  *  the Polyline.
  83.  *
  84.  * Parameters:
  85.  *  <WndProc Parameters>
  86.  *  pLRes           LRESULT * in which to store the return
  87.  *                  value for the message.
  88.  *
  89.  * Return Value:
  90.  *  BOOL            TRUE to prevent further processing,
  91.  *                  FALSE otherwise.
  92.  */
  93. BOOL CCosmoDoc::FMessageHook(HWND hWnd, UINT iMsg, WPARAM wParam
  94.     , LPARAM lParam, LRESULT *pLRes)
  95.     {
  96.     UINT        dx, dy;
  97.     RECT        rc;
  98.     *pLRes=0;
  99.     if (WM_SIZE==iMsg)
  100.         {
  101.         //Don't effect the Polyline size to or from minimized state.
  102.         if (SIZE_MINIMIZED!=wParam && SIZE_MINIMIZED !=m_uPrevSize)
  103.             {
  104.             //When we change size, resize any Polyline we hold.
  105.             dx=LOWORD(lParam);
  106.             dy=HIWORD(lParam);
  107.             /*
  108.              * If we are getting WM_SIZE in response to a Polyline
  109.              * notification, then don't resize the Polyline window
  110.              * again.
  111.              */
  112.             if (!m_fNoSize && NULL!=m_pPL)
  113.                 {
  114.                 //Resize the polyline to fit the new client
  115.                 SetRect(&rc, 8, 8, dx-8, dy-8);
  116.                 m_pPL->RectSet(&rc, FALSE);
  117.                 /*
  118.                  * We consider sizing something that makes the file
  119.                  * dirty, but not until we've finished the create
  120.                  * process, which is why we set fNoDirty to FALSE
  121.                  * in WM_CREATE since we get a WM_SIZE on the first
  122.                  * creation.
  123.                  */
  124.                 if (!m_fNoDirty)
  125.                     FDirtySet(TRUE);
  126.                 SetRect(&rc, 0, 0, dx, dy);
  127.                 if (NULL!=m_pAdv)
  128.                     m_pAdv->OnSizeChange(this, &rc);
  129.                 m_fNoDirty=FALSE;
  130.                 }
  131.             }
  132.         m_uPrevSize=wParam;
  133.         }
  134.     /*
  135.      * We return FALSE even on WM_SIZE so we can let the default
  136.      * procedure handle maximized MDI child windows appropriately.
  137.      */
  138.     return FALSE;
  139.     }
  140. /*
  141.  * CCosmoDoc::Clear
  142.  *
  143.  * Purpose:
  144.  *  Sets all contents in the document back to defaults with
  145.  *  no filename.
  146.  *
  147.  * Paramters:
  148.  *  None
  149.  *
  150.  * Return Value:
  151.  *  None
  152.  */
  153. void CCosmoDoc::Clear(void)
  154.     {
  155.     //Completely reset the polyline
  156.     m_pPL->New();
  157.     CDocument::Clear();
  158.     m_lVer=0;
  159.     return;
  160.     }
  161. /*
  162.  * CCosmoDoc::Load
  163.  *
  164.  * Purpose:
  165.  *  Loads a given document without any user interface overwriting
  166.  *  the previous contents of the Polyline window.  We do this by
  167.  *  opening the file and telling the Polyline to load itself from
  168.  *  that file.
  169.  *
  170.  * Parameters:
  171.  *  fChangeFile     BOOL indicating if we're to update the window
  172.  *                  title and the filename from using this file.
  173.  *  pszFile         LPTSTR to the filename to load, NULL if the file
  174.  *                  is new and untitled.
  175.  *
  176.  * Return Value:
  177.  *  UINT            An error value from DOCERR_*
  178.  */
  179. UINT CCosmoDoc::Load(BOOL fChangeFile, LPTSTR pszFile)
  180.     {
  181.     if (NULL==pszFile)
  182.         {
  183.         //For a new untitled document, just rename ourselves.
  184.         Rename(NULL);
  185.         m_lVer=VERSIONCURRENT;
  186.         return DOCERR_NONE;
  187.         }
  188.     m_lVer=m_pPL->ReadFromFile(pszFile);
  189.     if (POLYLINE_E_READFAILURE==m_lVer)
  190.         return DOCERR_READFAILURE;
  191.     if (POLYLINE_E_UNSUPPORTEDVERSION==m_lVer)
  192.         return DOCERR_UNSUPPORTEDVERSION;
  193.     if (fChangeFile)
  194.         Rename(pszFile);
  195.     //Importing a file makes things dirty
  196.     FDirtySet(!fChangeFile);
  197.     return DOCERR_NONE;
  198.     }
  199. /*
  200.  * CCosmoDoc::Save
  201.  *
  202.  * Purpose:
  203.  *  Writes the file to a known filename, requiring that the user has
  204.  *  previously used FileOpen or FileSaveAs to provide a filename.
  205.  *
  206.  * Parameters:
  207.  *  uType           UINT indicating the type of file the user
  208.  *                  requested to save in the File Save As dialog.
  209.  *  pszFile         LPTSTR under which to save.  If NULL, use the
  210.  *                  current name.
  211.  *
  212.  * Return Value:
  213.  *  UINT            An error value from DOCERR_*
  214.  */
  215. UINT CCosmoDoc::Save(UINT uType, LPTSTR pszFile)
  216.     {
  217.     LONG        lVer, lRet;
  218.     UINT        uTemp;
  219.     BOOL        fRename=TRUE;
  220.     if (NULL==pszFile)
  221.         {
  222.         fRename=FALSE;
  223.         pszFile=m_szFile;
  224.         }
  225.     /*
  226.      * Type 1 is the current version, type 2 is version 1.0 of the
  227.      * Polyline so we use this to send the right version to
  228.      * CPolyline::WriteToFile.
  229.      */
  230.     switch (uType)
  231.         {
  232.         case 0:         //From Save, use loaded version.
  233.             lVer=m_lVer;
  234.             break;
  235.         case 1:
  236.             lVer=VERSIONCURRENT;
  237.             break;
  238.         case 2:
  239.             lVer=MAKELONG(0, 1);    //1.0
  240.             break;
  241.         default:
  242.             return DOCERR_UNSUPPORTEDVERSION;
  243.         }
  244.     /*
  245.      * If the version the user wants to save is different from the
  246.      * version that we loaded and m_lVer is not zero (new doc),
  247.      * then inform the user of the version change and verify.
  248.      */
  249.     if (0!=m_lVer && m_lVer!=lVer)
  250.         {
  251.         TCHAR       szMsg[128];
  252.         wsprintf(szMsg, PSZ(IDS_VERSIONCHANGE)
  253.             , (UINT)HIWORD(m_lVer), (UINT)LOWORD(m_lVer)
  254.             , (UINT)HIWORD(lVer), (UINT)LOWORD(lVer));
  255.         uTemp=MessageBox(m_hWnd, szMsg, PSZ(IDS_DOCUMENTCAPTION)
  256.             , MB_YESNOCANCEL);
  257.         if (IDCANCEL==uTemp)
  258.             return DOCERR_CANCELLED;
  259.         //If the user won't upgrade, revert to loaded version.
  260.         if (IDNO==uTemp)
  261.             lVer=m_lVer;
  262.         }
  263.     lRet=m_pPL->WriteToFile(pszFile, lVer);
  264.     if (POLYLINE_E_NONE!=lRet)
  265.         return DOCERR_WRITEFAILURE;
  266.     //Saving makes us clean
  267.     FDirtySet(FALSE);
  268.     //Update the known version of this document.
  269.     m_lVer=lVer;
  270.     if (fRename)
  271.         Rename(pszFile);
  272.     return DOCERR_NONE;
  273.     }
  274. /*
  275.  * CCosmoDoc::Undo
  276.  *
  277.  * Purpose:
  278.  *  Reverses a previous action.
  279.  *
  280.  * Parameters:
  281.  *  None
  282.  *
  283.  * Return Value:
  284.  *  None
  285.  */
  286. void CCosmoDoc::Undo(void)
  287.     {
  288.     m_pPL->Undo();
  289.     return;
  290.     }
  291. /*
  292.  * CCosmoDoc::Clip
  293.  *
  294.  * Purpose:
  295.  *  Places a private format, a metafile, and a bitmap of the display
  296.  *  on the clipboard, optionally implementing Cut by deleting the
  297.  *  data in the current window after rendering.
  298.  *
  299.  * Parameters:
  300.  *  hWndFrame       HWND of the main window.
  301.  *  fCut            BOOL indicating cut (TRUE) or copy (FALSE).
  302.  *
  303.  * Return Value:
  304.  *  BOOL            TRUE if successful, FALSE otherwise.
  305.  */
  306. BOOL CCosmoDoc::Clip(HWND hWndFrame, BOOL fCut)
  307.     {
  308.     BOOL            fRet=TRUE;
  309.     HGLOBAL         hMem;
  310.     UINT            i;
  311.     //This array is so we can loop over the formats we provide.
  312.     static UINT     rgcf[3]={0, CF_METAFILEPICT, CF_BITMAP};
  313.     const UINT      cFormats=3;
  314.     if (!OpenClipboard(hWndFrame))
  315.         return FALSE;
  316.     //Clean out whatever junk is in the clipboard.
  317.     EmptyClipboard();
  318.     rgcf[0]=m_cf;
  319.     for (i=0; i < cFormats; i++)
  320.         {
  321.         //Copy private data first.
  322.         hMem=RenderFormat(rgcf[i]);
  323.         if (NULL!=hMem)
  324.             SetClipboardData(rgcf[i], hMem);
  325.         else
  326.             fRet &=FALSE;
  327.         }
  328.     //Free clipboard ownership.
  329.     CloseClipboard();
  330.     //Delete our current data if "cut" succeeded.
  331.     if (fRet && fCut)
  332.         {
  333.         m_pPL->New();
  334.         FDirtySet(TRUE);
  335.         }
  336.     return fRet;
  337.     }
  338. /*
  339.  * CCosmoDoc::RenderFormat
  340.  *
  341.  * Purpose:
  342.  *  Renders a specific clipboard format into global memory.
  343.  *
  344.  * Parameters:
  345.  *  cf              UINT format to render.
  346.  *
  347.  * Return Value:
  348.  *  HGLOBAL         Global memory handle containing the data.
  349.  */
  350. HGLOBAL CCosmoDoc::RenderFormat(UINT cf)
  351.     {
  352.     HGLOBAL     hMem;
  353.     if (cf==m_cf)
  354.         {
  355.         m_pPL->DataGetMem(VERSIONCURRENT, &hMem);
  356.         return hMem;
  357.         }
  358.     switch (cf)
  359.         {
  360.         case CF_METAFILEPICT:
  361.             return m_pPL->RenderMetafilePict();
  362.         case CF_BITMAP:
  363.             return (HGLOBAL)m_pPL->RenderBitmap();
  364.         }
  365.     return NULL;
  366.     }
  367. /*
  368.  * CCosmoDoc::FQueryPaste
  369.  *
  370.  * Purpose:
  371.  *  Determines if we can paste data from the clipboard.
  372.  *
  373.  * Parameters:
  374.  *  None
  375.  *
  376.  * Return Value:
  377.  *  BOOL            TRUE if data is available, FALSE otherwise.
  378.  */
  379. BOOL CCosmoDoc::FQueryPaste(void)
  380.     {
  381.     return IsClipboardFormatAvailable(m_cf);
  382.     }
  383. /*
  384.  * CCosmoDoc::Paste
  385.  *
  386.  * Purpose:
  387.  *  Retrieves the private data format from the clipboard and sets it
  388.  *  to the current figure in the editor window.
  389.  *
  390.  *  Note that if this function is called, then the clipboard format
  391.  *  is available because the Paste menu item is only enabled if the
  392.  *  format is present.
  393.  *
  394.  * Parameters:
  395.  *  hWndFrame       HWND of the main window.
  396.  *
  397.  * Return Value:
  398.  *  BOOL            TRUE if successful, FALSE otherwise.
  399.  */
  400. BOOL CCosmoDoc::Paste(HWND hWndFrame)
  401.     {
  402.     HGLOBAL         hMem;
  403.     PPOLYLINEDATA   ppl;
  404.     BOOL            fRet=FALSE;
  405.     if (!OpenClipboard(hWndFrame))
  406.         return FALSE;
  407.     hMem=GetClipboardData(m_cf);
  408.     if (NULL!=hMem)
  409.         {
  410.         ppl=(PPOLYLINEDATA)GlobalLock(hMem);
  411.         //TRUE in wParam to cause PLN_SIZECHANGE notification
  412.         m_pPL->DataSet(ppl, FALSE, TRUE);
  413.         GlobalUnlock(hMem);
  414.         FDirtySet(TRUE);
  415.         fRet=TRUE;
  416.         }
  417.     CloseClipboard();
  418.     return fRet;
  419.     }
  420. /*
  421.  * CCosmoDoc::ColorSet
  422.  *
  423.  * Purpose:
  424.  *  Changes a color used in our contained Polyline.
  425.  *
  426.  * Parameters:
  427.  *  iColor          UINT index of the color to change.
  428.  *  cr              COLORREF new color.
  429.  *
  430.  * Return Value:
  431.  *  COLORREF        Previous color for the given index.
  432.  */
  433. COLORREF CCosmoDoc::ColorSet(UINT iColor, COLORREF cr)
  434.     {
  435.     return m_pPL->ColorSet(iColor, cr);
  436.     }
  437. /*
  438.  * CCosmoDoc::ColorGet
  439.  *
  440.  * Purpose:
  441.  *  Retrieves a color currently in use in the Polyline.
  442.  *
  443.  * Parameters:
  444.  *  iColor          UINT index of the color to retrieve.
  445.  *
  446.  * Return Value:
  447.  *  COLORREF        Current color for the given index.
  448.  */
  449. COLORREF CCosmoDoc::ColorGet(UINT iColor)
  450.     {
  451.     return m_pPL->ColorGet(iColor);
  452.     }
  453. /*
  454.  * CCosmoDoc::LineStyleSet
  455.  *
  456.  * Purpose:
  457.  *  Changes the line style currently used in the Polyline
  458.  *
  459.  * Parameters:
  460.  *  iStyle          UINT index of the new line style to use.
  461.  *
  462.  * Return Value:
  463.  *  UINT            Previous line style.
  464.  */
  465. UINT CCosmoDoc::LineStyleSet(UINT iStyle)
  466.     {
  467.     return m_pPL->LineStyleSet(iStyle);
  468.     }
  469. /*
  470.  * CCosmoDoc::LineStyleGet
  471.  *
  472.  * Purpose:
  473.  *  Retrieves the line style currently used in the Polyline
  474.  *
  475.  * Parameters:
  476.  *  None
  477.  *
  478.  * Return Value:
  479.  *  UINT            Current line style.
  480.  */
  481. UINT CCosmoDoc::LineStyleGet(void)
  482.     {
  483.     if (NULL==m_pPL)    //m_pPL might not be valid yet
  484.         return 0L;
  485.     return m_pPL->LineStyleGet();
  486.     }
  487. /*
  488.  * CPolylineAdviseSink::CPolylineAdviseSink
  489.  * CPolylineAdviseSink::~CPolylineAdviseSink
  490.  *
  491.  * Constructor Parameters:
  492.  *  pv              LPVOID to store in this object
  493.  */
  494. CPolylineAdviseSink::CPolylineAdviseSink(LPVOID pv)
  495.     {
  496.     m_pv=pv;
  497.     return;
  498.     }
  499. CPolylineAdviseSink::~CPolylineAdviseSink(void)
  500.     {
  501.     return;
  502.     }
  503. /*
  504.  * CPolylineAdviseSink::OnPointChange
  505.  *
  506.  * Purpose:
  507.  *  Informs the document that the polyline added or removed a point.
  508.  *
  509.  * Parameters:
  510.  *  None
  511.  *
  512.  * Return Value:
  513.  *  None
  514.  */
  515. void CPolylineAdviseSink::OnPointChange(void)
  516.     {
  517.     PCDocument      pDoc=(PCDocument)m_pv;
  518.     pDoc->FDirtySet(TRUE);
  519.     return;
  520.     }
  521. /*
  522.  * CPolylineAdviseSink::OnSizeChange
  523.  *
  524.  * Purpose:
  525.  *  Informs the document that the polyline changed size.
  526.  *
  527.  * Parameters:
  528.  *  None
  529.  *
  530.  * Return Value:
  531.  *  None
  532.  */
  533. void CPolylineAdviseSink::OnSizeChange(void)
  534.     {
  535.     PCCosmoDoc      pDoc=(PCCosmoDoc)m_pv;
  536.     RECT            rc;
  537.     DWORD           dwStyle;
  538.     /*
  539.      * Polyline window is informing us that it changed size in
  540.      * response to setting it's data.  Therefore we have to
  541.      * size ourselves accordingly but without moving the screen
  542.      * position of the polyline window.
  543.      */
  544.     pDoc->m_fNoSize=TRUE;
  545.     //Set the document window size.
  546.     GetWindowRect(pDoc->m_pPL->Window(), &rc);
  547.     InflateRect(&rc, 8, 8);
  548.     //Adjust for a window sans menu
  549.     dwStyle=GetWindowLong(pDoc->m_hWnd, GWL_STYLE);
  550.     AdjustWindowRect(&rc, dwStyle, FALSE);
  551.     SetWindowPos(pDoc->m_hWnd, NULL, 0, 0, rc.right-rc.left
  552.         , rc.bottom-rc.top, SWP_NOMOVE | SWP_NOZORDER);
  553.     if (NULL!=pDoc->m_pAdv)
  554.         pDoc->m_pAdv->OnSizeChange(pDoc, &rc);
  555.     pDoc->m_fNoSize=FALSE;
  556.     pDoc->FDirtySet(TRUE);
  557.     return;
  558.     }
  559. /*
  560.  * CPolylineAdviseSink::OnDataChange
  561.  *
  562.  * Purpose:
  563.  *  Informs the document that the polyline data changed.
  564.  *
  565.  * Parameters:
  566.  *  None
  567.  *
  568.  * Return Value:
  569.  *  None
  570.  */
  571. void CPolylineAdviseSink::OnDataChange(void)
  572.     {
  573.     PCCosmoDoc      pDoc=(PCCosmoDoc)m_pv;
  574.     if (NULL!=pDoc->m_pAdv)
  575.         pDoc->m_pAdv->OnDataChange(pDoc);
  576.     pDoc->FDirtySet(TRUE);
  577.     return;
  578.     }
  579. /*
  580.  * CPolylineAdviseSink::OnColorChange
  581.  *
  582.  * Purpose:
  583.  *  Informs the document that the polyline data changed a color.
  584.  *
  585.  * Parameters:
  586.  *  None
  587.  *
  588.  * Return Value:
  589.  *  None
  590.  */
  591. void CPolylineAdviseSink::OnColorChange(void)
  592.     {
  593.     PCCosmoDoc      pDoc=(PCCosmoDoc)m_pv;
  594.     pDoc->FDirtySet(TRUE);
  595.     return;
  596.     }
  597. /*
  598.  * CPolylineAdviseSink::OnLineStyleChange
  599.  *
  600.  * Purpose:
  601.  *  Informs the document that the polyline changed its line style.
  602.  *
  603.  * Parameters:
  604.  *  None
  605.  *
  606.  * Return Value:
  607.  *  None
  608.  */
  609. void CPolylineAdviseSink::OnLineStyleChange(void)
  610.     {
  611.     PCCosmoDoc      pDoc=(PCCosmoDoc)m_pv;
  612.     pDoc->FDirtySet(TRUE);
  613.     return;
  614.     }