home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgLangD.iso / C++-7 / DISK10 / MFC / SRC / OLEUI.CP$ / oleui
Encoding:
Text File  |  1992-03-11  |  9.5 KB  |  387 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library. 
  2. // Copyright (C) 1992 Microsoft Corporation 
  3. // All rights reserved. 
  4. //  
  5. // This source code is only intended as a supplement to the 
  6. // Microsoft Foundation Classes Reference and Microsoft 
  7. // QuickHelp documentation provided with the library. 
  8. // See these sources for detailed information regarding the 
  9. // Microsoft Foundation Classes product. 
  10.  
  11. #include "afxole.h"
  12. #pragma hdrstop
  13.  
  14. #include "afxoleUI.h"       // user interface parts
  15.  
  16. #include "shellapi.h"
  17.  
  18. #ifdef AFX_OLE_SEG
  19. #pragma code_seg(AFX_OLE_SEG)
  20. #endif
  21.  
  22. #ifdef _DEBUG
  23. #undef THIS_FILE
  24. static char BASED_CODE THIS_FILE[] = __FILE__;
  25. #endif
  26.  
  27. /////////////////////////////////////////////////////////////////////////////
  28. // User interface for COleClientItem
  29.  
  30. int COleClientItem::cWaitForRelease = 0;
  31. BOOL COleClientItem::InWaitForRelease()
  32. {
  33.     return cWaitForRelease != 0;
  34. }
  35.  
  36. void COleClientItem::WaitForServer()
  37. {
  38.     // enforce synchronous action from the server
  39.     if (afxTraceFlags & 0x10)
  40.         TRACE("WAITING for server\n");
  41.  
  42.     ASSERT(m_lpObject != NULL);
  43.     ASSERT(cWaitForRelease == 0);
  44. #ifdef _DEBUG
  45.     m_lastStatus = OLE_WAIT_FOR_RELEASE;
  46. #endif
  47.     cWaitForRelease++;
  48.  
  49.     // OnRelease may NULL out our m_lpObject
  50.     while (m_lpObject != NULL && ::OleQueryReleaseStatus(m_lpObject) != OLE_OK)
  51.     {
  52.         TRY
  53.         {
  54.             AfxGetApp()->PumpMessage();
  55.         }
  56.         CATCH(CException,e)
  57.         {
  58.             TRACE("DANGER: caught exception in WaitForServer - continuing\n");
  59.         }
  60.         END_CATCH
  61.     }
  62.     cWaitForRelease--;
  63.  
  64.     if (afxTraceFlags & 0x10)
  65.         TRACE("DONE WAITING for server\n");
  66. }
  67.  
  68. BOOL COleClientItem::ReportError(OLESTATUS status)
  69.     // return TRUE if error or warning reported
  70. {
  71.     UINT idString = 0;
  72.  
  73.     switch (status)
  74.     {
  75.     default:
  76.         return FALSE;       // nothing sensible to report
  77.  
  78.     case OLE_ERROR_STATIC:
  79.         idString = AFX_ERROR_STATIC_OBJECT;
  80.         break;
  81.  
  82.     case OLE_ERROR_REQUEST_PICT:
  83.     case OLE_ERROR_ADVISE_RENAME:
  84.     case OLE_ERROR_SHOW:
  85.     case OLE_ERROR_OPEN:
  86.     case OLE_ERROR_NETWORK:
  87.     case OLE_ERROR_ADVISE_PICT:
  88.     case OLE_ERROR_COMM:
  89.     case OLE_ERROR_LAUNCH:
  90.         // invalid link
  91.         idString = AFX_ERROR_FAILED_TO_CONNECT;
  92.         break;
  93.  
  94.     case OLE_ERROR_DOVERB:
  95.         idString = AFX_ERROR_BAD_VERB;
  96.         break;
  97.  
  98.     case OLE_BUSY:
  99.         idString = AFX_ERROR_SERVER_BUSY;
  100.         break;
  101.  
  102.     case OLE_ERROR_MEMORY:
  103.         idString = AFX_ERROR_MEMORY;
  104.         break;
  105.     }
  106.  
  107.     CString s;
  108.     s.LoadString(idString);
  109.  
  110.     // bring up a message box in the topmost window
  111.     CWinApp* pApp = AfxGetApp();
  112.     ASSERT(pApp != NULL && pApp->m_pMainWnd != NULL);
  113.     pApp->m_pMainWnd->MessageBox(s, pApp->m_pszAppName,
  114.             MB_OK | MB_ICONEXCLAMATION);
  115.  
  116.     return TRUE;
  117. }
  118.  
  119.  
  120. /////////////////////////////////////////////////////////////////////////////
  121. // OLE Object Verb Menu helpers
  122.  
  123. // Parameters:
  124. //      pClient = client object to operate on (NULL => none)
  125. //      pMenu = menu to modify
  126. //      iMenuItem = index into menu where menu item or popup is to be placed
  127. //              (note will delete the old one)
  128. //      nIDVerbMin = first menu command id for sending to pClient
  129. //
  130. // Supported cases:
  131. //  NULL client "&Object" disabled
  132. //  0 verbs       "<Object Class> &Object"
  133. //  1 verb (no name) "<Object Class> &Object"
  134. //  1 verb == edit   "<Object Class> &Object"
  135. //  1 verb != edit   "<verb> <Object Class> &Object"
  136. //  more than 1 verb "<Object Class> &Object" => verbs
  137.  
  138. void AfxOleSetEditMenu(COleClientItem* pClient, CMenu* pMenu,
  139.     UINT iMenuItem, UINT nIDVerbMin)
  140. {
  141.     ASSERT(pMenu != NULL);
  142.  
  143.     static CString NEAR strObjectVerb;           // "&Object"
  144.     static CString NEAR strEditVerb;             // "Edit"
  145.     static BOOL bInited = FALSE;
  146.     if (!bInited)
  147.     {
  148.         VERIFY(strObjectVerb.LoadString(AFX_IDS_OBJECT_MENUITEM));
  149.         VERIFY(strEditVerb.LoadString(AFX_IDS_EDIT_VERB));
  150.     }
  151.  
  152.     pMenu->DeleteMenu(iMenuItem, MF_BYPOSITION); // get rid of old UI
  153.  
  154.     HANDLE hLinkData = NULL;
  155.     UINT mfObjectVerb = MF_GRAYED|MF_DISABLED;
  156.  
  157.     if (pClient != NULL)
  158.     {
  159.         // get type from object
  160.         hLinkData = pClient->GetLinkFormatData();
  161.         mfObjectVerb = MF_ENABLED;
  162.     }
  163.  
  164.     LPCSTR   lpszData;
  165.     // use the link data to determine what class we are talking about
  166.  
  167.     if (hLinkData == NULL ||
  168.        (lpszData = (LPCSTR)::GlobalLock(hLinkData)) == NULL)
  169.     {
  170.         // not a valid link, just use the simple '&Object' format disabled
  171.         pMenu->InsertMenu(iMenuItem, MF_BYPOSITION, nIDVerbMin, strObjectVerb);
  172.         pMenu->EnableMenuItem(iMenuItem, mfObjectVerb | MF_BYPOSITION |
  173.             MF_GRAYED|MF_DISABLED);
  174.         return;
  175.     }
  176.  
  177.     LONG    lSize;
  178.     char    szClass[OLE_MAXNAMESIZE];
  179.     char    szBuffer[OLE_MAXNAMESIZE+40];
  180.  
  181.     // get real language class of object in szClass for menu
  182.     lSize = OLE_MAXNAMESIZE;
  183.     if (::RegQueryValue(HKEY_CLASSES_ROOT, lpszData, szClass,
  184.         &lSize) != ERROR_SUCCESS)
  185.     {
  186.         // no localized class name, use unlocalized name
  187.         lstrcpy(szClass, lpszData);
  188.     }
  189.     ::GlobalUnlock(hLinkData);
  190.  
  191.     // determine list of available verbs
  192.     char    szFirstVerb[OLE_MAXNAMESIZE];
  193.     HMENU  hPopup = NULL;
  194.     int     cVerbs = 0;
  195.  
  196.     while (1)
  197.     {
  198.         wsprintf(szBuffer, "%s\\protocol\\StdFileEditing\\verb\\%d",
  199.                  (LPCSTR)lpszData, cVerbs);
  200.  
  201.         /* get verb name */
  202.         char    szVerb[OLE_MAXNAMESIZE];
  203.         lSize = OLE_MAXNAMESIZE;
  204.         if (::RegQueryValue(HKEY_CLASSES_ROOT, szBuffer, szVerb, &lSize) != 0)
  205.         {
  206.             // finished counting verbs
  207.             break;
  208.         }
  209.         cVerbs++;
  210.  
  211.         if (_stricmp(szVerb, strEditVerb) == 0)
  212.             strcpy(szVerb, strEditVerb);    // use 'Edit' not 'EDIT'
  213.  
  214.         if (cVerbs == 1)
  215.         {
  216.             // save first verb (special case if this is it)
  217.             strcpy(szFirstVerb, szVerb);
  218.         }
  219.         else
  220.         {
  221.             // overflow into popup
  222.             if (cVerbs == 2)
  223.             {
  224.                 // start the popup
  225.                 ASSERT(hPopup == NULL);
  226.                 hPopup = CreatePopupMenu();
  227.  
  228.                 // now add the first verb
  229.                 InsertMenu(hPopup, -1, MF_BYPOSITION, nIDVerbMin + 0,
  230.                     szFirstVerb);
  231.             }
  232.  
  233.             ASSERT(hPopup != NULL);
  234.             InsertMenu(hPopup, -1, MF_BYPOSITION, nIDVerbMin + cVerbs - 1,
  235.                     szVerb);
  236.         }
  237.     }
  238.  
  239.     if (cVerbs >= 2)
  240.     {
  241.         // install the popup
  242.         wsprintf(szBuffer, "%s %s", (LPCSTR)szClass, (LPCSTR)strObjectVerb);
  243.         pMenu->InsertMenu(iMenuItem, MF_BYPOSITION|MF_POPUP, (UINT)hPopup, szBuffer);
  244.     }
  245.     else if (cVerbs == 0 || _stricmp(szFirstVerb, strEditVerb) == 0)
  246.     {
  247.         // no verbs or redundant 'edit' verb
  248.         wsprintf(szBuffer, "%s %s", (LPCSTR)szClass, (LPCSTR)strObjectVerb);
  249.         pMenu->InsertMenu(iMenuItem, MF_BYPOSITION, nIDVerbMin, szBuffer);
  250.     }
  251.     else
  252.     {
  253.         // use that verb in menu item
  254.         ASSERT(cVerbs == 1);
  255.         wsprintf(szBuffer, "%s %s %s", (LPCSTR)szFirstVerb, (LPCSTR)szClass,
  256.             (LPCSTR)strObjectVerb);
  257.         pMenu->InsertMenu(iMenuItem, MF_BYPOSITION, nIDVerbMin, szBuffer);
  258.     }
  259.  
  260.     // enable what we added
  261.     pMenu->EnableMenuItem(iMenuItem, MF_ENABLED|MF_BYPOSITION);
  262. }
  263.  
  264. /////////////////////////////////////////////////////////////////////////////
  265. // InsertObject dialog
  266.  
  267. class CInsertNewObjectDlg : public CModalDialog
  268. {
  269. public:
  270.     CString&    m_rClassName;
  271.  
  272.     CInsertNewObjectDlg(CString& rReturn)
  273.             : CModalDialog(AFX_IDD_INSERTNEWOBJECT),
  274.                 m_rClassName(rReturn)
  275.         { }
  276.  
  277.     BOOL OnInitDialog();
  278.     void OnOK();
  279.     DECLARE_MESSAGE_MAP()
  280. };
  281.  
  282. BEGIN_MESSAGE_MAP(CInsertNewObjectDlg, CModalDialog)
  283.     ON_LBN_DBLCLK(AFX_IDC_LISTBOX, OnOK)
  284. END_MESSAGE_MAP()
  285.  
  286. BOOL CInsertNewObjectDlg::OnInitDialog()
  287. {
  288.     int cClasses = 0;
  289.     CListBox* pList = (CListBox*)GetDlgItem(AFX_IDC_LISTBOX);
  290.  
  291.     pList->ResetContent();
  292.  
  293.     char szClass[OLE_MAXNAMESIZE];
  294.     int i = 0;
  295.     while (::RegEnumKey(HKEY_CLASSES_ROOT, i++, szClass, OLE_MAXNAMESIZE) == 0)
  296.     {
  297.         if (*szClass == '.')
  298.             continue;       // skip extensions
  299.  
  300.         // See if this class really refers to a server
  301.         LONG lSize;
  302.         HKEY hkey = NULL;
  303.         char szExec[OLE_MAXNAMESIZE+40];
  304.         lstrcpy(szExec, szClass);
  305.         lstrcat(szExec, "\\protocol\\StdFileEditing\\server");
  306.  
  307.         if (::RegOpenKey(HKEY_CLASSES_ROOT, szExec, &hkey) == 0)
  308.         {
  309.             // since it has a server - add it to the list
  310.             char szName[OLE_MAXNAMESIZE];
  311.             lSize = OLE_MAXNAMESIZE;
  312.             if (::RegQueryValue(HKEY_CLASSES_ROOT, szClass,
  313.               szName, &lSize) == 0)
  314.             {
  315.                 // we have a class name
  316.                 pList->AddString(szName);
  317.                 cClasses++;
  318.             }
  319.             ::RegCloseKey(hkey);
  320.         }
  321.     }
  322.  
  323.     if (cClasses == 0)
  324.     {
  325.         // whoops - nothing to choose from
  326.         EndDialog(IDCANCEL);
  327.     }
  328.     pList->SetCurSel(0);
  329.     return TRUE;
  330. }
  331.  
  332. void CInsertNewObjectDlg::OnOK()
  333. {
  334.     CListBox* pList = (CListBox*)GetDlgItem(AFX_IDC_LISTBOX);
  335.  
  336.     char szKey[OLE_MAXNAMESIZE];
  337.     pList->GetText(pList->GetCurSel(), szKey);
  338.  
  339.     char szClass[OLE_MAXNAMESIZE];
  340.     int i = 0;
  341.     while (::RegEnumKey(HKEY_CLASSES_ROOT, i++, szClass, OLE_MAXNAMESIZE) == 0)
  342.     {
  343.         if (*szClass == '.')
  344.             continue;       // skip extensions
  345.  
  346.         // See if this class really refers to a server
  347.         LONG lSize;
  348.         HKEY hkey = NULL;
  349.         char szExec[OLE_MAXNAMESIZE+40];
  350.         lstrcpy(szExec, szClass);
  351.         lstrcat(szExec, "\\protocol\\StdFileEditing\\server");
  352.  
  353.         if (::RegOpenKey(HKEY_CLASSES_ROOT, szExec, &hkey) == 0)
  354.         {
  355.             // we found a match - see if appropriate name
  356.             char szName[OLE_MAXNAMESIZE];
  357.             lSize = OLE_MAXNAMESIZE;
  358.             if (::RegQueryValue(HKEY_CLASSES_ROOT, szClass,
  359.               szName, &lSize) == 0)
  360.             {
  361.                 // it is a named class - see if it matches key
  362.                 if (strcmp(szKey, szName) == 0)
  363.                 {
  364.                     // this is it
  365.                     m_rClassName = szClass;
  366.                     CModalDialog::OnOK();   // terminate dialog
  367.                     return;
  368.                 }
  369.             }
  370.             ::RegCloseKey(hkey);
  371.         }
  372.     }
  373.  
  374.     // didn't find it
  375.     EndDialog(IDCANCEL);
  376. }
  377.  
  378.  
  379. BOOL AfxOleInsertDialog(CString& name)
  380. {
  381.     CInsertNewObjectDlg dlg(name);
  382.  
  383.     return (dlg.DoModal() == IDOK);
  384. }
  385.  
  386. /////////////////////////////////////////////////////////////////////////////
  387.