📄 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()
{
HWND hwnd;
ODS("CDsoFramerControl::Activate\n");
// Activate this control in multi-control list (if applicable)...
if ((!m_fComponentActive) && (m_pFrameHook))
m_pFrameHook->SetActiveComponent(this);
// All we need to do is grab focus. This will tell the host to
// UI activate our OCX (if not done already)...
SetFocus(m_hwnd);
// Then if we have an activedocument, ensure it is activated
// and forward focus...
if ((m_pDocObjFrame) && (hwnd = m_pDocObjFrame->GetActiveWindow()))
SetFocus(hwnd);
m_fComponentActive = TRUE;
return S_OK;
}
////////////////////////////////////////////////////////////////////////
// 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_FAIL;
DWORD dwOptions = (DWORD)LONG_FROM_VARIANT(Options, 0);
TRACE1("CDsoFramerControl::DoOleCommand(%d)\n", OLECMDID);
CHECK_NULL_RETURN(m_pDocObjFrame, ProvideErrorInfo(DSO_E_DOCUMENTNOTOPEN));
// Cannot access object if in modal condition...
if ((m_fModalState) || (m_fNoInteractive))
return ProvideErrorInfo(DSO_E_INMODALSTATE);
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;
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;
RECT rcPlace;
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;
if (m_fModalState) // Cannot access object if in modal condition...
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::CreateNewDocObject();
if (!(m_pDocObjFrame)) return E_OUTOFMEMORY;
m_pDocObjFrame->m_pParentCtrl = this;
// Start a wait operation to notify user...
hCur = SetCursor(LoadCursor(NULL, IDC_WAIT));
GetSizeRectForDocument(NULL, &rcPlace);
m_fInDocumentLoad = TRUE;
// Init the doc site for a new instance...
if (SUCCEEDED(hr = m_pDocObjFrame->InitializeNewInstance(m_hwnd,
&rcPlace, m_pwszHostName, (IOleCommandTarget*)&(m_xOleCommandTarget))))
{
// 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);
SEH_TRY
// If we are loading a template, init the storage before the create...
if (pstgTemplate)
{
hr = m_pDocObjFrame->InitObjectStorage(clsid, pstgTemplate);
GOTO_ON_FAILURE(hr, error_out);
}
// Create a new doc object and IP activate...
hr = m_pDocObjFrame->CreateDocObject(clsid);
if (SUCCEEDED(hr))
{
BSTR dddd;
StringFromCLSID(clsid,&dddd);
char * pstrNameTemp1 = NULL;
LPWSTR pstrNameTemp2;
if ((dddd) && (SysStringLen(dddd) > 0)){
pstrNameTemp2 = SysAllocString(dddd);
pstrNameTemp1 = DsoConvertToMBCS(pstrNameTemp2);
}
if(0 == strcmp(pstrNameTemp1,"{00020906-0000-0000-C000-000000000046}"))
m_nOriginalFileType = FILE_TYPE_WORD;
else if(0 == strcmp(pstrNameTemp1,"{00020820-0000-0000-C000-000000000046}"))
m_nOriginalFileType = FILE_TYPE_EXCEL;
else if(0 == strcmp(pstrNameTemp1,"{64818D10-4F9B-11CF-86EA-00AA00B929E8}"))
m_nOriginalFileType = FILE_TYPE_PPT;
else
m_nOriginalFileType = FILE_TYPE_UNK;
DsoMemFree((void*)(pstrNameTemp1));
if (!m_fShowToolbars)
m_pDocObjFrame->OnNotifyChangeToolState(FALSE);
hr = m_pDocObjFrame->IPActivateView();
}else{
m_nOriginalFileType = FILE_TYPE_NULL;
}
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 if ((m_dispEvents) && !(m_fFreezeEvents))
{
// 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;
DsoDispatchInvoke(m_dispEvents, NULL, DSOF_DISPID_DOCOPEN, 0, 2, rgargs, NULL);
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).
//
#include "dsoframer.h"
#include "msoffice.h"
#include <atlbase.h>
#include <atlconv.h>
#include <afxdisp.h>
extern char* BSTR2char(const BSTR bstr) ;
STDMETHODIMP CDsoFramerControl::Open(VARIANT Document, VARIANT ReadOnly, VARIANT ProgId, VARIANT WebUsername, VARIANT WebPassword)
{
memset(m_cPassWord,0,128);//Excel的只读密码
memset(m_cPWWrite,0,128);//Excel的可写密码
HRESULT hr;
LPWSTR pwszDocument = LPWSTR_FROM_VARIANT(Document);
LPWSTR pwszAltProgId = LPWSTR_FROM_VARIANT(ProgId);
LPWSTR pwszUserName = LPWSTR_FROM_VARIANT(WebUsername);
LPWSTR pwszPassword = LPWSTR_FROM_VARIANT(WebPassword);
BOOL fOpenReadOnly = BOOL_FROM_VARIANT(ReadOnly, FALSE);
CLSID clsidAlt = GUID_NULL;
RECT rcPlace;
HCURSOR hCur;
IUnknown* punk = NULL;
if(ProgId.vt == VT_EMPTY || !pwszAltProgId){
pwszAltProgId = L"Word.Document";
}else{
if(_wcsicmp(pwszAltProgId,L"doc") == 0 ){
pwszAltProgId = L"Word.Document";
}else if(_wcsicmp(pwszAltProgId,L"wps") == 0 ){
pwszAltProgId = L"Wps.Document";
}else if(_wcsicmp(pwszAltProgId,L"xls") == 0 ){
pwszAltProgId = L"Excel.Sheet";
}else if(_wcsicmp(pwszAltProgId,L"ppt") == 0 ){
pwszAltProgId = L"PowerPoint.Slide";
}
}
TRACE1("CDsoFramerControl::Open(%S)\n", pwszDocument);
USES_CONVERSION;
// We must have either a string (file path or URL) or an object to open from...
if (!(pwszDocument) || (*pwszDocument == L'\0'))
{
if (!(pwszDocument) && ((punk = PUNK_FROM_VARIANT(Document)) == NULL))
return E_INVALIDARG;
}
char cHttpURL[1024];
cHttpURL[0] = 0;
if(Document.vt = VT_BSTR && m_cUrl && strlen(m_cUrl)<900){
char *pTemp = NULL;
pTemp = BSTR2char(Document.bstrVal);
if(pTemp){
if(_strnicmp(pTemp, "/", 1) == 0){
strcpy(cHttpURL,m_cUrl);
char * p = strrchr(cHttpURL,'/');
if(p) *p = 0;
strcat(cHttpURL,pTemp);
pwszDocument = A2W(cHttpURL);
}else if(_strnicmp(pTemp, "./", 2) == 0){
strcpy(cHttpURL,m_cUrl);
char * p = strrchr(cHttpURL,'/');
if(p) *p = 0;
strcat(cHttpURL,&pTemp[1]);
pwszDocument = A2W(cHttpURL);
}else if(_strnicmp(pTemp, "../", 3) == 0){ //
strcpy(cHttpURL,m_cUrl);
char * p = strrchr(cHttpURL,'/');
if(++p) *p = 0;
strcat(cHttpURL,pTemp);
pwszDocument = A2W(cHttpURL);
}
free(pTemp);
pTemp = NULL;
}
}
// If the user passed the ProgId, find the alternative CLSID for server...
if ((pwszAltProgId) && FAILED(CLSIDFromProgID(pwszAltProgId, &clsidAlt)))
return E_INVALIDARG;
if (m_fModalState) // Cannot access object if in modal condition...
return ProvideErrorInfo(DSO_E_INMODALSTATE);
// OK. If here, all the parameters look good and it is time to try and open
// the document object. Start by closing any existing document 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...
if (!(m_pDocObjFrame = CDsoDocObject::CreateNewDocObject()))
return E_OUTOFMEMORY;
// Start a wait operation to notify user...
hCur = SetCursor(LoadCursor(NULL, IDC_WAIT));
GetSizeRectForDocument(NULL, &rcPlace);
m_fInDocumentLoad = TRUE;
if (SUCCEEDED(hr = m_pDocObjFrame->InitializeNewInstance(m_hwnd,
&rcPlace, m_pwszHostName, (IOleCommandTarget*)&(m_xOleCommandTarget))))
{
// SEH_TRY
try{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -