📄 olecli1.cpp
字号:
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992-1998 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.
#include "stdafx.h"
#ifdef AFX_OLE_SEG
#pragma code_seg(AFX_OLE_SEG)
#endif
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define new DEBUG_NEW
/////////////////////////////////////////////////////////////////////////////
// COleClientItem - Container view of IOleObject and related interfaces
COleClientItem::COleClientItem(COleDocument* pContainerDoc)
{
if (pContainerDoc != NULL)
ASSERT_VALID(pContainerDoc);
// initialize OLE client side view of IOleObject
m_lpObject = NULL;
m_lpViewObject = NULL;
m_dwConnection = 0;
m_lpStorage = NULL;
m_lpLockBytes = NULL;
m_scLast = S_OK;
m_pView = NULL;
m_pInPlaceFrame = NULL;
m_pInPlaceDoc = NULL;
m_nItemState = emptyState; // initially empty until OleLoad, OleCreate
m_bMoniker = FALSE;
m_nDrawAspect = DVASPECT_CONTENT; // default draw aspect
m_dwItemNumber = 0;
m_bLinkUnavail = FALSE; // set to TRUE on failed DoVerb, or in links dialog
m_nItemType = OT_UNKNOWN; // type unknown so far
m_hWndServer = NULL;
m_bClosing = FALSE; // COleClientItem::Close in process
m_bLocked = FALSE; // need CoLockObjectExternal(..., FALSE, ...)
// initialize compound file support
m_lpNewStorage = NULL;
m_bNeedCommit = FALSE;
if (pContainerDoc != NULL)
pContainerDoc->AddItem(this);
ASSERT(m_pDocument == pContainerDoc);
ASSERT_VALID(this);
AfxOleLockApp();
}
COleClientItem::~COleClientItem()
{
ASSERT_VALID(this);
// release any references we may have to other objects
Release();
// only remove it from the associated document if it hasn't been detached
// from the document already!
if (m_pDocument != NULL)
m_pDocument->RemoveItem(this);
// make sure all outside connections are disconnected
ExternalDisconnect();
AfxOleUnlockApp();
}
void COleClientItem::Delete(BOOL bAutoDelete)
{
USES_CONVERSION;
ASSERT_VALID(this);
Release(); // first close it
COleDocument* pDoc = GetDocument();
if (pDoc != NULL && pDoc->m_bCompoundFile)
{
// cleanup docfile storage first
COleDocument* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (pDoc->m_lpRootStg != NULL)
{
// get item name
TCHAR szItemName[OLE_MAXITEMNAME];
GetItemName(szItemName);
// attempt to remove it from the storage, ignore errors
pDoc->m_lpRootStg->DestroyElement(T2COLE(szItemName));
}
}
if (bAutoDelete)
{
// remove item from document
if (pDoc != NULL)
pDoc->RemoveItem(this);
InternalRelease(); // remove the item from memory
}
}
void COleClientItem::Release(OLECLOSE dwCloseOption)
{
ASSERT_VALID(this);
m_scLast = S_OK;
// cleanup view advise
if (m_lpViewObject != NULL)
{
DWORD dwAspect;
IAdviseSink* pAdviseSink;
pAdviseSink = NULL;
VERIFY(m_lpViewObject->GetAdvise(&dwAspect, NULL, &pAdviseSink) == S_OK);
if( pAdviseSink != NULL )
{
RELEASE( pAdviseSink );
}
VERIFY(m_lpViewObject->SetAdvise(dwAspect, 0, NULL) == S_OK);
RELEASE(m_lpViewObject);
}
// cleanup the OLE object itself
if (m_lpObject != NULL)
{
// cleanup object advise
if (m_dwConnection != 0)
{
VERIFY(m_lpObject->Unadvise(m_dwConnection) == S_OK);
m_dwConnection = 0;
}
// close object and save (except now when called from destructor)
// (NOTE: errors are _not_ reported as an exception)
m_scLast = m_lpObject->Close(dwCloseOption);
RELEASE(m_lpObject);
}
// cleanup storage related data
RELEASE(m_lpStorage);
RELEASE(m_lpLockBytes);
// cleanup in-place editing data
if (m_pInPlaceFrame != NULL)
{
m_pInPlaceFrame->InternalRelease();
m_pInPlaceFrame = NULL;
if (m_pInPlaceDoc != NULL)
{
m_pInPlaceDoc->InternalRelease();
m_pInPlaceDoc = NULL;
}
}
ASSERT(m_pInPlaceFrame == NULL);
ASSERT(m_pInPlaceDoc == NULL);
}
void COleClientItem::Close(OLECLOSE dwCloseOption)
{
ASSERT_VALID(this);
ASSERT(m_lpObject != NULL);
// gaurd against re-entry
if (m_bClosing)
return;
m_bClosing = TRUE;
// attempt to close the object
m_scLast = m_lpObject->Close(dwCloseOption);
// remove external lock placed on item during in-place activation
if (m_bLocked)
{
OleLockRunning(m_lpObject, FALSE, TRUE);
m_bLocked = FALSE;
}
// handle failure cases -- COleClientItem::Close can be used to
// robustly handle a server crashing (ie. something unexpected happens,
// we'll call COleClientItem::Close to attempt safe shutdown)
if (GetItemState() != loadedState)
{
// We'll call COleClientItem::Close anywhere a catastrophe
// happens inside of other portions of COleClientItem. We must
// completely exit from any in-place/open state.
// force transition from activeUIState to activeState
if (GetItemState() == activeUIState)
OnDeactivateUI(FALSE);
// force transition from activeState to loadedState
if (GetItemState() == activeState)
OnDeactivate();
if (m_nItemState != loadedState)
{
// in case of extreme failure, force loadedState
OnChange(OLE_CHANGED_STATE, (DWORD)loadedState);
m_nItemState = loadedState; // force it to loaded state
}
}
m_bClosing = FALSE; // now safe for further close calls
}
/////////////////////////////////////////////////////////////////////////////
// COleClientItem name management
DWORD COleClientItem::GetNewItemNumber()
{
ASSERT_VALID(this);
COleDocument* pDoc = GetDocument();
ASSERT_VALID(pDoc);
DWORD dwNextItemNumber = pDoc->m_dwNextItemNumber;
for (;;)
{
// make sure that m_dwNextItemNumber is not used in another item first
POSITION pos = pDoc->GetStartPosition();
COleClientItem* pItem;
while ((pItem = pDoc->GetNextClientItem(pos)) != NULL)
{
if (pItem->m_dwItemNumber == dwNextItemNumber)
break;
}
if (pItem == NULL)
break; // no item using m_dwNextItemNumber
// m_dwNextItemNumber is in use, bump to next one!
++dwNextItemNumber;
}
pDoc->m_dwNextItemNumber = dwNextItemNumber + 1;
return dwNextItemNumber;
}
void COleClientItem::GetItemName(LPTSTR lpszItemName) const
{
ASSERT_VALID(this);
ASSERT(lpszItemName != NULL);
wsprintf(lpszItemName, _T("Embedding %lu"), m_dwItemNumber);
ASSERT(lstrlen(lpszItemName) < OLE_MAXITEMNAME);
}
// extracts icon resource ID and path name from registry "file.exe,35" format
static void AfxGetIconInfo(LPCTSTR lpszRegInfo, LPTSTR lpszImagePath,
UINT& nIndex)
{
LPTSTR pstrTarget = lpszImagePath;
LPCTSTR pstrSource = lpszRegInfo;
while (*pstrSource != ',' && *pstrSource != '\0')
{
*pstrTarget = *pstrSource;
pstrTarget = _tcsinc(pstrTarget);
pstrSource = _tcsinc(pstrSource);
}
*pstrTarget = '\0';
// extract the index
if (*pstrSource != '\0')
{
LPTSTR pstrIndex = _tcsinc(pstrSource);
nIndex = (UINT) _ttol(pstrIndex);
}
else
nIndex = 0;
}
HICON COleClientItem::GetIconFromRegistry() const
{
CLSID clsid;
GetClassID(&clsid);
if (clsid == CLSID_NULL)
return NULL;
return GetIconFromRegistry(clsid);
}
HICON COleClientItem::GetIconFromRegistry(CLSID& clsid)
{
// This function will extract the icon registered as the DefaultIcon
// for the server referred to by clsid. We get the ProgID for the server
// and then extract \\hkcr\progid\DefaultIcon. If that doesn't exist, we
// get a default icon from \\hkcr\DocShortcut\DefaultIcon and if that fails
// we just return 0.
USES_CONVERSION;
HICON hIcon = NULL;
HRESULT hr;
OLECHAR *szCLSID;
DWORD dwType = 0;
TCHAR szName[MAX_PATH+1];
TCHAR szPathName[MAX_PATH+1];
HKEY hkeyObj;
HKEY hkeyDefIcon;
HKEY hkeyCLSID;
UINT nIndex;
hr = ::StringFromCLSID(clsid, &szCLSID);
if (!SUCCEEDED(hr))
return NULL;
// first, try for the real icon
if (RegOpenKeyEx(HKEY_CLASSES_ROOT, _T("clsid"), 0, KEY_READ, &hkeyCLSID) == ERROR_SUCCESS)
{
if (RegOpenKeyEx(hkeyCLSID, OLE2T(szCLSID), 0, KEY_READ, &hkeyObj) == ERROR_SUCCESS)
{
if (RegOpenKeyEx(hkeyObj, _T("DefaultIcon"), 0, KEY_READ, &hkeyDefIcon) == ERROR_SUCCESS)
{
DWORD dwCount;
dwCount = sizeof(szName);
if (RegQueryValueEx(hkeyDefIcon, NULL, NULL, &dwType, (BYTE*) szName, &dwCount) == ERROR_SUCCESS)
{
AfxGetIconInfo(szName, szPathName, nIndex);
// Load the icon
hIcon = ::ExtractIcon(AfxGetApp()->m_hInstance, szPathName, nIndex);
// ExtractIcon() failure case means NULL return
if (int(hIcon) == 1)
hIcon = NULL;
}
RegCloseKey(hkeyDefIcon);
}
RegCloseKey(hkeyObj);
}
RegCloseKey(hkeyCLSID);
}
// if we didn't get the real icon, try the default icon
if (hIcon == NULL)
{
if (RegOpenKeyEx(HKEY_CLASSES_ROOT, _T("DocShortcut"), 0, KEY_READ,&hkeyObj) == ERROR_SUCCESS)
{
if (RegOpenKeyEx(hkeyObj, _T("DefaultIcon"), 0, KEY_READ, &hkeyDefIcon) == ERROR_SUCCESS)
{
DWORD dwCount;
dwCount = sizeof(szName);
if (RegQueryValueEx(hkeyDefIcon, NULL, NULL, &dwType, (BYTE*) szName, &dwCount) == ERROR_SUCCESS)
{
AfxGetIconInfo(szName, szPathName, nIndex);
// Load the icon
hIcon = ::ExtractIcon(AfxGetApp()->m_hInstance, szPathName, nIndex);
// ExtractIcon() failure case means NULL return
if (int(hIcon) == 1)
hIcon = NULL;
}
RegCloseKey(hkeyDefIcon);
}
RegCloseKey(hkeyObj);
}
}
::CoTaskMemFree(szCLSID);
return hIcon;
}
/////////////////////////////////////////////////////////////////////////////
// COleClientItem creation helpers
void COleClientItem::UpdateItemType()
{
ASSERT_VALID(this);
ASSERT(m_lpObject != NULL);
// check for linked object
LPOLELINK lpOleLink = QUERYINTERFACE(m_lpObject, IOleLink);
if (lpOleLink != NULL)
{
lpOleLink->Release();
m_nItemType = OT_LINK;
return;
}
// check for static object
DWORD dwStatus;
if (m_lpObject->GetMiscStatus(DVASPECT_CONTENT, &dwStatus) == S_OK
&& (dwStatus & OLEMISC_STATIC) == 0)
{
m_nItemType = OT_EMBEDDED;
return;
}
// not not link, not embedding -- must be static
m_nItemType = OT_STATIC;
}
BOOL COleClientItem::FinishCreate(SCODE sc)
{
USES_CONVERSION;
ASSERT_VALID(this);
ASSERT(m_pView == NULL);
TRY
{
// m_lpObject is currently an IUnknown, convert to IOleObject
if (m_lpObject != NULL)
{
LPUNKNOWN lpUnk = m_lpObject;
m_lpObject = QUERYINTERFACE(lpUnk, IOleObject);
lpUnk->Release();
if (m_lpObject == NULL)
AfxThrowOleException(E_OUTOFMEMORY);
}
// check return code from create function
CheckGeneral(sc);
UpdateItemType();
// cache the IViewObject interface
m_lpViewObject = QUERYINTERFACE(m_lpObject, IViewObject2);
if (m_lpViewObject == NULL)
CheckGeneral(E_NOINTERFACE);
ASSERT(m_lpViewObject != NULL);
if (GetType() != OT_STATIC)
{
// setup for advises; we assume that OLE cleans them up properly
LPADVISESINK lpAdviseSink =
(LPADVISESINK)GetInterface(&IID_IAdviseSink);
ASSERT(lpAdviseSink != NULL);
CheckGeneral(m_lpObject->Advise(lpAdviseSink, &m_dwConnection));
ASSERT(m_dwConnection != 0);
// set up view advise
VERIFY(m_lpViewObject->SetAdvise(DVASPECT_CONTENT, 0, lpAdviseSink)
== S_OK);
// the server shows these in its user-interface
// (as document title and in File Exit menu)
m_lpObject->SetHostNames(T2COLE(AfxGetAppName()),
T2COLE(m_pDocument->GetTitle()));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -