home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / atl / activedoc / menu.h < prev    next >
C/C++ Source or Header  |  1998-03-26  |  5KB  |  188 lines

  1. // menu.h : menu merging implementation
  2. //
  3. // This is a part of the Active Template Library.
  4. // Copyright (C) 1996-1998 Microsoft Corporation
  5. // All rights reserved.
  6. //
  7. // This source code is only intended as a supplement to the
  8. // Active Template Library Reference and related
  9. // electronic documentation provided with the library.
  10. // See these sources for detailed information regarding the
  11. // Active Template Library product.
  12.  
  13. template <class T>
  14. class CMenu
  15. {
  16. public:
  17.     void InPlaceMenuCreate()
  18.     {
  19.         IOleInPlaceFrame*   pFrame;
  20.         HRESULT             hr;
  21.         HMENU               hOurMenu;
  22.         OLEMENUGROUPWIDTHS  mgw;
  23.         T* pT = static_cast<T*>(this);
  24.  
  25.         if (pT->m_spInPlaceFrame == NULL)
  26.         {
  27.             // We weren't given an IOleInPlaceFrame pointer, so
  28.             // we'll have to get it ourselves.
  29.             OLEINPLACEFRAMEINFO frameInfo;
  30.             RECT rcPos, rcClip;
  31.             CComPtr<IOleInPlaceUIWindow> spInPlaceUIWindow;
  32.             frameInfo.cb = sizeof(OLEINPLACEFRAMEINFO);
  33.             pT->m_spInPlaceSite->GetWindowContext(&pFrame,
  34.                 &spInPlaceUIWindow, &rcPos, &rcClip, &frameInfo);
  35.         }
  36.         else
  37.             pFrame = pT->m_spInPlaceFrame;
  38.  
  39.         ZeroMemory(&mgw, sizeof(OLEMENUGROUPWIDTHS));
  40.  
  41.         // Create a blank menu and ask the container to add
  42.         // its menus into the OLEMENUGROUPWIDTHS structure
  43.         m_hMenuShared = ::CreateMenu();
  44.         hr = pFrame->InsertMenus(m_hMenuShared, &mgw);
  45.         if (FAILED(hr))
  46.         {
  47.             ::DestroyMenu(m_hMenuShared);
  48.             m_hMenuShared = NULL;
  49.             return;
  50.         }
  51.  
  52.         // Insert our menus
  53.         hOurMenu = LoadMenu(_Module.GetResourceInstance(),
  54.             MAKEINTRESOURCE(IDR_MAINMENU));
  55.         MergeMenus(m_hMenuShared, hOurMenu, &mgw.width[0], 1);
  56.         DestroyMenu(hOurMenu);
  57.  
  58.         // Send the menu to the client
  59.         m_hOleMenu = (HMENU)OleCreateMenuDescriptor(m_hMenuShared, &mgw);
  60.         pFrame->SetMenu(m_hMenuShared, m_hOleMenu, pT->m_hWnd);
  61.  
  62.         // If we got the IOleInPlaceFrame pointer ourselves
  63.         // we have to release it
  64.         if (pT->m_spInPlaceFrame == NULL)
  65.             pFrame->Release();
  66.     }
  67.  
  68.     void InPlaceMenuDestroy()
  69.     {
  70.         T* pT = static_cast<T*>(this);
  71.         CComPtr<IOleInPlaceFrame> spInPlaceFrame;
  72.         CComPtr<IOleInPlaceUIWindow> spInPlaceUIWindow;
  73.         OLEINPLACEFRAMEINFO frameInfo;
  74.         RECT rcPos, rcClip;
  75.  
  76.         // Get the clients IOleInPlaceFrame so we can ask
  77.         // it to remove its menu
  78.         pT->m_spInPlaceSite->GetWindowContext(&spInPlaceFrame,
  79.             &spInPlaceUIWindow, &rcPos, &rcClip, &frameInfo);
  80.         if (spInPlaceFrame)
  81.             spInPlaceFrame->SetMenu(NULL, NULL, NULL);
  82.  
  83.         OleDestroyMenuDescriptor(m_hOleMenu);
  84.         m_hOleMenu = NULL;
  85.  
  86.         HMENU hOurMenu = LoadMenu(_Module.GetResourceInstance(),
  87.             MAKEINTRESOURCE(IDR_MAINMENU));
  88.         UnmergeMenus(m_hMenuShared, hOurMenu);
  89.         DestroyMenu(hOurMenu);
  90.     }
  91.  
  92.     void MergeMenus(HMENU hMenuShared, HMENU hMenuSource, LONG* lpMenuWidths,
  93.         int nWidthIndex)
  94.     {
  95.         // Copy the popups from the pMenuSource
  96.         int nMenuItems = GetMenuItemCount(hMenuSource);
  97.         int nGroupWidth = 0;
  98.         int nPosition = 0;
  99.  
  100.         // Insert at appropriate spot depending on nWidthIndex
  101.         ATLASSERT(nWidthIndex == 0 || nWidthIndex == 1);
  102.         if (nWidthIndex == 1)
  103.             nPosition = (int)lpMenuWidths[0];
  104.  
  105.         for (int i = 0; i < nMenuItems; i++)
  106.         {
  107.             // Get the HMENU of the popup
  108.             HMENU hMenuPopup = ::GetSubMenu(hMenuSource, i);
  109.  
  110.             // Separators move us to next group
  111.             UINT state = GetMenuState(hMenuSource, i, MF_BYPOSITION);
  112.             if (hMenuPopup == NULL && (state & MF_SEPARATOR) != 0)
  113.             {
  114.                // Servers should not touch past 5
  115.                 ATLASSERT(nWidthIndex <= 5);
  116.                 lpMenuWidths[nWidthIndex] = nGroupWidth;
  117.                 nGroupWidth = 0;
  118.                 if (nWidthIndex < 5)
  119.                     nPosition += (int)lpMenuWidths[nWidthIndex+1];
  120.                 nWidthIndex += 2;
  121.             }
  122.             else
  123.             {
  124.                 // Get the menu item text
  125.                 TCHAR szItemText[256];
  126.                 int nLen = GetMenuString(hMenuSource, i, szItemText,
  127.                     sizeof szItemText, MF_BYPOSITION);
  128.  
  129.                 // Popups are handled differently than normal menu items
  130.                 if (hMenuPopup != NULL)
  131.                 {
  132.                     if (::GetMenuItemCount(hMenuPopup) != 0)
  133.                     {
  134.                         // Strip the HIBYTE because it contains a count of items
  135.                         state = LOBYTE(state) | MF_POPUP;   // Must be popup
  136.  
  137.                         // Non-empty popup -- add it to the shared menu bar
  138.                         InsertMenu(hMenuShared, nPosition, state | MF_BYPOSITION,
  139.                             (UINT)hMenuPopup, szItemText);
  140.                         ++nPosition;
  141.                         ++nGroupWidth;
  142.                     }
  143.                 }
  144.                 else if (nLen > 0)
  145.                 {
  146.                     // only non-empty items are added
  147.                     ATLASSERT(szItemText[0] != 0);
  148.  
  149.                     // here the state does not contain a count in the HIBYTE
  150.                     InsertMenu(hMenuShared, nPosition, state | MF_BYPOSITION,
  151.                         GetMenuItemID(hMenuSource, i), szItemText);
  152.                     ++nPosition;
  153.                     ++nGroupWidth;
  154.                 }
  155.             }
  156.         }
  157.     }
  158.  
  159.     void UnmergeMenus(HMENU hMenuShared, HMENU hMenuSource)
  160.     {
  161.         int cOurItems = GetMenuItemCount(hMenuSource);
  162.         int cMenuItems = GetMenuItemCount(hMenuShared);
  163.  
  164.         for (int i = cMenuItems-1; i >= 0; i--)
  165.         {
  166.             // Check the popup menus
  167.             HMENU hMenuPopup = ::GetSubMenu(hMenuShared, i);
  168.             if (hMenuPopup != NULL)
  169.             {
  170.                 // If it is one of ours, remove it from the hMenuShared
  171.                 for (int j = 0; j < cOurItems; j++)
  172.                 {
  173.                     if (::GetSubMenu(hMenuSource, j) == hMenuPopup)
  174.                     {
  175.                         // Remove the menu from hMenuShared
  176.                         RemoveMenu(hMenuShared, i, MF_BYPOSITION);
  177.                         break;
  178.                     }
  179.                 }
  180.             }
  181.         }
  182.     }
  183.  
  184. protected:
  185.     HMENU   m_hOleMenu;
  186.     HMENU   m_hMenuShared;
  187. };
  188.