|
|
Microsoft Windows NT Build 511 (SDK Final Release) 07-24-1993
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and Microsoft
// QuickHelp documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.
#include "afxole.h"
#pragma hdrstop
#include "afxoleui.h" // user interface parts
#include "shellapi.h"
#ifdef AFX_OLE_SEG
#pragma code_seg(AFX_OLE_SEG)
#endif
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// User interface for COleClientItem
int COleClientItem::cWaitForRelease = 0;
BOOL COleClientItem::InWaitForRelease()
{
return cWaitForRelease != 0;
}
void COleClientItem::WaitForServer()
{
// enforce synchronous action from the server
if (afxTraceFlags & 0x10)
TRACE("WAITING for server\n");
ASSERT(m_lpObject != NULL);
ASSERT(cWaitForRelease == 0);
#ifdef _DEBUG
m_lastStatus = OLE_WAIT_FOR_RELEASE;
#endif
cWaitForRelease++;
// OnRelease may NULL out our m_lpObject
while (m_lpObject != NULL && ::OleQueryReleaseStatus(m_lpObject) != OLE_OK)
{
TRY
{
AfxGetApp()->PumpMessage();
}
CATCH(CException,e)
{
TRACE("DANGER: caught exception in WaitForServer - continuing\n");
}
END_CATCH
}
cWaitForRelease--;
if (afxTraceFlags & 0x10)
TRACE("DONE WAITING for server\n");
}
BOOL COleClientItem::ReportError(OLESTATUS status)
// return TRUE if error or warning reported
{
UINT idString = 0;
switch (status)
{
default:
return FALSE; // nothing sensible to report
case OLE_ERROR_STATIC:
idString = AFX_ERROR_STATIC_OBJECT;
break;
case OLE_ERROR_REQUEST_PICT:
case OLE_ERROR_ADVISE_RENAME:
case OLE_ERROR_SHOW:
case OLE_ERROR_OPEN:
case OLE_ERROR_NETWORK:
case OLE_ERROR_ADVISE_PICT:
case OLE_ERROR_COMM:
case OLE_ERROR_LAUNCH:
// invalid link
idString = AFX_ERROR_FAILED_TO_CONNECT;
break;
case OLE_ERROR_DOVERB:
idString = AFX_ERROR_BAD_VERB;
break;
case OLE_BUSY:
idString = AFX_ERROR_SERVER_BUSY;
break;
case OLE_ERROR_MEMORY:
idString = AFX_ERROR_MEMORY;
break;
}
CString s;
s.LoadString(idString);
// bring up a message box in the topmost window
CWinApp* pApp = AfxGetApp();
ASSERT(pApp != NULL && pApp->m_pMainWnd != NULL);
pApp->m_pMainWnd->MessageBox(s, pApp->m_pszAppName,
MB_OK | MB_ICONEXCLAMATION);
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// OLE Object Verb Menu helpers
// Parameters:
// pClient = client object to operate on (NULL => none)
// pMenu = menu to modify
// iMenuItem = index into menu where menu item or popup is to be placed
// (note will delete the old one)
// nIDVerbMin = first menu command id for sending to pClient
//
// Supported cases:
// NULL client "&Object" disabled
// 0 verbs "<Object Class> &Object"
// 1 verb (no name) "<Object Class> &Object"
// 1 verb == edit "<Object Class> &Object"
// 1 verb != edit "<verb> <Object Class> &Object"
// more than 1 verb "<Object Class> &Object" => verbs
void AfxOleSetEditMenu(COleClientItem* pClient, CMenu* pMenu,
UINT iMenuItem, UINT nIDVerbMin)
{
ASSERT(pMenu != NULL);
static CString NEAR strObjectVerb; // "&Object"
static CString NEAR strEditVerb; // "Edit"
static BOOL bInited = FALSE;
if (!bInited)
{
VERIFY(strObjectVerb.LoadString(AFX_IDS_OBJECT_MENUITEM));
VERIFY(strEditVerb.LoadString(AFX_IDS_EDIT_VERB));
}
pMenu->DeleteMenu(iMenuItem, MF_BYPOSITION); // get rid of old UI
HANDLE hLinkData = NULL;
UINT mfObjectVerb = MF_GRAYED|MF_DISABLED;
if (pClient != NULL)
{
// get type from object
hLinkData = pClient->GetLinkFormatData();
mfObjectVerb = MF_ENABLED;
}
LPCSTR lpszData;
// use the link data to determine what class we are talking about
if (hLinkData == NULL ||
(lpszData = (LPCSTR)::GlobalLock(hLinkData)) == NULL)
{
// not a valid link, just use the simple '&Object' format disabled
pMenu->InsertMenu(iMenuItem, MF_BYPOSITION, nIDVerbMin, strObjectVerb);
pMenu->EnableMenuItem(iMenuItem, mfObjectVerb | MF_BYPOSITION |
MF_GRAYED|MF_DISABLED);
return;
}
LONG lSize;
char szClass[OLE_MAXNAMESIZE];
char szBuffer[OLE_MAXNAMESIZE+40];
// get real language class of object in szClass for menu
lSize = OLE_MAXNAMESIZE;
if (::RegQueryValue(HKEY_CLASSES_ROOT, lpszData, szClass,
&lSize) != ERROR_SUCCESS)
{
// no localized class name, use unlocalized name
lstrcpy(szClass, lpszData);
}
::GlobalUnlock(hLinkData);
// determine list of available verbs
char szFirstVerb[OLE_MAXNAMESIZE];
HMENU hPopup = NULL;
int cVerbs = 0;
while (1)
{
wsprintf(szBuffer, "%s\\protocol\\StdFileEditing\\verb\\%d",
(LPCSTR)lpszData, cVerbs);
/* get verb name */
char szVerb[OLE_MAXNAMESIZE];
lSize = OLE_MAXNAMESIZE;
if (::RegQueryValue(HKEY_CLASSES_ROOT, szBuffer, szVerb, &lSize) != 0)
{
// finished counting verbs
break;
}
cVerbs++;
if (_stricmp(szVerb, strEditVerb) == 0)
strcpy(szVerb, strEditVerb); // use 'Edit' not 'EDIT'
if (cVerbs == 1)
{
// save first verb (special case if this is it)
strcpy(szFirstVerb, szVerb);
}
else
{
// overflow into popup
if (cVerbs == 2)
{
// start the popup
ASSERT(hPopup == NULL);
hPopup = CreatePopupMenu();
// now add the first verb
InsertMenu(hPopup, -1, MF_BYPOSITION, nIDVerbMin + 0,
szFirstVerb);
}
ASSERT(hPopup != NULL);
InsertMenu(hPopup, -1, MF_BYPOSITION, nIDVerbMin + cVerbs - 1,
szVerb);
}
}
if (cVerbs >= 2)
{
// install the popup
wsprintf(szBuffer, "%s %s", (LPCSTR)szClass, (LPCSTR)strObjectVerb);
pMenu->InsertMenu(iMenuItem, MF_BYPOSITION|MF_POPUP, (UINT)hPopup, szBuffer);
}
else if (cVerbs == 0 || _stricmp(szFirstVerb, strEditVerb) == 0)
{
// no verbs or redundant 'edit' verb
wsprintf(szBuffer, "%s %s", (LPCSTR)szClass, (LPCSTR)strObjectVerb);
pMenu->InsertMenu(iMenuItem, MF_BYPOSITION, nIDVerbMin, szBuffer);
}
else
{
// use that verb in menu item
ASSERT(cVerbs == 1);
wsprintf(szBuffer, "%s %s %s", (LPCSTR)szFirstVerb, (LPCSTR)szClass,
(LPCSTR)strObjectVerb);
pMenu->InsertMenu(iMenuItem, MF_BYPOSITION, nIDVerbMin, szBuffer);
}
// enable what we added
pMenu->EnableMenuItem(iMenuItem, MF_ENABLED|MF_BYPOSITION);
}
/////////////////////////////////////////////////////////////////////////////
// InsertObject dialog
class CInsertNewObjectDlg : public CModalDialog
{
public:
CString& m_rClassName;
CInsertNewObjectDlg(CString& rReturn)
: CModalDialog(AFX_IDD_INSERTNEWOBJECT),
m_rClassName(rReturn)
{ }
BOOL OnInitDialog();
void OnOK();
DECLARE_MESSAGE_MAP()
};
BEGIN_MESSAGE_MAP(CInsertNewObjectDlg, CModalDialog)
ON_LBN_DBLCLK(AFX_IDC_LISTBOX, OnOK)
END_MESSAGE_MAP()
BOOL CInsertNewObjectDlg::OnInitDialog()
{
int cClasses = 0;
CListBox* pList = (CListBox*)GetDlgItem(AFX_IDC_LISTBOX);
pList->ResetContent();
char szClass[OLE_MAXNAMESIZE];
int i = 0;
while (::RegEnumKey(HKEY_CLASSES_ROOT, i++, szClass, OLE_MAXNAMESIZE) == 0)
{
if (*szClass == '.')
continue; // skip extensions
// See if this class really refers to a server
LONG lSize;
HKEY hkey = NULL;
char szExec[OLE_MAXNAMESIZE+40];
lstrcpy(szExec, szClass);
lstrcat(szExec, "\\protocol\\StdFileEditing\\server");
if (::RegOpenKey(HKEY_CLASSES_ROOT, szExec, &hkey) == 0)
{
// since it has a server - add it to the list
char szName[OLE_MAXNAMESIZE];
lSize = OLE_MAXNAMESIZE;
if (::RegQueryValue(HKEY_CLASSES_ROOT, szClass,
szName, &lSize) == 0)
{
// we have a class name
pList->AddString(szName);
cClasses++;
}
::RegCloseKey(hkey);
}
}
if (cClasses == 0)
{
// whoops - nothing to choose from
EndDialog(IDCANCEL);
}
pList->SetCurSel(0);
return TRUE;
}
void CInsertNewObjectDlg::OnOK()
{
CListBox* pList = (CListBox*)GetDlgItem(AFX_IDC_LISTBOX);
char szKey[OLE_MAXNAMESIZE];
pList->GetText(pList->GetCurSel(), szKey);
char szClass[OLE_MAXNAMESIZE];
int i = 0;
while (::RegEnumKey(HKEY_CLASSES_ROOT, i++, szClass, OLE_MAXNAMESIZE) == 0)
{
if (*szClass == '.')
continue; // skip extensions
// See if this class really refers to a server
LONG lSize;
HKEY hkey = NULL;
char szExec[OLE_MAXNAMESIZE+40];
lstrcpy(szExec, szClass);
lstrcat(szExec, "\\protocol\\StdFileEditing\\server");
if (::RegOpenKey(HKEY_CLASSES_ROOT, szExec, &hkey) == 0)
{
// we found a match - see if appropriate name
char szName[OLE_MAXNAMESIZE];
lSize = OLE_MAXNAMESIZE;
if (::RegQueryValue(HKEY_CLASSES_ROOT, szClass,
szName, &lSize) == 0)
{
// it is a named class - see if it matches key
if (strcmp(szKey, szName) == 0)
{
// this is it
m_rClassName = szClass;
CModalDialog::OnOK(); // terminate dialog
return;
}
}
::RegCloseKey(hkey);
}
}
// didn't find it
EndDialog(IDCANCEL);
}
BOOL AfxOleInsertDialog(CString& name)
{
CInsertNewObjectDlg dlg(name);
return (dlg.DoModal() == IDOK);
}
/////////////////////////////////////////////////////////////////////////////
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.