home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c082_122 / 2.ddi / OLESRVR.ZIP / OLESRVR.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-10  |  15.2 KB  |  674 lines

  1. // ObjectWindows - (C) Copyright 1992 by Borland International
  2.  
  3. /* implementation of classes TAppOleServer & TWindowServer */
  4.  
  5. #include <owl.h>
  6.  
  7. #define SERVERONLY
  8. #include <ole.h>
  9.  
  10. #include <ctype.h>
  11. #include "olesrvr.h"
  12.  
  13. #define szEmbedding   "Embedding"
  14.  
  15.  
  16.  
  17. /*
  18.     constructor
  19.     -----------
  20. */
  21. TWindowServer::TWindowServer (PTWindowsObject Parent,
  22.                               LPSTR           Title) : TWindow (Parent, Title)
  23. {
  24.   AssignMenu ("MenuBar");
  25.  
  26.     Attr.Style = WS_OVERLAPPEDWINDOW;
  27.     Attr.X = 100;
  28.     Attr.Y = 100;
  29.     Attr.W = 250;
  30.     Attr.H = 250;
  31. }
  32.  
  33.  
  34. /*
  35.     About
  36.     -----
  37.  
  38.     Help/About menu item
  39. */
  40. void
  41. TWindowServer::About (RTMessage /* Msg */)
  42. {
  43.   GetApplication()->ExecDialog (new TDialog (this, "AboutBox"));
  44. }
  45.  
  46.  
  47. /*
  48.     SaveChangesPrompt
  49.     -----------------
  50.  
  51.     the user has requested File/New, File/Open, or File/Exit
  52.  
  53.     prompt the user to save changes in the document and return whether the
  54.     pending operation (new/open/exit) should be executed or canceled
  55. */
  56. FILEIOSTATUS
  57. TWindowServer::SaveChangesPrompt ()
  58. {
  59.   TOLEApp       *pApp = (TOLEApp *) GetApplication();
  60.   TOLEDocument  *pDoc = pApp->pServer->pDocument;
  61.   int            outcome = IDYES;
  62.  
  63.   if (pDoc->fDirty) {
  64.     char   buf[128];
  65.  
  66.     if (pDoc->type == doctypeEmbedded)
  67.       wsprintf (buf,
  68.                 "Embedded object %s has changed. Do you want to update?",
  69.                 (LPSTR) pDoc->szName);
  70.  
  71.     else
  72.       wsprintf (buf, "Do you want to save changes to %s?", (LPSTR) pDoc->szName);
  73.  
  74.     outcome = MessageBox (HWindow, buf, szAppName, MB_ICONQUESTION | MB_YESNOCANCEL);
  75.  
  76.     if (outcome == IDYES)
  77.       if (pDoc->type == doctypeEmbedded)
  78.         OleSavedServerDoc (pDoc->lhDoc);
  79.  
  80.       else
  81.           pDoc->SaveDoc();
  82.   }
  83.  
  84.   if (outcome != IDCANCEL) {
  85.     if (OleRevokeServerDoc (pDoc->lhDoc) == OLE_WAIT_FOR_RELEASE) {
  86.       //
  87.       // server library is in the process of closing down connections to
  88.       // the document. wait until it is finished (flag "fDirty" becomes TRUE)
  89.       // before we re-use the document space...
  90.       //
  91.       pApp->Wait (pDoc->fRelease);
  92.     }
  93.  
  94.     pDoc->lhDoc = 0;
  95.  
  96.     if (pDoc->type == doctypeEmbedded)
  97.       EndEmbedding();
  98.   }
  99.  
  100.   return outcome == IDCANCEL ? fiCancel : fiExecute;
  101. }
  102.  
  103. /* Prompt the user for changes and initiate application shutdown by
  104.  * calling OleRevokeServer()
  105.  *
  106.  * OleRevokeServer() automatically revokes any documents which revokes
  107.  *   any objects
  108.  */
  109. BOOL TWindowServer::CanClose()
  110. {
  111.    if (SaveChangesPrompt() == fiExecute) {
  112.     TOLEApp     *pApp = (TOLEApp *) GetApplication();
  113.     TOLEServer  *pServer = pApp->pServer;
  114.  
  115.     if (OleRevokeServer (pServer->lhServer) == OLE_WAIT_FOR_RELEASE) {
  116.       //
  117.       // server library is in the process of closing down connections to
  118.       // the server. wait until it is finished (flag "fDirty" becomes TRUE)
  119.       // before we terminate
  120.       //
  121.       pApp->Wait (pServer->fRelease);
  122.     }
  123.     return(TRUE);
  124.   }
  125.   else
  126.     return(FALSE);
  127. }
  128.  
  129. /*
  130.     New
  131.     ---
  132.  
  133.     File/New menu item
  134. */
  135. void
  136. TWindowServer::New (RTMessage /* Msg */)
  137. {
  138.   if (SaveChangesPrompt() == fiExecute) {
  139.     //
  140.     // make the new document (we reuse the same objects)
  141.     //
  142.     ((TOLEApp *) GetApplication())->pServer->pDocument->Reset (0);
  143.   }
  144. }
  145.  
  146.  
  147. /*
  148.     Open
  149.     ----
  150.  
  151.     File/Open menu item
  152. */
  153. void
  154. TWindowServer::Open (RTMessage /* Msg */)
  155. {
  156.   if (SaveChangesPrompt() == fiExecute) {
  157.     char           path[MAXPATHLENGTH];
  158.     TOLEDocument  *pDoc = ((TOLEApp *) GetApplication())->pServer->pDocument;
  159.  
  160.     pDoc->Reset (TOLEDocument::PromptForOpenFileName (path) ? path : 0);
  161.   }
  162. }
  163.  
  164.  
  165. /*
  166.     Save
  167.     ----
  168.  
  169.     File/Save menu item
  170.  
  171.     NOTE: only for stand-alone mode...
  172. */
  173. void
  174. TWindowServer::Save (RTMessage /* Msg */)
  175. {
  176.   ((TOLEApp *) GetApplication())->pServer->pDocument->SaveDoc();
  177. }
  178.  
  179.  
  180. /*
  181.     SaveAs
  182.     ------
  183.  
  184.     File/Save As menu item
  185. */
  186. void
  187. TWindowServer::SaveAs (RTMessage /* Msg */)
  188. {
  189.   ((TOLEApp *) GetApplication())->pServer->pDocument->SaveAs();
  190. }
  191.  
  192.  
  193. /*
  194.     Update
  195.     ------
  196.  
  197.     File/Update menu item
  198.  
  199.     NOTE: only for embedding mode...
  200. */
  201. void
  202. TWindowServer::Update (RTMessage /* Msg */)
  203. {
  204.   TOLEDocument  *pDoc = ((TOLEApp *) GetApplication())->pServer->pDocument;
  205.  
  206.   //
  207.   // notify the server library that the embedded document has changed
  208.   //
  209.   OleSavedServerDoc (pDoc->lhDoc);
  210.  
  211.   //
  212.   // reset the doc's "fDirty" flag to FALSE
  213.   //
  214.   pDoc->fDirty = FALSE;
  215. }
  216.  
  217.  
  218. /*
  219.     Copy
  220.     ----
  221.  
  222.     Edit/Copy menu item
  223.  
  224.     WHAT IT DOES:
  225.       - open and empty the clipboard
  226.       - put the data formats on the clipboard
  227.       - close the clipboard
  228.  
  229.     NOTE: since this app only has one object we don't support "Cut" and
  230.           "Delete", but your app might want to
  231. */
  232. void
  233. TWindowServer::Copy (RTMessage /* Msg */)
  234. {
  235.   TOLEApp     *pApp = (TOLEApp *) GetApplication();
  236.   TOLEObject  *pObject = pApp->pServer->pDocument->pObject;
  237.   HANDLE       handle;
  238.  
  239.   if (OpenClipboard (HWindow)) {
  240.     EmptyClipboard();
  241.  
  242.     //
  243.     // server applications are responsible for placing the data formats on the
  244.     // clipboard in most important order first
  245.     //
  246.     // here is the standard ordering:
  247.     //    1. Application-specific data
  248.     //    2. Native
  249.     //    3. OwnerLink
  250.     //    4. CF_METAFILEPICT
  251.     //    5. CF_BITMAP
  252.     //    6. ObjectLink
  253.     //    7. Any other data
  254.     //
  255.     // add Native first...
  256.     //
  257.     if ((handle = pObject->GetNativeData()) != NULL)
  258.       SetClipboardData (pApp->cfNative, handle);
  259.  
  260.     //
  261.     // in order for the object to be embedded we must also identify the
  262.     // owner of the object using "OwnerLink" data
  263.     //
  264.     if ((handle = pObject->GetLinkData()) != NULL)
  265.       SetClipboardData (pApp->cfOwnerLink, handle);
  266.  
  267.     //
  268.     // now offer at least one presentation format
  269.     //
  270.     // if the server doesn't have an object handler DLL then it must provide
  271.     // a metafile
  272.     //
  273.     if ((handle = pObject->GetMetafilePicture()) != NULL)
  274.       SetClipboardData (CF_METAFILEPICT, handle);
  275.  
  276.     //
  277.     // now offer bitmap
  278.     //
  279.     if ((handle = pObject->GetBitmapData()) != NULL)
  280.       SetClipboardData (CF_BITMAP, handle);
  281.  
  282.     //
  283.     // if the document type is a file then we can offer "ObjectLink"
  284.     //
  285.     if (pApp->pServer->pDocument->type == doctypeFromFile)
  286.       if ((handle = pObject->GetLinkData()) != NULL)
  287.         SetClipboardData (pApp->cfObjectLink, handle);
  288.  
  289.     //
  290.     // now close the clipboard
  291.     //
  292.     CloseClipboard ();
  293.   }
  294. }
  295.  
  296.  
  297. /*
  298.     ShapeChange
  299.     -----------
  300.  
  301.     user has selected a menu item from the "Shape" menu
  302.  
  303.     check the new menu item, uncheck the previous menu item, change the
  304.     selected object's type, repaint the damaged area, and check the menu items
  305.     to see if they should be enabled/disabled
  306. */
  307. void
  308. TWindowServer::ShapeChange (NATIVETYPE newType)
  309. {
  310.   TOLEDocument  *pDoc = ((TOLEApp *) GetApplication())->pServer->pDocument;
  311.   TOLEObject    *pObject = pDoc->pObject;
  312.   NATIVETYPE     oldType = pObject->GetType();
  313.  
  314.   if (newType != oldType) {
  315.     RECT   r = {OBJX, OBJY, OBJX + OBJWIDTH, OBJY + OBJHEIGHT};
  316.  
  317.     //
  318.     // change the object's type which marks the document as "dirty" and
  319.     // notifies each linked object of the change
  320.     //
  321.     pObject->SetType (newType);
  322.  
  323.     InvalidateRect (HWindow, &r, TRUE);
  324.  
  325.     //
  326.     // now remove the check from the previous menu item and check the new
  327.     // selection
  328.     //
  329.     HMENU  hMenu = GetMenu (HWindow);
  330.  
  331.     CheckMenuItem (hMenu, oldType, MF_UNCHECKED);
  332.     CheckMenuItem (hMenu, newType, MF_CHECKED);
  333.   }
  334. }
  335.  
  336.  
  337. /*
  338.     WmCommand
  339.     ---------
  340.  
  341.     rather than have a message response function for each menu item on the
  342.     "Shape" menu we catch the commands here instead
  343.  
  344.     other commands are passed to our inherited method
  345. */
  346. void
  347. TWindowServer::WMCommand (RTMessage Msg)
  348. {
  349.   if (Msg.WParam >= IDM_ELLIPSE && Msg.WParam <= IDM_TRIANGLE)
  350.     ShapeChange ((NATIVETYPE) Msg.WParam);
  351.  
  352.   else
  353.     TWindow::WMCommand (Msg);
  354. }
  355.  
  356.  
  357. /*
  358.     BeginEmbedding
  359.     --------------
  360.  
  361.     change the File/Save As... menu item to File/Save Copy As...
  362. */
  363. void
  364. TWindowServer::BeginEmbedding ()
  365. {
  366.   HMENU  hMenu = GetMenu (HWindow);
  367.  
  368.   ModifyMenu (hMenu, IDM_SAVEAS, MF_BYCOMMAND | MF_STRING,
  369.               IDM_SAVEAS, "Save Copy &As...");
  370. }
  371.  
  372.  
  373. /*
  374.     UpdateFileMenu
  375.     --------------
  376.  
  377.     change File/Save and File/Exit
  378. */
  379. void
  380. TWindowServer::UpdateFileMenu (LPSTR szDocName)
  381. {
  382.   HMENU  hMenu = GetMenu (HWindow);
  383.   char   buf[128];
  384.  
  385.   //
  386.   // change File/Save to File/Update <Client Document>
  387.   //
  388.   wsprintf (buf, "&Update %s", szDocName);
  389.   ModifyMenu (hMenu, IDM_SAVE, MF_BYCOMMAND | MF_STRING, IDM_UPDATE, buf);
  390.  
  391.   //
  392.   // change File/Exit to File/Exit & Return to <Client Document>
  393.   //
  394.   wsprintf (buf, "E&xit && Return to %s", szDocName);
  395.   ModifyMenu (hMenu, CM_EXIT, MF_BYCOMMAND | MF_STRING, CM_EXIT, buf);
  396. }
  397.  
  398.  
  399. /*
  400.     EndEmbedding
  401.     ------------
  402.  
  403.     change File/Save Copy As..., File/Exit & Return, and File/Update
  404. */
  405. void
  406. TWindowServer::EndEmbedding ()
  407. {
  408.   HMENU  hMenu = GetMenu (HWindow);
  409.  
  410.   ModifyMenu (hMenu, IDM_SAVEAS, MF_BYCOMMAND | MF_STRING,
  411.               IDM_SAVEAS, "Save &As...");
  412.  
  413.   ModifyMenu (hMenu, CM_EXIT, MF_BYCOMMAND | MF_STRING, CM_EXIT, "E&xit");
  414.  
  415.   ModifyMenu (hMenu, IDM_UPDATE, MF_BYCOMMAND | MF_STRING, IDM_SAVE, "&Save");
  416. }
  417.  
  418.  
  419. /*
  420.     Paint
  421.     -----
  422.  
  423.     draw the object
  424. */
  425. void
  426. TWindowServer::Paint (HDC hDC, PAINTSTRUCT _FAR &)
  427. {
  428.   SetViewportOrg (hDC, OBJX, OBJY);
  429.   ((TOLEApp *) GetApplication())->pServer->pDocument->pObject->Draw (hDC);
  430. }
  431.  
  432.  
  433.  
  434. /*
  435.     enum OLEAPPERROR
  436.     ---- -----------
  437.  
  438.     error codes particular to the OLE app. if we detect an error while
  439.     registering the clipboard formats, initializing the vtable pointers,
  440.     processing the command line, or initializing the server then we set
  441.     "Status" accordingly which will abort the app
  442.  
  443.     we also override the Error() method accordingly so we can display an
  444.     appropriate error message
  445. */
  446. enum OLEAPPERROR {olRegClipError = 182, olInitVTBLError = 183};
  447.  
  448.  
  449. /*
  450.     CreateServer
  451.     ------------
  452.  
  453.     process the command line and check for option /Embedding or -Embedding
  454.  
  455.     then create the OLE server
  456.  
  457.     there are four scenarios we are concerned with:
  458.  
  459.     1. Case One: olesrvr.exe
  460.       - embedding = FALSE; create an untitled document
  461.  
  462.     2. Case two: olesrvr.exe filename
  463.       - embedding = FALSE; create a new document from the file
  464.  
  465.     3. Case three: olesrvr.exe -Embedding
  466.       - embedding = TRUE; do NOT create or register a document.
  467.                           do NOT show a window until client requests it
  468.  
  469.     4. Case four: olesrvr.exe -Embedding filename
  470.       - embedding = TRUE; load file, register it (this is the linking case)
  471.                           do NOT show a window until client requests it
  472. */
  473. void
  474. TOLEApp::CreateServer ()
  475. {
  476.   LPSTR   lpStr = lpCmdLine;
  477.   BOOL    embedded = FALSE;
  478.   LPSTR   szPath = 0;
  479.  
  480.   //
  481.   // skip any whitespace
  482.   //
  483.   while (*lpStr && *lpStr == ' ')
  484.     lpStr++;
  485.  
  486.   //
  487.   // check for a '-' or '/'
  488.   //
  489.   if (*lpStr && (*lpStr == '-' || *lpStr == '/')) {
  490.     lpStr++;
  491.  
  492.     //
  493.     // assume TRUE unless we see otherwise
  494.     //
  495.     embedded = TRUE;
  496.  
  497.     for (int i = 0; i < sizeof (szEmbedding) - 1; i++)
  498.       if (*lpStr++ != szEmbedding[i]) {
  499.         embedded = FALSE;
  500.         break;
  501.       }
  502.   }
  503.  
  504.   //
  505.   // skip any whitespace
  506.   //
  507.   while (*lpStr && *lpStr == ' ')
  508.     lpStr++;
  509.  
  510.   //
  511.   // check for a filename
  512.   //
  513.   if (*lpStr)
  514.     szPath = lpStr;
  515.  
  516.   //
  517.   // if we are embedded, then we won't display the window until requested
  518.   // to by the library
  519.   //
  520.   if (embedded)
  521.     nCmdShow = SW_HIDE;
  522.  
  523.   if (szPath)
  524.     new TOLEServer (*this, szPath);
  525.  
  526.   else
  527.     new TOLEServer (*this, embedded);
  528. }
  529.  
  530.  
  531. /*
  532.     RegisterClipboardFormats
  533.     ------------------------
  534.  
  535.     if you are a mini-server (embedding only) you will need to register
  536.     clipboard formats for "Native" and "OwnerLink"
  537.  
  538.     if you are a full server (linking and embedding) you will also need to
  539.     register clipboard format "ObjectLink"
  540. */
  541. BOOL
  542. TOLEApp::RegisterClipboardFormats ()
  543. {
  544.     cfNative = RegisterClipboardFormat ("Native");
  545.     cfOwnerLink = RegisterClipboardFormat ("OwnerLink");
  546.     cfObjectLink = RegisterClipboardFormat ("ObjectLink");
  547.  
  548.   return cfNative != 0 && cfOwnerLink != 0 && cfObjectLink != 0;
  549. }
  550.  
  551.  
  552. /*
  553.     InitInstance
  554.     ------------
  555.  
  556.     - create the main window
  557.     - create OLE VTBL thunks
  558.     - create clipboard formats
  559.     - parse command line
  560.     - create/register OLE server
  561.  
  562.     NOTE: we let Windows free all thunks when the application terminates and
  563.           don't do it ourselves
  564. */
  565. void
  566. TOLEApp::InitInstance ()
  567. {
  568.   MainWindow = new TWindowServer (NULL, szAppName);
  569.   MainWindow = MakeWindow (MainWindow);
  570.  
  571.   if (!TOLEServer::InitVTBL (hInstance) ||
  572.       !TOLEDocument::InitVTBL (hInstance) ||
  573.       !TOLEObject::InitVTBL (hInstance))
  574.     Status = olInitVTBLError;
  575.  
  576.   else if (!RegisterClipboardFormats())
  577.     Status = olRegClipError;
  578.  
  579.   else
  580.     CreateServer();
  581.  
  582.   //
  583.   // we do this *after* calling CreateServer(), because if we are embedded
  584.   // then we don't want to display the main window until requested to by
  585.   // the server library, and it is CreateServer() who determines that and sets
  586.   // "nCmdShow" accordingly
  587.   //
  588.   if (MainWindow)
  589.     MainWindow->Show (nCmdShow);
  590.  
  591.   else
  592.     Status = EM_INVALIDMAINWINDOW;
  593. }
  594.  
  595.  
  596. /*
  597.     Error
  598.     -----
  599.  
  600.     trap error messages generated by OLE app, display an error message box
  601.     and terminate the application
  602. */
  603. void
  604. TOLEApp::Error (int errorCode)
  605. {
  606.   char  *str;
  607.  
  608.   if (errorCode == olRegClipError)
  609.     str = "Fatal Error: Cannot register ""Native"", ""OwnerLink"", and ""ObjectLink"" clipboard formats";
  610.  
  611.   else if (errorCode == olInitVTBLError)
  612.     str = "Fatal Error: Cannot create thunks for ""OLESERVER"", ""OLESERVERDOC"", and ""OLEOBJECT"" VTBLs";
  613.  
  614.   else {
  615.     TApplication::Error (errorCode);
  616.     return;
  617.   }
  618.  
  619.   MessageBox (0, str, szAppName, MB_OK | MB_ICONSTOP);
  620.   PostAppMessage (GetCurrentTask(), WM_QUIT, 0, 0);
  621. }
  622.  
  623.  
  624. /*
  625.     Wait
  626.     ----
  627.  
  628.     dispatch messages until the given flag is set to TRUE
  629.     one use of this function is to wait until a Release method is called
  630.     after a function has returned OLE_WAIT_FOR_RELEASE.
  631.  
  632.     PARAMETER: "waitFlag" is a reference to a flag that will be set to TRUE
  633.                when we can return
  634. */
  635. void
  636. TOLEApp::Wait (BOOL &waitFlag)
  637. {
  638.   MSG   msg;
  639.   BOOL  fMoreMessages = FALSE;
  640.  
  641.   while (!waitFlag) {
  642.     OleUnblockServer (pServer->lhServer, &fMoreMessages);
  643.  
  644.     if (!fMoreMessages) {
  645.       //
  646.       // if there are no more messages in the OLE queue, go to system queue
  647.       //
  648.       if (GetMessage (&msg, NULL, NULL, NULL)) {
  649.         TranslateMessage (&msg);
  650.         DispatchMessage (&msg);
  651.       }
  652.     }
  653.   }
  654. }
  655.  
  656.  
  657.  
  658. /*
  659.     WinMain
  660.     -------
  661. */
  662. int PASCAL
  663. WinMain (HINSTANCE hInstance,
  664.              HINSTANCE hPrevInstance,
  665.              LPSTR     lpCmdLine,
  666.              int       nCmdShow)
  667. {
  668.   TOLEApp  app (szAppName, hInstance, hPrevInstance, lpCmdLine, nCmdShow);
  669.  
  670.   app.Run ();
  671.  
  672.   return app.Status;
  673. }
  674.