⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dsofdocobj.cpp

📁 用于在线office文档编辑的控件。可以在线新建文档、修改文档
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/***************************************************************************
 * DSOFDOCOBJ.CPP
 *
 * CDsoDocObject: ActiveX Document Single Instance Frame/Site Object
 *
 *  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"
#include "xmlhttpclient.h"

////////////////////////////////////////////////////////////////////////
// CDsoDocObject - The DocObject Site Class
//
//  This class wraps the functionality for DocObject hosting. Right now
//  we are setup for one active site at a time, but this could be changed
//  to allow multiple sites (although only one could be UI active at any
//  given time).
//
CDsoDocObject::CDsoDocObject()
{
	ODS("CDsoDocObject::CDsoDocObject\n");
	m_bNewCreate = TRUE;
	m_pParentCtrl = NULL;
	m_hwnd = NULL;           
	m_hwndCtl = NULL;        
	m_pcmdCtl = NULL;        
	m_rcViewRect.left = m_rcViewRect.top = m_rcViewRect.right = m_rcViewRect.bottom = 0;     

	m_pwszSourceFile = NULL; 
	m_pstgSourceFile = NULL; 
	m_pmkSourceObject = NULL;
	m_idxSourceName = 0;  

	m_pstgroot = NULL;       
	m_pstgfile = NULL;       
	m_pstmview = NULL;       

	m_pwszWebResource = NULL;
	m_pstmWebResource = NULL;
	m_punkRosebud = NULL;    
	m_pwszUsername = NULL;   
	m_pwszPassword = NULL;   
	m_pwszHostName = NULL;   

	memset(&m_clsidObject, 0, sizeof(CLSID));

	m_pole = NULL;       
	m_pipobj = NULL;     
	m_pipactive = NULL;  
	m_pdocv = NULL;      
	m_pcmdt = NULL;      
	m_pprtprv = NULL;    

	m_hMenuActive = NULL;    
	m_hMenuMerged = NULL;    
	m_holeMenu = NULL;       
	m_hwndMenuObj = NULL;    
	m_hwndIPObject = NULL;    
	m_hwndUIActiveObj = NULL; 
	m_dwObjectThreadID = 0;
	memset(&m_bwToolSpace, 0, sizeof(BORDERWIDTHS));

	m_fDisconnectOnQuit = 0;
	m_fAppWindowActive = 0;
	m_fOpenReadOnly = 0;
	m_fObjectInModalCondition = 0;
	m_fObjectIPActive = 0;
	m_fObjectUIActive = 0;
	m_fObjectActivateComplete = 0;
	m_fLockedServerRunning = 0;
	m_fLoadedFromAuto = 0;
	m_fInClose = 0;
	m_cRef = 1;
	m_fDisplayTools = TRUE;
}

CDsoDocObject::~CDsoDocObject(void)
{
	ODS("CDsoDocObject::~CDsoDocObject\n");
	if (m_pole)	Close();
	if (m_hwnd) DestroyWindow(m_hwnd);

	SAFE_FREESTRING(m_pwszUsername);
	SAFE_FREESTRING(m_pwszPassword);
	SAFE_FREESTRING(m_pwszHostName);

	SAFE_RELEASE_INTERFACE(m_punkRosebud);
	SAFE_RELEASE_INTERFACE(m_pcmdCtl);
    SAFE_RELEASE_INTERFACE(m_pstgroot);
}

////////////////////////////////////////////////////////////////////////
// CDsoDocObject::InitializeNewInstance
//
//  Sets up the docobject site. We must a control site to attach to and
//  a bounding rect. The IOleCommandTarget is used to forward toolbar
//  commands back to the host if a user selects one.
//
STDMETHODIMP CDsoDocObject::InitializeNewInstance(HWND hwndCtl, LPRECT prcPlace, LPWSTR pwszHost, IOleCommandTarget* pcmdCtl)
{
	HRESULT hr = E_UNEXPECTED;
	WNDCLASS wndclass;

    ODS("CDsoDocObject::InitializeNewInstance()\n");

 // As an AxDoc site, we need a valid parent window...
	if ((!hwndCtl) || (!IsWindow(hwndCtl)))
		return hr;

 // Create a temp storage for this docobj site (if one already exists, bomb out)...
	if ((m_pstgroot) || FAILED(hr = StgCreateDocfile(NULL,	STGM_TRANSACTED | STGM_READWRITE |
			STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_DELETEONRELEASE, 0, &m_pstgroot)))
		return hr;

 // If our site window class has not been registered before, we should register it...

 // This is protected by a critical section just for fun. The fact we had to single
 // instance the OCX because of the host hook makes having multiple instances conflict here
 // very unlikely. However, that could change sometime, so better to be safe than sorry.
	EnterCriticalSection(&v_csecThreadSynch);

	if (GetClassInfo(v_hModule, "DSOFramerDocWnd", &wndclass) == 0)
	{
		memset(&wndclass, 0, sizeof(WNDCLASS));
		wndclass.style          = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
		wndclass.lpfnWndProc    = CDsoDocObject::FrameWindowProc;
		wndclass.hInstance      = v_hModule;
		wndclass.hCursor        = LoadCursor(NULL, IDC_ARROW);
		wndclass.lpszClassName  = "DSOFramerDocWnd";
		if (RegisterClass(&wndclass) == 0)
			hr = E_WIN32_LASTERROR;
	}

	LeaveCriticalSection(&v_csecThreadSynch);
	if (FAILED(hr)) return hr;
	
 // Save the place RECT (and validate as needed)...
	CopyRect(&m_rcViewRect, prcPlace);
	if (m_rcViewRect.top > m_rcViewRect.bottom)	{m_rcViewRect.top = 0; m_rcViewRect.bottom = 0;}
	if (m_rcViewRect.left > m_rcViewRect.right)	{m_rcViewRect.left = 0; m_rcViewRect.right = 0;}

 // Create our site window at the give location (we are child of the control window)...
	m_hwnd = CreateWindowEx(0, "DSOFramerDocWnd", NULL, WS_CHILD | WS_VISIBLE,
                    m_rcViewRect.left, m_rcViewRect.top,
					(m_rcViewRect.right - m_rcViewRect.left),
					(m_rcViewRect.bottom - m_rcViewRect.top),
                    hwndCtl, NULL, v_hModule, NULL);


	if (!m_hwnd) return E_OUTOFMEMORY;

	SetWindowLong(m_hwnd, GWL_USERDATA, (LONG)this);

	m_hwndCtl = hwndCtl;
    m_pwszHostName = DsoCopyString(((pwszHost) ? pwszHost : L"DsoFramerControl"));
	SAFE_SET_INTERFACE(m_pcmdCtl, pcmdCtl);
	return S_OK;
}

////////////////////////////////////////////////////////////////////////
// CDsoDocObject::InitObjectStorage
//
//  Creates and fills the 
//
STDMETHODIMP CDsoDocObject::InitObjectStorage(REFCLSID rclsid, IStorage *pstg)
{
    HRESULT hr;
    ODS("CDsoDocObject::InitObjectStorage()\n");
    CHECK_NULL_RETURN(pstg, E_POINTER);

 // Create a new storage for this CLSID...
	if (FAILED(hr = CreateObjectStorage(rclsid)))
		return hr;

 // Copy data into the new storage and commit the change...
	hr = pstg->CopyTo(0, NULL, NULL, m_pstgfile);
	if (SUCCEEDED(hr)) hr = m_pstgfile->Commit(STGC_OVERWRITE);

    return hr;
}

////////////////////////////////////////////////////////////////////////
// CDsoDocObject::CreateDocObject
//
//  This does the actual embedding. It is called no matter how you load
//  an object, and does some checking to make sure the CLSID is for a
//  a docobj server. If the function succeeds, we have an embedded object.
//  To activate and show the object, you must call IPActivateView().
//
STDMETHODIMP CDsoDocObject::CreateDocObject(REFCLSID rclsid)
{
	HRESULT             hr;
	BOOL                fInitNew;
	CLSID               clsid;
	DWORD               dwMiscStatus = 0;
    IOleObject*         pole    = NULL;
    IPersistStorage*    pipstg  = NULL;

    ODS("CDsoDocObject::CreateDocObject()\n");


	ASSERT(!(m_pole));
	IUnknown * pUnk=NULL;
	if(::GetActiveObject(rclsid,NULL,&pUnk)  == S_OK){
		ODS("CDsoDocObject: Object is aleady open\n");
		m_bNewCreate = FALSE;
	}else{
		ODS("CDsoDocObject: Object is new\n");
		m_bNewCreate = TRUE;
	}
 // Don't load if an object has already been loaded...
    if (m_pole) return E_UNEXPECTED;

 // First, check the server to make sure it is AxDoc server...
	if (FAILED(hr = ValidateDocObjectServer(rclsid)))
		return hr;

 // If we haven't loaded a storage, create a new one and remember to
 // call InitNew (instead of Load) later on...
	if ((fInitNew = (!m_pstgfile)) && FAILED(hr = CreateObjectStorage(rclsid)))
		return hr;

 // It is possible that someone picked an older ProgId/CLSID that
 // will AutoConvert on CoCreate, so fix up the storage with the
 // new CLSID info. We we actually call CoCreate on the new CLSID...
	if (fInitNew && SUCCEEDED(OleGetAutoConvert(rclsid, &clsid)))
	{
		OleDoAutoConvert(m_pstgfile, &clsid);
	}
	else clsid = rclsid;

 // We are ready to create an instance. Call CoCreate to make an
 // inproc handler and ask for IOleObject (all docobjs must support this)...
    if (FAILED(hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC, IID_IOleObject, (void**)&pole)))
		return hr;

 // Do a quick check to see if server wants us to set client site before the load...
	if (SUCCEEDED(hr = pole->GetMiscStatus(DVASPECT_CONTENT, &dwMiscStatus)) &&
		(dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST))
		pole->SetClientSite((IOleClientSite*)&m_xOleClientSite);

 // Load up the bloody thing...
	if (SUCCEEDED(hr = pole->QueryInterface(IID_IPersistStorage, (void**)&pipstg)))
	{
     // Remember to InitNew if this is a new storage...			
		hr = ((fInitNew) ? pipstg->InitNew(m_pstgfile) : pipstg->Load(m_pstgfile));
		pipstg->Release();
	}

 // Assuming all the above worked we should have an OLE Embeddable
 // object and should finish the initialization (set object running)...
	if (SUCCEEDED(hr))
	{
	 // Save the IOleObject* and do a disconnect on quit...
		m_fDisconnectOnQuit = TRUE;
		m_pole = pole;

	 // Make sure the object is running (uses IRunnableObject)...
		hr = EnsureOleServerRunning(TRUE);

		if (SUCCEEDED(hr))
		{
		 // If we didn't do so already, set our client site...
			if (!(dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST))
				m_pole->SetClientSite((IOleClientSite*)&m_xOleClientSite);

		 // Set the host names and then lock running...
			m_pole->SetHostNames(m_pwszHostName, m_pwszHostName);

		 // Keep server CLSID for this object
			m_clsidObject = clsid;

         // Ask object to save (if dirty)...
            if (IsStorageDirty()) SaveObjectStorage();
		}
	}

 // If we hit an error, cleanup (release should free the obj)...
	if (FAILED(hr))
	{
		if (dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)
			pole->SetClientSite(NULL);

		pole->Release();
		m_pole = NULL;
	}

    return hr;
}

////////////////////////////////////////////////////////////////////////
// CDsoDocObject::LoadStorageFromFile
//
//  Loads the internal IStorage from a file (local or UNC).
//
//  We handle three types of files: (1) BIFF files, which will just copy
//  their storage into our own; (2) non-BIFF files that are associated
//  with Office and can be loaded by IMoniker; and (3) non-BIFF files 
//  that are not associated with Office but may be loaded in Office using 
//  IPersistFile and then IPersistStorage (if an alternate CLSID is given), 
//
//  We do a special check for HTML/TXT files because they are associated
//  with IE, and we don't support IE files per se. Instead, you should pass
//  an alternate CLSID for the Office app you want to open that file in.
//
STDMETHODIMP CDsoDocObject::LoadStorageFromFile(LPWSTR pwszFile, REFCLSID rclsid, BOOL fReadOnly)
{
	HRESULT			hr;
	CLSID           clsid;
	CLSID           clsidConv;
	DWORD           dwBindFlgs;
	IStorage        *pstg    = NULL;
	IBindCtx		*pbctx   = NULL;
	IMoniker		*pmkfile = NULL;
	IPersistStorage *pipstg  = NULL;
	BOOL fLoadFromAltCLSID   = (rclsid != GUID_NULL);

	if (!(pwszFile) || ((*pwszFile) == L'\0'))
		return E_INVALIDARG;

	TRACE1("CDsoDocObject::LoadStorageFromFile(%S)\n", pwszFile);

 // First. we'll try to find the associated CLSID for the given file,
 // and then set it to the alternate if not found. If we don't have a
 // CLSID by the end of this, because user didn't specify alternate
 // and GetClassFile failed, then we error out...
    if (FAILED(GetClassFile(pwszFile, &clsid)) && !(fLoadFromAltCLSID))
		return DSO_E_INVALIDSERVER;

 // We should try to load from alternate CLSID if provided one...
    if (fLoadFromAltCLSID) clsid = rclsid;

 // We should also handle auto-convert to start "newest" server...
	if (SUCCEEDED(OleGetAutoConvert(clsid, &clsidConv)))
		clsid = clsidConv;

 // Validate that we have a DocObject server...
	if ((clsid == GUID_NULL) || FAILED(ValidateDocObjectServer(clsid)))
		return DSO_E_INVALIDSERVER;

 // We should have a CLSID, and can now create our substorage...
	if (FAILED(hr = CreateObjectStorage(clsid)))
		return hr;

 // Check for IE cache items since these are read-only as far as user is concerned...
    if (FIsIECacheFile(pwszFile)) fReadOnly = TRUE;

    dwBindFlgs = (STGM_TRANSACTED | STGM_SHARE_DENY_WRITE | (fReadOnly ? STGM_READ : STGM_READWRITE));

 // If these are native Office BiFF files, we can streamline the process to
 // copy the main storage into our sub-storage, without any involvement from
 // the server to fill our substorage. This will account for most Office loads...
	if (SUCCEEDED(hr = StgOpenStorage(pwszFile, NULL, dwBindFlgs, NULL, 0, &pstg)))
	{
		hr = pstg->CopyTo(0, NULL, NULL, m_pstgfile);
		if (SUCCEEDED(hr)) m_pstgfile->Commit(STGC_OVERWRITE);

 // Should that fail, we have to do things the more "formal" way (asking server
 // to properly save itself into our substorage)...
	}
	else if (fLoadFromAltCLSID)
	{
	 // If we are loading using an alternate CLSID that is either associated
     // with another app or is a non-Structured Storage doc not belonging to
     // to Office, then we have to explictily create an instance of the
     // alternate server (not the inproc handler), and load using IPersistFile,
     // then ask the server to save itself as OLE object using IPersistStorage.

	 // This is an expensive way to copy a storage, so we only do this when
	 // we are forced to use the alternate CLSID. This will typically be 
	 // the case for files like *.htm or *.asp that are not associated with
	 // Office, but can be opened in Office...
		IPersistFile *pipf;

		if (SUCCEEDED(hr = CoCreateInstance(clsid, NULL, CLSCTX_SERVER, 
			    IID_IPersistFile, (void**)&pipf)))
		{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -