home *** CD-ROM | disk | FTP | other *** search
- // mfcbind.cpp : Example of Binder-compatible utility functions
- //
- // This is a part of the Microsoft Foundation Classes C++ library.
- // Copyright (C) 1992-1995 Microsoft Corporation
- // All rights reserved.
- //
- // This source code is only intended as a supplement to the
- // Microsoft Foundation Classes Reference and related
- // electronic documentation provided with the library.
- // See these sources for detailed information regarding the
- // Microsoft Foundation Classes product.
-
- //BINDER:
- // This module contains functions specific to Binder support.
- // The code here is used to add special registry entries used by
- // Binder-Compatible DocObjects, in addition to registering
- // the standard entries generated by the MFC libraries.
- //
- // The following keys are written only if no existing entries
- // are found:
- // HKEY_CLASSES_ROOT\<ProgID>\DocObject
- // HKEY_CLASSES_ROOT\CLSID\<clsid>\DocObject
- // HKEY_CLASSES_ROOT\CLSID\<clsid>\Printable
- //
- // The following keys will overwrite any existing values:
- // HKEY_CLASSES_ROOT\CLSID\<clsid>\DefaultExtension
- //BINDER_END
-
- #include "stdafx.h"
- #include "mfcbind.h"
- #include <afxpriv.h> // for conversion helpers
-
- #ifdef _DEBUG
- #undef THIS_FILE
- static char BASED_CODE THIS_FILE[] = __FILE__;
- #endif
-
- //////////////////////////////////////////////////////////////////////////////
- // data for MfcBinderUpdateRegistry functionality
- // %1 = Class ID, formatted as a string
- // %2 = ProgID
- // %3 = Document file extension
- // %4 = Document filter name displayed in File Open dialog
- //
- static const TCHAR szCLSIDDocObject[] =
- _T("CLSID\\%1\\DocObject\0" _T("0"));
- static const TCHAR szProgIDDocObject[] =
- _T("%2\\DocObject\0" _T("0"));
- static const TCHAR szPrintable[] =
- _T("CLSID\\%1\\Printable\0");
- static const TCHAR szDefaultExt[] =
- _T("CLSID\\%1\\DefaultExtension\0%3,%4");
-
- static const LPCTSTR rglpszBindRegister[] =
- {
- szCLSIDDocObject, szProgIDDocObject, szPrintable, NULL
- };
-
- static const LPCTSTR rglpszBindOverwrite[] =
- {
- szDefaultExt, NULL
- };
-
- void MfcBinderUpdateRegistry(const CDocTemplate* pDocTemplate,
- OLE_APPTYPE nAppType,
- LPCTSTR* rglpszRegister,
- LPCTSTR* rglpszOverwrite)
- {
- USES_CONVERSION;
- ASSERT(pDocTemplate != NULL);
-
- // Find the COleTemplateServer associated with the document
- // template
- COleTemplateServer* pServer =
- (COleTemplateServer*)pDocTemplate->m_pAttachedFactory;
-
- if (pServer == NULL)
- return;
-
- // Do the normal registration for an OLE document type
- pServer->UpdateRegistry(nAppType, rglpszRegister, rglpszOverwrite);
-
- // Retrieve the values needed for the Binder-Compatible
- // registry entries.
- CString strProgID;
- CString strFilterName;
- CString strFilterExt;
-
- TRY
- {
- if (!pDocTemplate->GetDocString(strProgID, CDocTemplate::regFileTypeId) ||
- strProgID.IsEmpty())
- {
- AfxThrowUserException();
- }
-
- if (!pDocTemplate->GetDocString(strFilterName, CDocTemplate::filterName) ||
- strFilterName.IsEmpty())
- {
- AfxThrowUserException();
- }
-
- if (!pDocTemplate->GetDocString(strFilterExt, CDocTemplate::filterExt) ||
- strFilterExt.IsEmpty())
- {
- AfxThrowUserException();
- }
- }
- CATCH(CResourceException, pEx)
- {
- TRACE0("Error: not enough information in DocTemplate to"
- " register Binder-compatible document\n");
- return;
- }
- END_CATCH
-
- LPOLESTR lpszClassID;
- ::StringFromCLSID(pServer->GetClassID(), &lpszClassID);
- if (lpszClassID == NULL)
- {
- TRACE0("Error: Could not generate CLSID in MfcBinderUpdateRegistry\n");
- return;
- }
-
- // Use the helper function AfxOleRegisterHelp() to add the
- // Binder-Compatible entries to the registry.
- LPCTSTR rglpszSymbols[4];
- rglpszSymbols[0] = OLE2T(lpszClassID);
- rglpszSymbols[1] = strProgID;
- rglpszSymbols[2] = strFilterExt;
- rglpszSymbols[3] = strFilterName;
-
- BOOL bResult;
- bResult = AfxOleRegisterHelper((LPCTSTR*)rglpszBindRegister,
- rglpszSymbols,
- sizeof(rglpszSymbols)/sizeof(LPCTSTR),
- FALSE);
- if (bResult)
- bResult = AfxOleRegisterHelper((LPCTSTR*)rglpszBindOverwrite,
- rglpszSymbols,
- sizeof(rglpszSymbols)/sizeof(LPCTSTR),
- TRUE);
-
- // free memory for class ID
- ASSERT(lpszClassID != NULL);
- AfxFreeTaskMem(lpszClassID);
-
- if (!bResult)
- AfxMessageBox(BIND_IDP_FAILED_TO_AUTO_REGISTER);
- }
-
- HMENU MfcBinderMergeMenus(CMenu* pMenuShared, CMenu* pMenuSource,
- LONG* lpMenuWidths, int iWidthIndex)
- {
- BOOL bHelpMergedAsSubMenu = FALSE;
- HMENU hMenuHelpSubMenu = NULL;
-
- // copy the popups from the pMenuSource
- int cMenuItems = pMenuSource->GetMenuItemCount();
- int cGroupWidth = 0; // number of items in current group
- int nPosition = 0; // position in shared menu
-
- // insert at appropriate spot depending on iWidthIndex
- ASSERT(iWidthIndex == 0 || iWidthIndex == 1);
- if (iWidthIndex == 1)
- nPosition = (int)lpMenuWidths[0];
-
- int nItem;
- for (nItem = 0; nItem < cMenuItems; nItem++)
- {
- // get the HMENU of the popup
- HMENU hMenuPopup = ::GetSubMenu(pMenuSource->m_hMenu, nItem);
-
- // separators move us to next group
- UINT state = pMenuSource->GetMenuState(nItem, MF_BYPOSITION);
- if (hMenuPopup == NULL && (state & MF_SEPARATOR) != 0)
- {
- ASSERT(iWidthIndex <= 5); // servers should not touch past 5
- lpMenuWidths[iWidthIndex] += cGroupWidth;
- cGroupWidth = 0;
- if (iWidthIndex < 5)
- nPosition += (int)lpMenuWidths[iWidthIndex+1];
- iWidthIndex += 2;
- }
- else
- {
- CMenu* pMenuHelp = NULL;
- // first check whether this is the Help group
- if (iWidthIndex == 5)
- {
- // if so, check to see if container has Help menu items
- if (lpMenuWidths[iWidthIndex] == 1)
- {
- // Get the container's Help menu
- pMenuHelp = pMenuShared->GetSubMenu(nPosition);
- }
- }
-
- // get the menu item text
- CString strItemText;
- int nLen = pMenuSource->GetMenuString(nItem, strItemText, MF_BYPOSITION);
-
- // popups are handled differently than normal menu items
- if (hMenuPopup != NULL)
- {
- if (::GetMenuItemCount(hMenuPopup) != 0)
- {
- // strip the HIBYTE because it contains a count of items
- state = LOBYTE(state) | MF_POPUP; // must be popup
-
- // non-empty popup -- add it to the shared menu bar
- if (pMenuHelp != NULL)
- {
- // Container has help items - add as submenu
- // Name of our help menu should indicate the server
- CString strObjHelp(AfxGetAppName());
- strObjHelp += ' ';
-
- // add item name, skipping ampersands
- int nChar;
- for (nChar = 0; nChar < nLen; nChar++)
- if (strItemText[nChar] != '&')
- strObjHelp += strItemText[nChar];
-
- pMenuHelp->AppendMenu(MF_POPUP, (UINT)hMenuPopup,
- strObjHelp);
-
- // Clear the count of Help group items and
- // add Help menu to Window group
- lpMenuWidths[iWidthIndex] = 0;
- lpMenuWidths[iWidthIndex-1]++;
-
- bHelpMergedAsSubMenu = TRUE;
- hMenuHelpSubMenu = hMenuPopup;
- continue;
- }
- else
- {
- // if we didn't do special Help menu merging, just
- // insert the menu
- pMenuShared->InsertMenu(nPosition, state | MF_BYPOSITION,
- (UINT)hMenuPopup, strItemText);
- nPosition++;
- cGroupWidth++;
- }
- }
- }
- else if (nLen > 0)
- {
- // only non-empty items are added
- ASSERT(!strItemText.IsEmpty());
-
- if (pMenuHelp != NULL)
- {
- // Container has help items - add to its submenu
- pMenuHelp->AppendMenu(MF_STRING,
- pMenuSource->GetMenuItemID(nItem),
- strItemText);
-
- // Clear the count of Help group items and
- // add Help menu to Window group
- lpMenuWidths[iWidthIndex] = 0;
- lpMenuWidths[iWidthIndex-1]++;
-
- bHelpMergedAsSubMenu = TRUE;
- continue;
- }
- else
- {
- // here the state does not contain a count in the HIBYTE
- pMenuShared->InsertMenu(nPosition, state | MF_BYPOSITION,
- pMenuSource->GetMenuItemID(nItem), strItemText);
- nPosition++;
- cGroupWidth++;
- }
- }
- }
- }
-
- // set the last group width
- if (!bHelpMergedAsSubMenu)
- {
- ASSERT(iWidthIndex <= 5); // servers should not touch past 5
- lpMenuWidths[iWidthIndex] += cGroupWidth;
- }
-
- return hMenuHelpSubMenu;
- }
-
- void MfcBinderUnmergeMenus(CMenu* pMenuShared, CMenu* pMenuSource,
- CMenu* pMenuHelpPopup)
- {
- int cOurItems = pMenuSource->GetMenuItemCount();
- int cMenuItems = pMenuShared->GetMenuItemCount();
-
- for (int i = cMenuItems-1; i >= 0; i--)
- {
- // check out the popup menus
- HMENU hMenuPopup = ::GetSubMenu(pMenuShared->m_hMenu, i);
- if (hMenuPopup != NULL)
- {
- // if we have a Help submenu, check to see if it appears
- // in this submenu somewhere
- if (pMenuHelpPopup)
- {
- int cPopupItems = ::GetMenuItemCount(hMenuPopup);
- for (int k = 0; k < cPopupItems; k++)
- {
- if (::GetSubMenu(hMenuPopup, k) == pMenuHelpPopup->m_hMenu)
- {
- // remove the Help submenu
- ::RemoveMenu(hMenuPopup, k, MF_BYPOSITION);
- pMenuHelpPopup = NULL;
- break;
- }
- }
- }
- else
- {
- // if it is one of ours, remove it from the pMenuShared
- for (int j = 0; j < cOurItems; j++)
- {
- if (::GetSubMenu(pMenuSource->m_hMenu, j) == hMenuPopup)
- {
- // remove the menu from pMenuShared
- pMenuShared->RemoveMenu(i, MF_BYPOSITION);
- break;
- }
- }
- }
- }
- }
- }
-
-