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

  1. // ---------------------------------------------------------------------------
  2. // Copyright (C) 1994 Borland International
  3. // ---------------------------------------------------------------------------
  4. #include "ocfhlpr.h"
  5. #include "ocfhlpr.rh"
  6.  
  7. //
  8. // constants for menu enabling/disabling
  9. //
  10. const int MF_ON = MF_ENABLED;
  11. const int MF_OFF= MF_DISABLED|MF_GRAYED;
  12. const int MENU_GROUP_COUNT = 6;   // sizeof(TOcMenuDescr.Width) /
  13.                                   // sizeof(TOcMenuDescr.Width[0])
  14.  
  15. //
  16. // The TOcApp* pointer ...
  17. //
  18. static TOcApp*  TheOcApp = 0;
  19.  
  20.  
  21. //
  22. // Initializes OLE to use default IMalloc allocator.
  23. // Creates OCF helper objects
  24. //
  25. TOleInit::TOleInit(TRegList& regInfo,
  26.                    TComponentFactory callback,
  27.                    string& cmdLine, TRegLink* linkHead,
  28.                    HINSTANCE hInst) :
  29.           TOleAllocator(0), OcRegistrar(0), OcApp(TheOcApp)
  30. {
  31.   // Initialize OCF objects: Create TOcRegistrar & TOcApp
  32.   //
  33.   OcRegistrar = new TOcRegistrar(regInfo, callback, cmdLine,
  34.                                  linkHead, hInst);
  35.   OcRegistrar->CreateOcApp(OcRegistrar->GetOptions(), OcApp);
  36. }
  37.  
  38.  
  39. //
  40. // Cleans up the OCF helper objects
  41. //
  42. TOleInit::~TOleInit()
  43. {
  44.   // Free the Registrar
  45.   //
  46.   delete OcRegistrar;
  47. }
  48.  
  49.  
  50. //
  51. // Accessor to the OcApp helper object - used mainly by OLE Window
  52. //
  53. TOcApp*
  54. GetOcApp()
  55. {
  56.   return TheOcApp;
  57. }
  58.  
  59.  
  60. //
  61. // Constructor of object encapsulating an OLE Frame window
  62. //
  63. TOleFrameWin::TOleFrameWin(HWND hwnd) :
  64.   Hwnd(hwnd)
  65. {
  66. }
  67.  
  68.  
  69. //
  70. // Method to call when OLE Frame Window receives a WM_CREATE message
  71. //
  72. void
  73. TOleFrameWin::OnCreate()
  74. {
  75.   // Hand our frame HWND to OCF so it may send OLE notifications/requests
  76.   //
  77.   if (GetOcApp())
  78.     GetOcApp()->SetupWindow(Hwnd);
  79. }
  80.  
  81.  
  82. //
  83. // Method to call when OLE Frame Window receives a WM_DESTROY message
  84. //
  85. void
  86. TOleFrameWin::OnDestroy()
  87. {
  88.   // Release the OCF Application helper object
  89.   //
  90.   if (GetOcApp())
  91.     GetOcApp()->Release();
  92. }
  93.  
  94.  
  95. //
  96. // Method to call when OLE Frame Window receives a WM_ACTIVATEAPP message
  97. //
  98. void
  99. TOleFrameWin::OnActivateApp(bool active)
  100. {
  101.   GetOcApp()->EvActivate(active);
  102. }
  103.  
  104.  
  105. //
  106. // Constructor of object encapsulating an OLE Window
  107. // Simply initialize OCF Helper objects
  108. //
  109. TOleWin::TOleWin(HWND hwnd) : Hwnd(hwnd),
  110.                               Pos(0, 0, 0, 0),
  111.                               Embedded(false),
  112.                               ShowObjects(true)
  113. {
  114.   OcDoc     = 0;
  115.   OcView    = 0;
  116.   DragPart  = 0;
  117.  
  118.   //
  119.   // Init menu related variables
  120.   //
  121.   MergedMenu = 0;
  122.   HMenu      = 0;
  123.   memset(Width, 0, sizeof(Width));
  124. }
  125.  
  126.  
  127. //
  128. // Method to call when OLE Window receives a WM_CREATE message
  129. //
  130. void
  131. TOleWin::OnCreate()
  132. {
  133.   // Create OCF Document/View pair associated with each OLE Window
  134.   //
  135.   OcDoc  = new TOcDocument(*GetOcApp());
  136.   OcView = new TOcView(*OcDoc);
  137.  
  138.   // Hand OCF our window handle so it may send OLE notifications/requests
  139.   //
  140.   if (OcView)
  141.     OcView->SetupWindow(Hwnd);
  142. }
  143.  
  144.  
  145. //
  146. // Method to call when OLE Window receives a WM_DESTROY message
  147. //
  148. void
  149. TOleWin::OnDestroy()
  150. {
  151.   // Deactivate the embedded parts
  152.   //
  153.   for (TOcPartCollectionIter i(OcDoc->GetParts()); i; i++) {
  154.     TOcPart& p = *i.Current();
  155.     p.Activate(false);
  156.   }
  157.  
  158.   // Release the OCF View helper object
  159.   //
  160.   if (OcView)
  161.     OcView->ReleaseObject();
  162.  
  163.   // Close the OCF document helper object
  164.   //
  165.   if (OcDoc)
  166.     OcDoc->Close();
  167.  
  168.   // Delete the OCF document helper object
  169.   //
  170.   delete OcDoc;
  171. }
  172.  
  173.  
  174. //
  175. // Method to call when OLE Window receives a WM_SIZE message
  176. //
  177. void
  178. TOleWin::OnSize()
  179.  
  180. {
  181.   // Inform the OCF View helper that we've been resized
  182.   //
  183.   if (OcView)
  184.     OcView->EvResize();
  185. }
  186.  
  187.  
  188. //
  189. // Method to call when OLE Window receives a WM_PAINT message.
  190. // Asks parts to draw themselves
  191. //
  192. void
  193. TOleWin::OnPaint(HDC dc, PAINTSTRUCT& ps)
  194. {
  195.   bool metafile = GetDeviceCaps(dc, TECHNOLOGY) == DT_METAFILE;
  196.   SetupDC(dc, !metafile);
  197.  
  198.   PaintParts(dc, ps.fErase, TRect(ps.rcPaint), metafile);
  199. }
  200.  
  201.  
  202. //
  203. // Method to call when OLE Window receives a WM_COMMAND with an
  204. // id it does not care for. This method handles the various
  205. // OLE UI commands such as InsertObject or PasteSpecial
  206. //
  207. bool
  208. TOleWin::OnCommand(uint cmdID)
  209. {
  210.   switch (cmdID) {
  211.     case CM_EDITINSERTOBJECT:
  212.       EditInsertObject();
  213.       break;
  214.  
  215.     case CM_EDITPASTESPECIAL:
  216.       EditPasteSpecial();
  217.       break;
  218.  
  219.     case CM_EDITCONVERT:
  220.       EditConvert();
  221.       break;
  222.  
  223.     case CM_EDITLINKS:
  224.       EditLinks();
  225.       break;
  226.  
  227.     case CM_EDITSHOWOBJECTS:
  228.       ShowObjects = !ShowObjects;
  229.       InvalidateRect(Hwnd, 0, TRUE);
  230.       break;
  231.  
  232.     default:
  233.       return false;       // We did not handle the command!
  234.   }
  235.   return true;            // We handled the command
  236. }
  237.  
  238.  
  239. //
  240. //
  241. //
  242. void
  243. TOleWin::OnInitMenu(HMENU hMenu)
  244. {
  245.  
  246.   EnableMenuItem(hMenu, CM_EDITINSERTOBJECT, MF_BYCOMMAND |
  247.                  ((GetOcApp() && GetOcView()) ? MF_ON : MF_OFF));
  248.   EnableMenuItem(hMenu, CM_EDITCONVERT,
  249.               MF_BYCOMMAND|((DragPart != 0) ? MF_ON : MF_OFF));
  250.  
  251.   uint mask = GetOcApp()->EnableEditMenu(meEnablePaste |
  252.                                          meEnablePasteLink |
  253.                                          meEnableBrowseClipboard |
  254.                                          meEnableBrowseLinks,
  255.                                          GetOcView());
  256.  
  257.   EnableMenuItem(hMenu, CM_EDITPASTE,
  258.               MF_BYCOMMAND|((mask & meEnablePaste) ? MF_ON : MF_OFF));
  259.   EnableMenuItem(hMenu, CM_EDITPASTELINK,
  260.               MF_BYCOMMAND|((mask & meEnablePasteLink) ? MF_ON : MF_OFF));
  261.   EnableMenuItem(hMenu, CM_EDITPASTESPECIAL,
  262.               MF_BYCOMMAND|((mask & meEnableBrowseClipboard) ? MF_ON : MF_OFF));
  263.   EnableMenuItem(hMenu, CM_EDITLINKS,
  264.               MF_BYCOMMAND|((mask & meEnableBrowseLinks) ? MF_ON : MF_OFF));
  265.  
  266.   CheckMenuItem(hMenu, CM_EDITSHOWOBJECTS,
  267.                 MF_BYCOMMAND |(ShowObjects ? MF_CHECKED : MF_UNCHECKED));
  268. }
  269.  
  270.  
  271. //
  272. // Method to call when OLE Window receives a WM_INITMENUPOPUP message
  273. // (which is typically a hand-down from the frame window).
  274. // Method takes care of enabling/disabling/checking etc. OLE related
  275. // commands.
  276. //
  277. void
  278. TOleWin::OnInitMenuPopup(HMENU hMenu, int /*item*/)
  279. {
  280.   OnInitMenu(hMenu);
  281. }
  282.  
  283.  
  284. //
  285. // Method to call when OLE Window receives a WM_LBUTTONDOWN message.
  286. // Deactivates any active parts.
  287. //
  288. bool
  289. TOleWin::OnLButtonDown(int /*x*/, int /*y*/, UINT /*keyFlags*/)
  290. {
  291.   if (Deactivate())
  292.     return true;        // We handled the message...
  293.  
  294.   return false;
  295. }
  296.  
  297.  
  298. //
  299. // Method to call when OLE Window receives an WM_LBUTTONDBLCLK message.
  300. // Activates the part if the mouse was clicked on an inactivate part.
  301. //
  302. bool
  303. TOleWin::OnLButtonDblClk(int x, int y, UINT modKeys)
  304. {
  305.   TPoint point(x, y);
  306.   OleClientDC dc(*this);
  307.   DPtoLP(dc, &point, 1);
  308.  
  309.   TOcPart* p = GetOcDoc()->GetParts().Locate(point);
  310.  
  311.   if (modKeys & MK_CONTROL) {
  312.     if (p)
  313.       p->Open(true);
  314.   } else {
  315.     SetSelection(p);
  316.  
  317.     if (p && p == GetOcView()->GetActivePart())
  318.       p->Activate(false);
  319.  
  320. #if !defined(BOLE_ACTIVATE)
  321.     GetOcView()->ActivatePart(p);
  322. #else
  323.     if (p)
  324.       p->Activate(true);
  325. #endif
  326.   }
  327.  
  328.   return true;
  329. }
  330.  
  331.  
  332. //
  333. // Method to call when OLE window receives a WM_ACTIVATE or
  334. // WM_MDIACTIVATE message.
  335. //
  336. void
  337. TOleWin::OnActivate(bool active)
  338. {
  339.   GetOcView()->EvActivate(active);
  340. }
  341.  
  342.  
  343. //
  344. //
  345. //
  346. void
  347. TOleWin::OnSetFocus(HWND /*hwndLostFocus*/)
  348. {
  349.   GetOcView()->EvSetFocus(true);
  350. }
  351.  
  352.  
  353. //
  354. // Method to call when OLE Window receives a WM_RBUTTONDOWN message.
  355. // Implements the Local Object menu (with VERBS) if the mouse was
  356. // clicked on a part.
  357. //
  358. bool
  359. TOleWin::OnRButtonDown(int /*x*/, int /*y*/, uint /*keyFlags*/)
  360. {
  361.   return true;
  362. }
  363.  
  364.  
  365. //
  366. // Method to call when OLE Window receives a WM_OCEVENT message.
  367. // This method invokes a separate handler for the various OCF
  368. // events. These in turn provide various default behaviours.
  369. //
  370. LRESULT
  371. TOleWin::OnOcEvent(WPARAM wParam, LPARAM lParam)
  372. {
  373.   switch (wParam) {
  374.     case OC_VIEWTITLE:
  375.          return (LRESULT)OnOcViewTitle();
  376.  
  377.     case OC_VIEWSETTITLE:
  378.          OnOcViewSetTitle((const char far*)lParam);
  379.          return (LRESULT)true;
  380.  
  381.     case OC_VIEWSETSITERECT:
  382.          return (LRESULT)OnOcViewSetSiteRect((TRect far*)lParam);
  383.  
  384.     case OC_VIEWGETSCALE:
  385.          return (LRESULT)OnOcViewGetScale((TOcScaleFactor far*)lParam);
  386.  
  387.     case OC_VIEWPARTINVALID:
  388.          return (LRESULT)OnOcViewPartInvalid((TOcPartChangeInfo far*)lParam);
  389.  
  390.     case OC_VIEWGETSITERECT:
  391.           return (LRESULT)OnOcViewGetSiteRect((TRect far*)lParam);
  392.  
  393.     case OC_VIEWDROP:
  394.          return OnOcViewDrop((TOcDragDrop far*)lParam);
  395.  
  396.     default:
  397.       return LRESULT(false);
  398.   }
  399. }
  400.  
  401.  
  402. const char*
  403. TOleWin::OnOcViewTitle()
  404. {
  405.   static char title[100];
  406.  
  407.   if (IsWindow(Hwnd)) {
  408.     GetWindowText(Hwnd, title, sizeof(title));
  409.   }
  410.   return title;
  411. }
  412.  
  413.  
  414. void
  415. TOleWin::OnOcViewSetTitle(const char far* text)
  416. {
  417.   if (IsWindow(Hwnd))
  418.     SetWindowText(Hwnd, text);
  419. }
  420.  
  421.  
  422. bool
  423. TOleWin::OnOcViewGetScale(TOcScaleFactor* scaleInfo)
  424. {
  425.   if (scaleInfo)
  426.     *scaleInfo = Scale;
  427.  
  428.   return true;
  429. }
  430.  
  431.  
  432. bool
  433. TOleWin::OnOcViewSetSiteRect(TRect far* rect)
  434. {
  435.   OleClientDC dc(*this);
  436.   return DPtoLP(dc, (POINT*)rect, 2);
  437. }
  438.  
  439.  
  440. bool
  441. TOleWin::OnOcViewGetSiteRect(TRect far* rect)
  442. {
  443.   OleClientDC dc(*this);
  444.   return LPtoDP(dc, (POINT*)rect, 2);
  445.  
  446. }
  447.  
  448.  
  449. bool
  450. TOleWin::OnOcViewPartInvalid(TOcPartChangeInfo far* changeInfo)
  451. {
  452.   TRect rect(changeInfo->GetPart()->GetRect());
  453.   rect.right++;
  454.   rect.bottom++;
  455.  
  456.   OleClientDC dc(*this);
  457.   LPtoDP(dc, (TPoint*)&rect, 2);
  458.   InvalidateRect(Hwnd, &rect, true);
  459.   InvalidatePart((TOcInvalidate)changeInfo->GetType());
  460.   return true;
  461. }
  462.  
  463.  
  464. bool
  465. TOleWin::OnOcViewDrop(TOcDragDrop far*)
  466. {
  467.   //
  468.   // Answer positively: we'll take any drop
  469.   //
  470.   return true;
  471. }
  472.  
  473.  
  474. //
  475. // Displays the InsertObject dialog and allows user to
  476. // embed an object [newly created or created from file]
  477. //
  478. void
  479. TOleWin::EditInsertObject()
  480. {
  481.   try {
  482.     TOcInitInfo initInfo(OcView);
  483.     if (GetOcApp()->Browse(initInfo)) {
  484.       TRect rect;
  485.       GetInsertPosition(rect);
  486.       SetSelection(new TOcPart(*GetOcDoc(), initInfo, rect));
  487.  
  488.       OcView->Rename();
  489.       InvalidatePart(invView);
  490.     }
  491.   }
  492.   catch (TXBase& xbase) {
  493.     MessageBox(Hwnd, xbase.why().c_str(), "EXCEPTION: InsertObject", MB_OK);
  494.   }
  495. }
  496.  
  497.  
  498. //
  499. // Displays PasteSpecial dialog and allows use to paste/pasteLink
  500. // object current on the clipboard.
  501. //
  502. void
  503. TOleWin::EditPasteSpecial()
  504. {
  505.   try {
  506.     TOcInitInfo initInfo(GetOcView());
  507.  
  508.     if (GetOcView()->BrowseClipboard(initInfo)) {
  509.       TRect rect;
  510.       GetInsertPosition(rect);
  511.       new TOcPart(*GetOcDoc(), initInfo, rect);
  512.       initInfo.ReleaseDataObject();
  513.     }
  514.   }
  515.   catch (TXBase& xbase) {
  516.     MessageBox(Hwnd, xbase.why().c_str(), "EXCEPTION: PasteSpecial", MB_OK);
  517.   }
  518. }
  519.  
  520.  
  521. void
  522. TOleWin::EditConvert()
  523. {
  524.   GetOcApp()->Convert(DragPart, false);
  525. }
  526.  
  527.  
  528. void
  529. TOleWin::EditLinks()
  530. {
  531.   GetOcView()->BrowseLinks();
  532. }
  533.  
  534.  
  535. //
  536. //
  537. //
  538. bool
  539. TOleWin::SelectEmbedded()
  540. {
  541.   return DragPart != 0;
  542. }
  543.  
  544.  
  545. void
  546. TOleWin::InvalidatePart(TOcInvalidate invalid)
  547. {
  548.   if (GetOcRemView())
  549.     GetOcRemView()->Invalidate(invalid);
  550. }
  551.  
  552.  
  553. //
  554. //
  555. //
  556. bool
  557. TOleWin::Deactivate()
  558. {
  559.   if (DragPart && DragPart->IsActive()) {
  560.     SetSelection(0);
  561.     return true;
  562.   } else {
  563.     return false;
  564.   }
  565. }
  566.  
  567.  
  568. //
  569. //
  570. //
  571. void
  572. TOleWin::SetSelection(TOcPart* part)
  573. {
  574.   if (part == DragPart)
  575.     return;
  576.  
  577.   // Invalidate old part
  578.   //
  579.   TOcPartChangeInfo changeInfo(DragPart, invView);
  580.   if (DragPart) {
  581.     DragPart->Select(false);
  582. #if !defined(BOLE_ACTIVATE)
  583.     DragPart->Activate(false);
  584. #endif
  585.     OnOcViewPartInvalid(&changeInfo);
  586.   }
  587.  
  588.   // Select and invalidate new one
  589.   //
  590.   DragPart = part;
  591.   changeInfo.SetPart(DragPart);
  592.   if (DragPart) {
  593.     part->Select(true);
  594.     OnOcViewPartInvalid(&changeInfo);
  595.   }
  596. }
  597.  
  598.  
  599. //
  600. //
  601. //
  602. void
  603. TOleWin::GetInsertPosition(TRect& rect)
  604. {
  605.   OleClientDC dc(*this);
  606.  
  607.   // Default to 0.5" from viewport origin
  608.   //
  609.   rect.left  = rect.top = 0;
  610.   rect.right = GetDeviceCaps(dc, LOGPIXELSX) >> 1;
  611.   rect.bottom= GetDeviceCaps(dc, LOGPIXELSY) >> 1;
  612.  
  613.   LPtoDP(dc, (TPoint*)&rect, 2);
  614.  
  615.   // Embedded rect is in pixel
  616.   //
  617.   rect.left  = rect.Width();
  618.   rect.top   = rect.Height();
  619.   rect.right = rect.bottom = 0;
  620. }
  621.  
  622.  
  623. //
  624. // Get the logical unit per inch for document
  625. //
  626. void
  627. TOleWin::GetLogPerUnit(TSize& logPerUnit)
  628. {
  629.   HDC dc = GetWindowDC(0);  // Screen DC
  630.   logPerUnit.cx = GetDeviceCaps(dc, LOGPIXELSX);
  631.   logPerUnit.cy = GetDeviceCaps(dc, LOGPIXELSY);
  632.   ReleaseDC(0, dc);
  633. }
  634.  
  635.  
  636. void
  637. TOleWin::SetupDC(HDC dc, bool scale)
  638. {
  639.   SetMapMode(dc, MM_ANISOTROPIC);
  640.  
  641.   TPoint scrollPos(0, 0);
  642.  
  643.   // Adjust for scrolling here
  644.   //
  645.  
  646.   SetWindowOrgEx(dc, scrollPos.x, scrollPos.y, 0);
  647.  
  648.  
  649.   if (!scale)
  650.     return;
  651.  
  652.   SetViewportOrgEx(dc, Pos.left, Pos.top, 0);
  653.  
  654.   //
  655.   //
  656.   //
  657.   TSize ext;
  658.   GetLogPerUnit(ext);
  659.   SetWindowExtEx(dc, ext.cx, ext.cy, 0);
  660.  
  661.   ext.cx = GetDeviceCaps(dc, LOGPIXELSX);
  662.   ext.cy = GetDeviceCaps(dc, LOGPIXELSY);
  663.  
  664.  
  665.   ext.cx = (int)(((uint32)ext.cx * Scale.SiteSize.cx + (Scale.PartSize.cx >> 1)) /
  666.                 Scale.PartSize.cx);
  667.   ext.cy = (int)(((uint32)ext.cy * Scale.SiteSize.cy + (Scale.PartSize.cy >> 1)) /
  668.                 Scale.PartSize.cy);
  669.  
  670.   SetViewportExtEx(dc, ext.cx, ext.cy, 0);
  671. }
  672.  
  673.  
  674. bool
  675. TOleWin::PaintParts(HDC dc, bool, TRect&, bool metafile)
  676. {
  677.   TRect clientRect;
  678.   TRect logicalRect;
  679.  
  680.   GetClientRect(Hwnd, &logicalRect);
  681.  
  682.   if (!IsEmbedded())
  683.     clientRect = logicalRect;
  684.   else {
  685.     GetWindowRect(Hwnd, &clientRect);
  686.     clientRect.Offset(-clientRect.left, -clientRect.top);
  687.   }
  688.  
  689.   TPoint scrollPos(0, 0);
  690.  
  691.   if (!metafile)
  692.     DPtoLP(dc, (TPoint*)&logicalRect, 2);
  693.  
  694.   for (TOcPartCollectionIter i(GetOcDoc()->GetParts()); i; i++) {
  695.     TOcPart& p = *i.Current();
  696.     if (p.IsVisible(logicalRect) || metafile) {
  697.       TRect r = p.GetRect();
  698.       r.Offset(-scrollPos.x, -scrollPos.y);
  699.       p.Draw(dc, r, clientRect, asDefault);
  700.  
  701.       if (metafile)
  702.         continue;
  703.  
  704.       // Paint selection
  705.       //
  706.       // >> Can draw selection (eg. XOR rectangle here)
  707.     }
  708.   }
  709.  
  710.   return true;
  711. }
  712.  
  713.  
  714. //
  715. // Sets and returns previous user-defined pointer which
  716. // can be stored along with the OCF helper.
  717. //
  718. void*
  719. TOleWin::SetUserInfo(void* ui)
  720. {
  721.   void* previous = UserInfo;
  722.   UserInfo = ui;
  723.   return previous;
  724. }
  725.  
  726.  
  727. //
  728. // Hands a menu handle and menu description to the OCF helper
  729. // object so the latter can handle OLE menu merging on behalf
  730. // of the window.
  731. //
  732. void
  733. TOleWin::SetWinMenu(const TOcMenuDescr& menuDescr)
  734. {
  735.   HMenu = menuDescr.HMenu;
  736.   if (HMenu)
  737.     memcpy(Width, menuDescr.Width, sizeof(Width));
  738.   else
  739.     memset(Width, 0, sizeof(Width));
  740. }
  741.  
  742.  
  743. //
  744. // Merge the container's menu in OLE's menu handle
  745. //
  746. bool
  747. TOleWin::OnOcAppInsMenus(TOcMenuDescr far* sharedMenu)
  748. {
  749.   //
  750.   // If we don't have a menu handle to merge, return false
  751.   //
  752.   if (!HMenu)
  753.     return false;
  754.  
  755.   //
  756.   // If we've merged into OLE's menu already, don't bother remerging
  757.   //
  758.   if(MergedMenu)
  759.     return true;
  760.  
  761.   //
  762.   // Merge the container menu in OLE's menu
  763.   //
  764.   MergeContainerMenu(*sharedMenu, *this);
  765.   return true;
  766.  
  767. }
  768.  
  769.  
  770. //
  771. // Handles OC_APPMENUS, a request to set a new menu bar
  772. // We return the handle so the frame may set the menu.
  773. //
  774. HMENU
  775. TOleWin::OnOcAppMenus(TOcMenuDescr far* menuDescr)
  776. {
  777.   //
  778.   // If OLE does not pass a handle, hand our original menu
  779.   //
  780.   if (!menuDescr->HMenu) {
  781.     MergedMenu = 0;
  782.     return HMenu;
  783.   }
  784.  
  785.   return MergedMenu ? MergedMenu : menuDescr->HMenu;
  786. }
  787.  
  788.  
  789. //
  790. //
  791. //
  792. HMENU
  793. TOleWin::OnOcAppRestoreUI()
  794. {
  795.   MergedMenu = 0;
  796.   return HMenu;
  797. }
  798.  
  799.  
  800. //
  801. // Merges source menu popups into the destination menu.
  802. // SrcOwnsEven determines whether the source or destination
  803. // own the even or odd entries within the menu.
  804. //
  805. static bool
  806. MergeMenu(MenuDescr& dst, const MenuDescr& src, bool srcOwnsEven)
  807. {
  808.   int dstOff = 0;
  809.   int srcOff = 0;
  810.  
  811.   for (int i=0; i<MENU_GROUP_COUNT; i++) {
  812.     if ((!(i%2) && srcOwnsEven) || ((i%2) && !srcOwnsEven)) {
  813.       // If the current location is owned by the source, there should
  814.       // not be anything there from the destination already.
  815.       //
  816.       if (dst.Width[i]) {
  817.         // However, if the entries are occupied,
  818.         // should they be removed/deleted - or should we just append ours?
  819.         //
  820.       }
  821.  
  822.       // If source has something to merge
  823.       //
  824.       if (src.Width[i]) {
  825.         // Iterate through the source's menu items
  826.         //
  827.         int insertCount = 0;
  828.         for (int j=0; j<src.Width[i]; j++) {
  829.           uint state = GetMenuState(src, srcOff+j, MF_BYPOSITION);
  830.  
  831.           // Validate source menu item
  832.           //
  833.           if (state == uint(-1))
  834.             break;
  835.  
  836.           // Retrieve string
  837.           //
  838.           char str[256];
  839.           GetMenuString(src, srcOff+j, str, sizeof(str), MF_BYPOSITION);
  840.  
  841.           // If it's a popup, we'll share the handle
  842.           //
  843.           uint idOrPopup = 0;
  844.           if (state & MF_POPUP) {
  845.             state &= (MF_STRING|MF_POPUP);
  846.             HMENU sub = GetSubMenu(src, srcOff+j);
  847.             idOrPopup = UINT(sub);
  848.           } else {
  849.             idOrPopup = GetMenuItemID(src, srcOff+j);
  850.           }
  851.  
  852.           // Insert destination menu
  853.           //
  854.           if (GetMenuItemCount(dst) <= dstOff+j)
  855.             AppendMenu(dst, state|MF_BYPOSITION, idOrPopup, str);
  856.           else
  857.             InsertMenu(dst, dstOff+j, state|MF_BYPOSITION, idOrPopup, str);
  858.  
  859.           insertCount++;
  860.         }
  861.  
  862.         // Update dst. width by # of new entries we've added
  863.         //
  864.         dst.Width[i] += insertCount;
  865.       }
  866.     } else {
  867.       // Here, if src.Width[i] == -1, we could delete the destinations entries
  868.       //
  869.     }
  870.  
  871.     // Update offset by width of entries just processed.
  872.     //
  873.     srcOff += src.Width[i];
  874.     dstOff += dst.Width[i];
  875.   }
  876.  
  877.   return true;
  878. }
  879.  
  880.  
  881. //
  882. // Merge so that source (container) owns the even entries
  883. //
  884. bool
  885. MergeContainerMenu(TOcMenuDescr& dst, const TOcMenuDescr& src)
  886. {
  887.   return MergeMenu(*((MenuDescr*)&dst), *((MenuDescr*)&src), true);
  888. }
  889.  
  890.  
  891. //
  892. // Merge so that source (server) owns the odd entries
  893. //
  894. bool
  895. MergeServerMenu(TOcMenuDescr& dst, const TOcMenuDescr& src)
  896. {
  897.   return MergeMenu(*((MenuDescr*)&dst), *((MenuDescr*)&src), false);
  898. }
  899.  
  900.  
  901. //
  902. // Prompts user for a filename using Common Dialog
  903. //
  904. bool
  905. GetOpenFileName(HWND owner, const char* filter, char* fileName,
  906.                 int size, DWORD flags)
  907. {
  908.    OPENFILENAME ofn;
  909.    memset(&ofn, 0, sizeof(ofn));
  910.    ofn.lStructSize   = sizeof(ofn);
  911.    ofn.hwndOwner     = owner;
  912.    ofn.lpstrFilter   = filter;
  913.    ofn.lpstrFile     = fileName;
  914.    ofn.nMaxFile      = size;
  915.    ofn.Flags         = flags;
  916.    return GetOpenFileName(&ofn);
  917. }
  918.  
  919.  
  920. //
  921. // Prompts user for a filename using Common Dialog
  922. //
  923. bool
  924. GetSaveFileName(HWND owner, const char* filter, char* fileName,
  925.                 int size, DWORD flags)
  926. {
  927.    OPENFILENAME ofn;
  928.    memset(&ofn, 0, sizeof(ofn));
  929.    ofn.lStructSize   = sizeof(ofn);
  930.    ofn.hwndOwner     = owner;
  931.    ofn.lpstrFilter   = filter;
  932.    ofn.lpstrFile     = fileName;
  933.    ofn.nMaxFile      = size;
  934.    ofn.Flags         = flags;
  935.    return GetSaveFileName(&ofn);
  936. }
  937.  
  938.