home *** CD-ROM | disk | FTP | other *** search
/ C Programming Starter Kit 2.0 / SamsPublishing-CProgrammingStarterKit-v2.0-Win31.iso / bc45 / owlsrc.pak / OLEFRAME.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-07-24  |  15.4 KB  |  592 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows
  3. // (C) Copyright 1994 by Borland International, All Rights Reserved
  4. //
  5. //   Implementation of class TOleFrame.
  6. //----------------------------------------------------------------------------
  7. #define INC_OLE2
  8. #include <owl/owlpch.h>
  9. #include <owl/decmdifr.h>
  10. #include <owl/statusba.h>
  11. #include <owl/ocfevent.h>
  12. #include <owl/uihandle.h>
  13. #include <owl/oleframe.h>
  14. #include <owl/olewindo.h>
  15.  
  16. DIAG_DEFINE_GROUP_INIT(OWL_INI, OwlOleMenu, 1, 0);
  17.  
  18. //#define DEBUG_PADS          // define to make pads paint red for debugging
  19. const int DllIdleTime = 200;  // time in MS for idle action polling
  20.  
  21. // Four edge locations for inplace-server space negotiation
  22. //
  23. const TDecoratedFrame::TLocation SpaceLoc[] = {
  24.   TDecoratedFrame::Left,
  25.   TDecoratedFrame::Top,
  26.   TDecoratedFrame::Right,
  27.   TDecoratedFrame::Bottom
  28. };
  29.  
  30. //----------------------------------------------------------------------------
  31. // An empty no-erase window that inserts itself into its decorated frame
  32. // parent
  33. //
  34.  
  35. class TPadWindow : public TWindow {
  36.   public:
  37.     TPadWindow(TWindow* parent, int edge, TModule* module = 0)
  38.       : TWindow(parent, 0, module)
  39.     {
  40.       Attr.Id = IDW_PADDECORATION+edge;
  41.       Attr.Style = WS_CHILD | WS_VISIBLE;
  42.       Attr.W = Attr.H = 1;             // takeup no space until needed
  43.                                        // need 1 since layout overlapps borders
  44.       #if defined(DEBUG_PADS)
  45.         SetBkgndColor(TColor(255,0,0));  // to help Debug toolbar negotiations
  46.         strstream s;
  47.         s << "Pad" << ('0' + edge);
  48.         Title = strnewdup(s.str());
  49.       #else
  50.         SetBkgndColor(NoErase);          // Don't erase--to avoid flicker
  51.       #endif
  52.     }
  53. };
  54.  
  55. //----------------------------------------------------------------------------
  56. // A small window class to act as a holder for the unattached remote server
  57. // view windows
  58. //
  59.  
  60. class TRemViewBucket : public TFrameWindow {
  61.   public:
  62.     TRemViewBucket(TWindow* parent)
  63.       : TFrameWindow(parent, "RemViewBucket")
  64.       {
  65.         Attr.Style = WS_CHILD | WS_DISABLED;
  66.         Attr.Id = IDW_REMVIEWBUCKET;
  67.       }
  68.  
  69.     bool SetDocTitle(const char far*, int) {return true;}
  70.  
  71.   protected:
  72.   private:
  73. };
  74.  
  75.  
  76. DEFINE_RESPONSE_TABLE1(TOleFrame, TDecoratedFrame)
  77.   EV_WM_SIZE,
  78.   EV_WM_TIMER,
  79.   EV_WM_ACTIVATEAPP,
  80.  
  81.   EV_MESSAGE(WM_OCEVENT, EvOcEvent),
  82.   EV_OC_APPINSMENUS,
  83.   EV_OC_APPMENUS,
  84.   EV_OC_APPPROCESSMSG,
  85.   EV_OC_APPFRAMERECT,
  86.   EV_OC_APPBORDERSPACEREQ,
  87.   EV_OC_APPBORDERSPACESET,
  88.   EV_OC_APPSTATUSTEXT,
  89.   EV_OC_APPRESTOREUI,
  90.   EV_OC_APPSHUTDOWN,
  91. END_RESPONSE_TABLE;
  92.  
  93. TOleFrame::TOleFrame(const char far* title,
  94.                      TWindow*        clientWnd,
  95.                      bool            trackMenuSelection,
  96.                      TModule*        module)
  97. :
  98.   TDecoratedFrame(0, title, clientWnd, trackMenuSelection, module),
  99.   TFrameWindow(0, title, clientWnd, false, module),
  100.   TWindow(0, title, module),
  101.   HOldMenu(0),
  102.   OcApp(0),
  103.   StashCount(0),
  104.   OcShutDown(DontCare)
  105. {
  106.   new TRemViewBucket(this);  // Construct bucket to hold hidden server windows
  107.  
  108.   // Retrieve the OcApp ptr from our owning application if it is a TOcModule
  109.   //
  110.   TOcModule* ocm = TYPESAFE_DOWNCAST(GetApplication(), TOcModule);
  111.   if (ocm)
  112.     SetOcApp(ocm->OcApp);
  113. }
  114.  
  115. //
  116. // Let the OC app go. It will delete itself when it can
  117. //
  118. TOleFrame::~TOleFrame()
  119. {
  120. }
  121.  
  122. //
  123. // Initial set of OcApp being passed to us to use.
  124. //
  125. void
  126. TOleFrame::SetOcApp(TOcApp* ocApp)
  127. {
  128.   PRECONDITION(ocApp);
  129.   OcApp = ocApp;
  130.  
  131.   // Initialize OLE 2 clipboard format names
  132.   //
  133.   char f[] = "%s";
  134.   AddUserFormatName(f, f, ocrEmbedSource);
  135.   AddUserFormatName(f, f, ocrEmbeddedObject);
  136.   AddUserFormatName(f, f, ocrLinkSource);
  137. }
  138.  
  139. //
  140. // Let the OcApp know our HWND so that it can talk to us
  141. //
  142. void
  143. TOleFrame::SetupWindow()
  144. {
  145.   PRECONDITION(OcApp);
  146.   TDecoratedFrame::SetupWindow();
  147.   OcApp->SetupWindow(*this);
  148.  
  149.   // Insert the four pad windows for in-place server toolbars. Inserting last
  150.   // will place them as the inner-most decorations, which is needed with the
  151.   // status bar
  152.   //
  153.   for (int edge = 0; edge < 4; edge++)
  154.     Insert(*new TPadWindow(this, edge), ::SpaceLoc[edge]);
  155.  
  156.   // Create a timer to allow us to poll for idle time when we are a dll server
  157.   //
  158.   if (!OcApp->IsOptionSet(amExeMode))
  159.     SetTimer(IDT_DLLIDLE, DllIdleTime);
  160. }
  161.  
  162. //
  163. //
  164. //
  165. void
  166. TOleFrame::CleanupWindow()
  167. {
  168.   if (!OcApp->IsOptionSet(amExeMode))
  169.     KillTimer(IDT_DLLIDLE);
  170. }
  171.  
  172. //
  173. // Add user defined format and result names to the list
  174. //
  175. void
  176. TOleFrame::AddUserFormatName(const char far* name, const char far* resultName,
  177.                              const char far* id)
  178. {
  179.   PRECONDITION(OcApp);
  180.   OcApp->AddUserFormatName(name, resultName, id);
  181. }
  182.  
  183. //
  184. //
  185. //
  186. void
  187. TOleFrame::OleViewClosing(bool close)
  188. {
  189.   if (close && OcShutDown == DontCare) {
  190.     OcShutDown = ViewInitiated;
  191.   }
  192.   else if (!close && OcShutDown == ViewInitiated) {
  193.     OcShutDown = DontCare;
  194.   }
  195. }
  196.  
  197. // Disconnect document servers with their clients.
  198. // Document servers can be documents with objects copied on the clipboard or
  199. // documents brought up though linking.
  200. //
  201. void
  202. sDisconnectDocServer(TWindow* win, void* /*retVal*/)
  203. {
  204.   if (win) {
  205.     win->ForEach(sDisconnectDocServer);
  206.  
  207.     TOleWindow* oleWin = TYPESAFE_DOWNCAST(win, TOleWindow);
  208.     if (oleWin)
  209.       oleWin->OleShutDown();
  210.   }
  211. }
  212.  
  213. //
  214. // Make sure that any embeded servers also get a chance to OK the close
  215. // sequence. If the user closes the app, but there are still embeddings, hide
  216. // the frame instead of destroying it
  217. //
  218. void
  219. TOleFrame::Destroy(int retVal)
  220. {
  221.   if (!HWindow || OcShutDown == UserInitiated)
  222.     return;
  223.  
  224.   // Disconnect document servers with their clients if user shuts down the app
  225.   //
  226.   if (OcShutDown == DontCare) {
  227.     OcShutDown = UserInitiated;
  228.     ForEach(sDisconnectDocServer, 0);
  229.   }
  230.  
  231.   if (!OcApp->CanClose()) {
  232.     OcApp->SetOption(amEmbedding, true);
  233.     OcShutDown = DontCare; // reset the shutdown flag
  234.     ShowWindow(SW_HIDE);
  235.   }
  236.   else {
  237.     bool dllServer = !OcApp->IsOptionSet(amExeMode);
  238.  
  239.     TDecoratedFrame::Destroy(retVal);
  240.  
  241.     // If user shuts down the DLL server (as in the case of open-editing,
  242.     // we need to set the mainwindow flag to 0 so that only the application
  243.     // will be destroyed.  All windows are destroyed in previous calls.
  244.     //
  245.     if (dllServer && OcShutDown != ServerInitiated) {
  246. //      GetApplication()->SetMainWindow(0);
  247.       GetApplication()->MainWindow = 0;
  248.       delete GetApplication();
  249.     }
  250.   }
  251. }
  252.  
  253. //
  254. // Forward size message to OcApp to allow it to notify any embedded servers
  255. // about size changes
  256. //
  257. void
  258. TOleFrame::EvSize(uint sizeType, TSize& size)
  259. {
  260.   TDecoratedFrame::EvSize(sizeType, size);
  261.   if (OcApp)
  262.     OcApp->EvResize();
  263. }
  264.  
  265. //
  266. // Forward Activate messages to OcApp to allow it to notify any embedded servers
  267. // about being activated
  268. //
  269. void
  270. TOleFrame::EvActivateApp(bool active, HTASK hTask)
  271. {
  272.   OcApp->EvActivate(active);
  273.   TDecoratedFrame::EvActivateApp(active, hTask);
  274. }
  275.  
  276. //
  277. //
  278. //
  279. void
  280. TOleFrame::EvTimer(uint timerId)
  281. {
  282.   if (timerId == IDT_DLLIDLE)
  283.     GetApplication()->PostDispatchAction();
  284.   TWindow::EvTimer(timerId);
  285. }
  286.  
  287. //
  288. // Handle & sub-dispatch the OC event message.
  289. //
  290. LRESULT
  291. TOleFrame::EvOcEvent(WPARAM wParam, LPARAM lParam)
  292. {
  293.   TEventHandler::TEventInfo eventInfo(WM_OCEVENT, wParam);
  294.  
  295.   // Give the client window the first chance at it
  296.   //
  297.   TWindow* receiver = GetClientWindow();
  298.   if (receiver->Find(eventInfo))
  299.     return receiver->Dispatch(eventInfo, wParam, lParam);
  300.  
  301.   // Then try this frame
  302.   //
  303.   if (Find(eventInfo))
  304.     return Dispatch(eventInfo, wParam, lParam);
  305.  
  306.   // Last, try the application in case it wants to override events
  307.   //
  308.   if (GetApplication()->Find(eventInfo))
  309.     return GetApplication()->Dispatch(eventInfo, wParam, lParam);
  310.   return 0;
  311. }
  312.  
  313. //
  314. // Insert our menus into a provided menu bar, possibly merging them with a
  315. // servers.
  316. //
  317. bool
  318. TOleFrame::EvOcAppInsMenus(TOcMenuDescr far& sharedMenu)
  319. {
  320.   if (HOldMenu) {
  321.     TRACEX(OwlOleMenu, 0, "EvOcAppInsMenus called while HOldMenu is " << hex <<
  322.           (uint)HOldMenu);
  323.     return true;
  324.   }
  325.  
  326.   // Recreate a temporary composite menu for frame
  327.   //
  328.   TMenuDescr compMenuDesc; // empty menudescr
  329.   if (GetMenuDescr()) {
  330.     compMenuDesc.Merge(*GetMenuDescr());
  331.  
  332.     // Mask off the server menus
  333.     //
  334.     compMenuDesc.Merge(TMenuDescr(0,  0, -1, 0, -1, 0, -1));
  335.   }
  336.  
  337.   // Merge into the OLE shared menubar
  338.   //
  339.   TMenuDescr shMenuDescr(sharedMenu.HMenu,
  340.                          sharedMenu.Width[0],
  341.                          sharedMenu.Width[1],
  342.                          sharedMenu.Width[2],
  343.                          sharedMenu.Width[3],
  344.                          sharedMenu.Width[4],
  345.                          sharedMenu.Width[5]);
  346.   shMenuDescr.Merge(compMenuDesc);
  347.  
  348.   // Copy the shared menu widths back to the OC struct
  349.   //
  350.   for (int i = 0; i < 6; i++)
  351.     sharedMenu.Width[i] = shMenuDescr.GetGroupCount(i);
  352.  
  353.   // Save the container popups so they can be destroyed later
  354.   //
  355.   StashContainerPopups(shMenuDescr);
  356.  
  357.   TRACEX(OwlOleMenu, 0, "Merged menu " << hex << (uint)sharedMenu.HMenu);
  358.   return true;
  359. }
  360.  
  361. //
  362. // Now, actually set the merged menubar into our frame
  363. //
  364. bool
  365. TOleFrame::EvOcAppMenus(TOcMenuDescr far& appMenus)
  366. {
  367.   if (!appMenus.HMenu) {
  368.     if (HOldMenu) {
  369.       TRACEX(OwlOleMenu, 0, "EvOcAppMenus(0) resetting Old " << hex <<
  370.              (uint)HOldMenu);
  371.       TMenu oleMenu(*this);
  372.       SetMenu(HOldMenu);     // assumes we are just restoring the old owl menu
  373.       HOldMenu = 0;
  374.     }
  375.     DestroyStashedPopups();  // destroy the popup copies we made
  376.     return true;
  377.   }
  378.  
  379.   // Don't set the menu again if we are holding a merged one already
  380.   //
  381.   if (HOldMenu) {
  382.     TRACEX(OwlOleMenu, 0, "EvOcAppMenus called while HOldMenu is " << hex <<
  383.           (uint)HOldMenu);
  384.     return true;
  385.   }
  386.  
  387.   HOldMenu = GetMenu();
  388.   TRACEX(OwlOleMenu, 0, "Saved Old " << hex << (uint)HOldMenu);
  389.  
  390.   SetMenu(appMenus.HMenu);
  391.   TRACEX(OwlOleMenu, 0, "Set merged " << hex << (uint)appMenus.HMenu);
  392.  
  393.   return true;
  394. }
  395.  
  396. //
  397. // Process accelerators and other queued messages from the server's queue in
  398. // our app
  399. //
  400. bool
  401. TOleFrame::EvOcAppProcessMsg(MSG far* msg)
  402. {
  403. #if defined(BI_DATA_NEAR)
  404.   MSG nearMsg = *msg;
  405.   bool ret = GetApplication()->ProcessAppMsg(nearMsg);
  406.   *msg = nearMsg;
  407.   return ret;
  408. #else
  409.   return GetApplication()->ProcessAppMsg(*msg);
  410. #endif
  411. }
  412.  
  413. //
  414. // Let the server know our frame's client rect, minus the status bar height,
  415. // if there is one
  416. //
  417. bool
  418. TOleFrame::EvOcAppFrameRect(TRect far* rect)
  419. {
  420.   PRECONDITION(rect);
  421.   *rect = GetClientRect();
  422.   TWindow*  sb = ChildWithId(IDW_STATUSBAR);
  423.   if (sb) {
  424.     TRect sbr = sb->GetClientRect();
  425.     rect->bottom -= sbr.bottom+1;
  426.   }
  427.   return true;
  428. }
  429.  
  430. //
  431. // Let the server know that we can handle border adornments on all four edges
  432. //
  433. bool
  434. TOleFrame::EvOcAppBorderSpaceReq(TRect far* /*space*/)
  435. {
  436.   return true;
  437. }
  438.  
  439. //
  440. // Actually create space on the requested edges for the server's adornments
  441. //
  442. bool
  443. TOleFrame::EvOcAppBorderSpaceSet(TRect far* space)
  444. {
  445.   // Resize pad decorations based on edges requested
  446.   //
  447.   int* edges = (int*)space;   // treat space as array of 4 int edges
  448.   bool needLayout = false;
  449.   for (int i = 0; i < 4; i++) {
  450.     TWindow*  pad = ChildWithId(IDW_PADDECORATION+i);
  451.     if (pad) {
  452.       int edge = edges && edges[i] ? edges[i]+1 : 1;
  453.       if (i%1 == 0 && pad->Attr.W != edge ||   // left & right edge
  454.           i%1 == 1 && pad->Attr.H != edge) {   // top & bottom edge
  455.         TLayoutMetrics m;
  456.         GetChildLayoutMetrics(*pad, m);
  457.         pad->Attr.H = pad->Attr.W = edge;  // set both axis, one will be stretched
  458.         SetChildLayoutMetrics(*pad, m);
  459.         needLayout = true;
  460.       }
  461.     }
  462.   }
  463.  
  464.   // Turn on/off control bar as needed
  465.   //
  466.   TWindow*  tb = ChildWithId(IDW_TOOLBAR);
  467.   if (tb)
  468.     if (space && tb->IsWindowVisible() || !space && !tb->IsWindowVisible()) {
  469.       SendMessage(WM_COMMAND, IDW_TOOLBAR);  // toggle tool bar on/off
  470.       needLayout = false;  // layout already done now by decorated frame.
  471.     }
  472.  
  473.   // Now do layout once at the end to reduce repaint
  474.   //
  475.   if (needLayout)
  476.     Layout();
  477.  
  478.   return true;
  479. }
  480.  
  481. //
  482. // Display the servers status messages on our status bar
  483. //
  484. void
  485. TOleFrame::EvOcAppStatusText(const char far* text)
  486. {
  487.   TMessageBar* mb = TYPESAFE_DOWNCAST(ChildWithId(IDW_STATUSBAR), TMessageBar);
  488.   if (mb) {
  489.     //mb->SetHintText(text);   // is the text a hint, or general status??
  490. #if defined(BI_DATA_NEAR)
  491.     mb->SetText(string(text).c_str());
  492. #else
  493.     mb->SetText(text);
  494. #endif
  495.   }
  496. }
  497.  
  498. //
  499. // Save off the popup menu handles that are copies so that we can destroy
  500. // them later. Keep track of active object menus, to allow cleanup when
  501. // the last one goes away.
  502. //
  503. void TOleFrame::StashContainerPopups(const TMenuDescr& shMenuDescr)
  504. {
  505.   StashCount++;
  506.  
  507.   int m = 0;
  508.   for (int i = 0; i < 6; i++) {
  509.     if (i%2 == 0)
  510.       for (int j = 0; j < shMenuDescr.GetGroupCount(i); j++) {
  511.         uint  state = shMenuDescr.GetMenuState(m+j, MF_BYPOSITION);
  512.         if (state == uint(-1))
  513.           continue;
  514.         TRACEX(OwlOleMenu, 1, "Stashing " << hex << (uint)shMenuDescr.GetSubMenu(m+j));
  515.         StashedContainerPopups.AppendMenu(state, TMenu(shMenuDescr.GetSubMenu(m+j)), "");
  516.       }
  517.     m += shMenuDescr.GetGroupCount(i);
  518.   }
  519. }
  520.  
  521. //
  522. // Throw away our popup copies that are no longer needed, when the last active
  523. // object is deactivated.
  524. //
  525. void TOleFrame::DestroyStashedPopups()
  526. {
  527.   if (--StashCount)
  528.     return;
  529.  
  530.   while (StashedContainerPopups.GetMenuItemCount()) {
  531.     TRACEX(OwlOleMenu, 1, "Destroying " << hex << (uint)StashedContainerPopups.GetSubMenu(0));
  532.     StashedContainerPopups.DeleteMenu(0, MF_BYPOSITION);
  533.   }
  534. }
  535.  
  536. //
  537. // Restore the UI back to pre-inplace server state. Remove the border space pads
  538. // and restore the menu.
  539. //
  540. void
  541. TOleFrame::EvOcAppRestoreUI()
  542. {
  543.   // Only restore the old menu if we are holding a merged one
  544.   //
  545.   if (HOldMenu) {
  546.     TRACEX(OwlOleMenu, 0, "EvOcAppRestoreUI resetting Old " << hex <<
  547.            (uint)HOldMenu);
  548.     TMenu oleMenu(*this);
  549.     SetMenu(HOldMenu);    // assumes we are just restoring the old owl menu
  550.     HOldMenu = 0;
  551.   }
  552.  
  553.   // Remove pad decorations & restore our toobar if we have one
  554.   //
  555.   EvOcAppBorderSpaceSet(0);
  556. }
  557.  
  558. //
  559. // Called by TOcRemView::Close when last embedding is closed
  560. // If that's the only reason the app is up we need to shut ourselves down
  561. //
  562. bool
  563. TOleFrame::EvOcAppShutdown()
  564. {
  565.   // If TOleFrame was created purely for embedded server, then
  566.   // we want to shut down the app when nobody is using the server.
  567.   // The amEmbedding flag will be set to false if user created normal
  568.   // document in this frame.
  569.   //
  570.   if (OcShutDown == DontCare && OcApp->IsOptionSet(amEmbedding)) {
  571.     // The shut down is initiated by OCF
  572.     //
  573.     OcShutDown = ServerInitiated;
  574.  
  575.     // Post frame close to kill the app later
  576.     //
  577.     PostMessage(WM_CLOSE);
  578.  
  579.     return true;
  580.   }
  581.   else {
  582.  
  583.     // If the last view closing caused the ocapp to shutdown, then close this
  584.     // frame.
  585.     //
  586.     if (OcApp->IsOptionSet(amEmbedding) && OcShutDown == ViewInitiated)
  587.       PostMessage(WM_CLOSE);
  588.  
  589.     return false; // Shut down initiated by user
  590.   }
  591. }
  592.