📄 dsofauto.cpp
字号:
/***************************************************************************
* DSOFAUTO.CPP
*
* CDsoFramerControl: Automation interface for Binder Control
*
* Copyright ?999-2004; Microsoft Corporation. All rights reserved.
* Written by Microsoft Developer Support Office Integration (PSS DSOI)
*
* This code is provided via KB 311765 as a sample. It is not a formal
* product and has not been tested with all containers or servers. Use it
* for educational purposes only. See the EULA.TXT file included in the
* KB download for full terms of use and restrictions.
*
* THIS CODE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
*
***************************************************************************/
#include "dsoframer.h"
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl - _FramerControl Implementation
//
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::Activate
//
// Activate the current embedded document (i.e, forward focus).
//
STDMETHODIMP CDsoFramerControl::Activate()
{
HRESULT hr;
ODS("CDsoFramerControl::Activate\n");
if (m_fInControlActivate)
return S_FALSE;
// Don't allow recursion of this function or we could get stuck in
// loop trying to constantly grab focus.
m_fInControlActivate = TRUE;
// All we need to do is grab focus. This will tell the host to
// UI activate our OCX, set focus to our window, and set this control
// as the active component with the hook manager.
hr = UIActivate(TRUE);
// Invalidate windows to update painting...
if (SUCCEEDED(hr))
InvalidateAllChildWindows(m_hwnd);
m_fInControlActivate = FALSE;
return hr;
}
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::get_ActiveDocument
//
// Returns the automation object currently embedded.
//
// Since we only support a single instance at a time, it might have been
// better to call this property Object or simply Document, but VB reserves
// the first name for use by the control extender, and IE reserves the second
// in its extender, so we decided on the "Office sounding" name. ;-)
//
STDMETHODIMP CDsoFramerControl::get_ActiveDocument(IDispatch** ppdisp)
{
HRESULT hr = DSO_E_DOCUMENTNOTOPEN;
IUnknown* punk;
ODS("CDsoFramerControl::get_ActiveDocument\n");
CHECK_NULL_RETURN(ppdisp, E_POINTER); *ppdisp = NULL;
// Get IDispatch from open document object.
if ((m_pDocObjFrame) && (punk = (IUnknown*)(m_pDocObjFrame->GetActiveObject())))
{
// Cannot access object if in print preview..
if (m_pDocObjFrame->InPrintPreview())
return ProvideErrorInfo(DSO_E_INMODALSTATE);
// Ask ip active object for IDispatch interface. If it is not supported on
// active object interface, try to get it from OLE object iface...
if (FAILED(hr = punk->QueryInterface(IID_IDispatch, (void**)ppdisp)) &&
(punk = (IUnknown*)(m_pDocObjFrame->GetOleObject())))
{
hr = punk->QueryInterface(IID_IDispatch, (void**)ppdisp);
}
ASSERT(SUCCEEDED(hr));
}
return ProvideErrorInfo(hr);
}
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::ExecOleCommand
//
// Allows caller to pass commands to embedded object via IOleCommandTarget and
// gives access to a few extra commands to extend functionality for certain object
// types (not all objects may support all commands).
//
STDMETHODIMP CDsoFramerControl::ExecOleCommand(LONG OLECMDID, VARIANT Options, VARIANT* vInParam, VARIANT* vInOutParam)
{
HRESULT hr = E_INVALIDARG;
DWORD dwOptions = (DWORD)LONG_FROM_VARIANT(Options, 0);
TRACE1("CDsoFramerControl::DoOleCommand(%d)\n", OLECMDID);
// Cannot access object if in modal condition...
if ((m_fModalState) || (m_fNoInteractive))
return ProvideErrorInfo(DSO_E_INMODALSTATE);
// Handle some custom commands that don't need doc open to call...
switch (OLECMDID)
{
case OLECMDID_RESETFRAMEHOOK:
{
LONG lhwnd = (DWORD)LONG_FROM_VARIANT(*vInParam, 0);
return ResetFrameHook((HWND)lhwnd);
}
case OLECMDID_LOCKSERVER:
if (BOOL_FROM_VARIANT(Options, TRUE) == FALSE)
return put_LockServer(VARIANT_FALSE);
}
// The rest require a doc object loaded first...
CHECK_NULL_RETURN(m_pDocObjFrame, ProvideErrorInfo(DSO_E_DOCUMENTNOTOPEN));
switch (OLECMDID)
{
case OLECMDID_GETDATAFORMAT:
// If requesting special data get...
hr = m_pDocObjFrame->HrGetDataFromObject(vInParam, vInOutParam);
break;
case OLECMDID_SETDATAFORMAT:
// If requesting special data set...
hr = m_pDocObjFrame->HrSetDataInObject(vInParam, vInOutParam, BOOL_FROM_VARIANT(Options, TRUE));
break;
case OLECMDID_LOCKSERVER: // optional lock on server...
if (BOOL_FROM_VARIANT(Options, FALSE))
hr = put_LockServer(VARIANT_TRUE);
break;
case OLECMDID_NOTIFYACTIVE:
if (vInParam) // Force notify server that it should be active...
{
m_pDocObjFrame->OnNotifyAppActivate(BOOL_FROM_VARIANT(*vInParam, FALSE), 0);
hr = S_OK;
}
break;
default:
// Do normal IOleCommandTarget call on object...
// If options was not passed as long, but as bool, we expect the caller meant to
// specify if user should be prompted or not, so update the options to allow the
// assuption to still work as expected (this is for compatibility)...
if ((dwOptions == 0) && ((DsoPVarFromPVarRef(&Options)->vt & 0xFF) == VT_BOOL))
dwOptions = (BOOL_FROM_VARIANT(Options, FALSE) ? OLECMDEXECOPT_PROMPTUSER : OLECMDEXECOPT_DODEFAULT);
// Ask object server to do the command...
hr = m_pDocObjFrame->DoOleCommand(OLECMDID, dwOptions, vInParam, vInOutParam);
}
return hr;
}
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::CreateNew
//
// Creates a new document object based on the passed in ProgID or Template.
// ProgID should map to the "document" object, such as "Word.Document",
// "Excel.Sheet", "PowerPoint.Slide", etc. A Template name should be full
// path to the file, whether local, UNC, or HTTP path. No relative paths.
//
STDMETHODIMP CDsoFramerControl::CreateNew(BSTR ProgIdOrTemplate)
{
HRESULT hr;
CLSID clsid;
HCURSOR hCur;
IStorage *pstgTemplate = NULL;
LPWSTR pwszTempFile = NULL;
TRACE1("CDsoFramerControl::CreateNew(%S)\n", ProgIdOrTemplate);
// Check the string to make sure a valid item is passed...
if (!(ProgIdOrTemplate) || (SysStringLen(ProgIdOrTemplate) < 4))
return E_INVALIDARG;
// Cannot create object if we are not activate yet, or if in modal condition...
if (!(m_fInPlaceActive) || (m_fModalState))
return ProvideErrorInfo(DSO_E_INMODALSTATE);
// Make sure any open document is closed first...
if ((m_pDocObjFrame) && FAILED(hr = Close()))
return hr;
// Make sure we are the active component for this process...
if (FAILED(hr = Activate())) return hr;
// Let's make a doc frame for ourselves...
m_pDocObjFrame = CDsoDocObject::CreateInstance((IDsoDocObjectSite*)&m_xDsoDocObjectSite);
if (!(m_pDocObjFrame)) return E_OUTOFMEMORY;
// Start a wait operation to notify user...
hCur = SetCursor(LoadCursor(NULL, IDC_WAIT));
m_fInDocumentLoad = TRUE;
// If the string passed looks like a URL, it is a web template. We need
// to download it to temp location and use for new object...
if (LooksLikeHTTP(ProgIdOrTemplate) &&
GetTempPathForURLDownload(ProgIdOrTemplate, &pwszTempFile))
{
// Ask URLMON to download the file...
if (FAILED(hr = URLDownloadFile(NULL, ProgIdOrTemplate, pwszTempFile)))
{
DsoMemFree(pwszTempFile); pwszTempFile = NULL;
goto error_out;
}
// If that worked, switch out the name of the template to local file...
ProgIdOrTemplate = SysAllocString(pwszTempFile);
}
// If the string is path to file, then it must be a template. It must be
// a storage file with CLSID associated with it, like any Office templates
// (.dot,.xlt,.pot,.vst,etc.), and path must be fully qualified...
if (LooksLikeUNC(ProgIdOrTemplate) || LooksLikeLocalFile(ProgIdOrTemplate))
{
if ((hr = StgIsStorageFile(ProgIdOrTemplate)) != S_OK)
{
hr = (FAILED(hr) ? hr : STG_E_NOTFILEBASEDSTORAGE);
goto error_out;
}
// Open the template for read access only...
hr = StgOpenStorage(ProgIdOrTemplate, NULL,
(STGM_READ | STGM_SHARE_DENY_WRITE | STGM_TRANSACTED),
NULL, 0, &pstgTemplate);
GOTO_ON_FAILURE(hr, error_out);
// We get the CLSID from the template...
hr = ReadClassStg(pstgTemplate, &clsid);
if (FAILED(hr) || (clsid == GUID_NULL))
{
hr = (FAILED(hr) ? hr : STG_E_OLDFORMAT);
goto error_out;
}
// Otherwise the string passed is assumed a ProgID...
}
else if (FAILED(CLSIDFromProgID(ProgIdOrTemplate, &clsid)))
{
hr = DSO_E_INVALIDPROGID;
goto error_out;
}
// If we are here, we must have a valid CLSID for the object...
ASSERT(clsid != GUID_NULL);
// If we had delayed the frame hook, we should set it up now...
if (!(m_pHookManager) && FDelayFrameHookSet())
{
m_pHookManager = CDsoFrameHookManager::RegisterFramerControl(m_hwndParent, m_hwnd);
if (!m_pHookManager) {hr = DSO_E_FRAMEHOOKFAILED; goto error_out;}
}
SEH_TRY
// If we are loading a template, init the storage before the create...
if (pstgTemplate)
{
hr = m_pDocObjFrame->CreateDocObject(pstgTemplate);
}
else
{
// Create a new doc object and IP activate...
hr = m_pDocObjFrame->CreateDocObject(clsid);
}
// If the call worked, we can activate it...
if (SUCCEEDED(hr))
{
EnableDropFile(FALSE);
if (!m_fShowToolbars)
m_pDocObjFrame->OnNotifyChangeToolState(FALSE);
hr = m_pDocObjFrame->IPActivateView();
}
SEH_EXCEPT(hr)
// Force a close if an error occurred...
if (FAILED(hr))
{
error_out:
m_fFreezeEvents = TRUE;
Close();
m_fFreezeEvents = FALSE;
hr = ProvideErrorInfo(hr);
}
else
{
// Fire the OnDocumentOpened event...
VARIANT rgargs[2];
rgargs[0].vt = VT_DISPATCH; get_ActiveDocument(&(rgargs[0].pdispVal));
rgargs[1].vt = VT_BSTR; rgargs[1].bstrVal = NULL;
RaiseAutomationEvent(DSOF_DISPID_DOCOPEN, 2, rgargs);
VariantClear(&rgargs[0]);
// Ensure we are active control...
Activate();
// Redraw the caption as needed...
RedrawCaption();
}
m_fInDocumentLoad = FALSE;
SetCursor(hCur);
SAFE_RELEASE_INTERFACE(pstgTemplate);
// Delete the temp file used in the URL download (if any)...
if (pwszTempFile)
{
FPerformShellOp(FO_DELETE, pwszTempFile, NULL);
DsoMemFree(pwszTempFile);
SysFreeString(ProgIdOrTemplate);
}
return hr;
}
////////////////////////////////////////////////////////////////////////
// CDsoFramerControl::Open
//
// Creates a document object based on a file or URL. This simulates an
// "open", but preserves the correct OLE embedding activation required
// by ActiveX Documents. Opening directly from a file is not recommended.
// We keep a lock on the original file (unless opened read-only) so the
// user cannot tell we don't have the file "open".
//
// The alternate ProgID allows us to open a file that is not associated
// with an DocObject server (like *.asp) with the server specified. Also
// the username/password are for web access (if Document is a URL).
//
STDMETHODIMP CDsoFramerControl::Open(VARIANT Document, VARIANT ReadOnly, VARIANT ProgId, VARIANT WebUsername, VARIANT WebPassword)
{
HRESULT hr;
LPWSTR pwszDocument = LPWSTR_FROM_VARIANT(Document);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -