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

📄 dsofdocobj.cpp

📁 用于在线office文档编辑的控件。可以在线新建文档、修改文档
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    SAFE_RELEASE_INTERFACE(m_pdocv);
    SAFE_RELEASE_INTERFACE(m_pipobj);

    return hr;
}

////////////////////////////////////////////////////////////////////////
// CDsoDocObject::UIActivateView
//
//  UI Activates/Deactivates the object as needed.
//
STDMETHODIMP CDsoDocObject::UIActivateView(BOOL fFocus)
{
    HRESULT hr = S_FALSE;
    TRACE1("CDsoDocObject::UIActivateView(%d)\n", fFocus);

	if (m_pdocv)
        hr = m_pdocv->UIActivate(fFocus);

	return hr;
}

////////////////////////////////////////////////////////////////////////
// CDsoDocObject::SaveDefault
//
//  Saves the open object back to the original open location (unless it
//  was opened read-only, or is a new object). There are three types of
//  loaded doc objects we can save: (1) Files obtained by URL write bind
//  via MSDAIPP; (2) Files opened from local file source; and (3) Objects
//  already running or files linked to via OLE moniker obtained by an
//  Automation instance passed to us in Open. This function determines
//  which type we should do and call the right code for that type.
//
STDMETHODIMP CDsoDocObject::SaveDefault()
{
	HRESULT	hr = DSO_E_NOTBEENSAVED;

 // We can't do  save default if file was open read-only,
 // caller must do save with new file name...
    if (IsReadOnly()) return DSO_E_DOCUMENTREADONLY;

 // If we have a URL (write-access) resource, do MSDAIPP save...
	if (m_pstmWebResource)
	{
		hr = SaveStorageToURL(NULL, TRUE, NULL, NULL);
	}
 // Else if it is local file, do a local save...
	else if (m_pwszSourceFile)
	{
		hr = SaveStorageToFile(NULL, TRUE);
	}
 // If opened by moniker, try to get storage for object and save there...
    else if ((m_pmkSourceObject) && (m_pstgfile))
    {
        IBindCtx *pbc;
        IStorage *pstg;

     // First save the current state of the object in the internal
     // storage for the control and then make a bind context to access
     // the storage for the original source object (which may be file or other object)...
        if (SUCCEEDED(hr = SaveObjectStorage()) &&
            SUCCEEDED(hr = CreateBindCtx(NULL, &pbc)))
        {
            BIND_OPTS bndopt;
            bndopt.cbStruct = sizeof(BIND_OPTS);
            bndopt.grfFlags = BIND_MAYBOTHERUSER;
            bndopt.grfMode = (STGM_READWRITE | STGM_TRANSACTED | STGM_SHARE_DENY_WRITE);
            bndopt.dwTickCountDeadline = 6000;

            hr = pbc->SetBindOptions(&bndopt);
            ASSERT(SUCCEEDED(hr));

         // Ask moniker for the original storage and save our data to it (by copy).  
         // It is possible this can fail if orginal storage is file open with exclusive
         // access, or if moniker was for non-saved object that is no longer running... 
            hr = m_pmkSourceObject->BindToStorage(pbc, NULL, IID_IStorage, (void**)&pstg);
            if (SUCCEEDED(hr))
            {
                hr = m_pstgfile->CopyTo(0, NULL, NULL, pstg);
                if (SUCCEEDED(hr))
                {
                 // Commit the changes to the file if content is current...
                    hr = pstg->Commit(STGC_ONLYIFCURRENT);
                }
                pstg->Release();
            }

            pbc->Release();
        }

    }

	return hr;
}

////////////////////////////////////////////////////////////////////////
// CDsoDocObject::SaveStorageToFile
//
//  Saves the open object to a file. If you pass NULL for the file, we'll
//  save back to the original open location.
//
STDMETHODIMP CDsoDocObject::SaveStorageToFile(LPWSTR pwszFile, BOOL fOverwriteFile)
{
	HRESULT		  hr = E_UNEXPECTED;
	IPersistFile *pipfile;
	IStorage     *pstg;
	LPWSTR        pwszFullName = NULL;
	LPWSTR		  pwszRename = NULL;
	BOOL          fDoNormalSave = FALSE;
	BOOL          fDoOverwriteOps = FALSE;
	BOOL          fFileOpSuccess = FALSE;

 // Make sure we have the most current state for the file...
	if ((!m_pole) || FAILED(hr = SaveObjectStorage()))
		return hr;

 // If they passed no file, use the default if current file is not read-only...
	if ((!pwszFile) && 
        !((fDoNormalSave = !!(pwszFile = m_pwszSourceFile)) && (!IsReadOnly())))
		return DSO_E_DOCUMENTREADONLY;

 // Make sure a file extension is given (add one if not)...
	if (ValidateFileExtension(pwszFile, &pwszFullName))
		pwszFile = pwszFullName;

 // See if we will be overwriting, and error unless given permission to do so...
    if ((fDoOverwriteOps = FFileExists(pwszFile)) && !(fOverwriteFile))
        return STG_E_FILEALREADYEXISTS;

 // If we had a previous lock, we have to free it...
	SAFE_RELEASE_INTERFACE(m_pstgSourceFile);

 // If we are overwriting, we do a little Shell Operation here. This is done
 // for two reasons: (1) it keeps the server from asking us to overwrite the
 //  file as it normally would in case of normal save; and (2) it lets us
 // restore the original if the save fails...
	if (fDoOverwriteOps)
	{
		pwszRename = DsoCopyStringCat(pwszFile, L".dstmp");
		fFileOpSuccess = ((pwszRename) && FPerformShellOp(FO_RENAME, pwszFile, pwszRename));
	}

 // Let's do it. First ask for server to save to file if it supports IPersistFile.
 // This gives us a "real" file as output. This will work with almost all Office servers...
	if (SUCCEEDED(hr = m_pole->QueryInterface(IID_IPersistFile, (void**)&pipfile)))
	{
		hr = pipfile->Save(pwszFile, FALSE);
		pipfile->Release();
	}
	else
	{
	 // If that doesn't work, save out the storage to OLE file. This may not produce
	 // the same type of file as you would get by the UI, but it would give a file
	 // that can be opened here again and in any "good" OLE server.
		if (SUCCEEDED(hr = StgCreateDocfile(pwszFile, STGM_TRANSACTED | 
				STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE, 0, &pstg)))
		{
			WriteClassStg(pstg, m_clsidObject);

			if (SUCCEEDED(hr = m_pstgfile->CopyTo(0, NULL, NULL, pstg)))
				hr = pstg->Commit(STGC_OVERWRITE);

			pstg->Release();
		}
	}

 // If we made a copy to protect on overwrite, either restore or delete it as needed...
	if ((fDoOverwriteOps) && (fFileOpSuccess) && (pwszRename))
	{
		FPerformShellOp((FAILED(hr) ? FO_RENAME : FO_DELETE), pwszRename, pwszFile);
	}

 // If this is an exisitng file save, or the operation failed, relock the
 // the original file save source...
    if (((fDoNormalSave) || (FAILED(hr))) && (m_pwszSourceFile))
    {
		StgOpenStorage(m_pwszSourceFile, NULL, 
			((m_pwszWebResource) ? 
				(STGM_READ | STGM_SHARE_DENY_WRITE) : 
				(STGM_TRANSACTED | STGM_SHARE_DENY_WRITE | STGM_READWRITE)), 
				NULL, 0, &m_pstgSourceFile);
    }
    else if (SUCCEEDED(hr))
	{
     // Otherwise if we succeeded, free any existing file info we have it and 
     // save the new file info for later re-saves (and lock)...
		SAFE_FREESTRING(m_pwszSourceFile);
		SAFE_FREESTRING(m_pwszWebResource);
		SAFE_RELEASE_INTERFACE(m_pstmWebResource);

	 // Save the name, and try to lock the file for editing...
		if (m_pwszSourceFile = DsoCopyString(pwszFile))
        {
            m_idxSourceName = CalcDocNameIndex(m_pwszSourceFile);
			StgOpenStorage(m_pwszSourceFile, NULL, 
				(STGM_TRANSACTED | STGM_SHARE_DENY_WRITE | STGM_READWRITE), NULL, 0, &m_pstgSourceFile);
        }
	}

	if (pwszRename)
		DsoMemFree(pwszRename);

	if (pwszFullName)
		DsoMemFree(pwszFullName);

	return hr;
}

////////////////////////////////////////////////////////////////////////
// CDsoDocObject::SaveStorageToURL
//
//  Saves the open object to a URL. If you pass NULL, we'll save back to
//  the original open location.
//
//  This works very similar to the LoadStorageFromURL in that we save to
//  a local file first using the normal SaveStorageToFile and then push an
//  upload to the server.
//
STDMETHODIMP CDsoDocObject::SaveStorageToURL(LPWSTR pwszURL, BOOL fOverwriteFile, LPWSTR pwszUserName, LPWSTR pwszPassword)
{
	HRESULT	 hr = DSO_E_DOCUMENTREADONLY;

 // If we have no URL to save to and no previously open web stream, fail...
	if ((!pwszURL) && (!m_pstmWebResource))
		return hr;

	if (!(m_punkRosebud) && !(m_punkRosebud = CreateRosebudIPP()))
		return DSO_E_REQUIRESMSDAIPP;

	if ((pwszURL) && (m_pwszWebResource) && 
		(DsoCompareStringsEx(pwszURL, -1, m_pwszWebResource, -1) == CSTR_EQUAL))
		pwszURL = NULL;

	if (pwszURL)
	{
		IStream  *pstmT = NULL;
		LPWSTR    pwszFullUrl = NULL;
		LPWSTR    pwszTempFile;

		IStream  *pstmBkupStm;
		IStorage *pstgBkupStg;
		LPWSTR    pwszBkupFile, pwszBkupUrl;
        UINT      idxBkup;

		if (!GetTempPathForURLDownload(pwszURL, &pwszTempFile))
			return E_INVALIDARG;

		if (ValidateFileExtension(pwszURL, &pwszFullUrl))
			pwszURL = pwszFullUrl;

	 // We are going to save out the current file info in case of 
	 // an error we can restore it to do native saves back to open location...
		pstmBkupStm  = m_pstmWebResource;  m_pstmWebResource  = NULL;
		pwszBkupUrl  = m_pwszWebResource;  m_pwszWebResource  = NULL;
		pwszBkupFile = m_pwszSourceFile;   m_pwszSourceFile   = NULL;
		pstgBkupStg  = m_pstgSourceFile;   m_pstgSourceFile   = NULL;
        idxBkup      = m_idxSourceName;    m_idxSourceName    = 0;

	 // Save the object to a new (temp) file on the local drive...
		if (SUCCEEDED(hr = SaveStorageToFile(pwszTempFile, TRUE)))
		{
		 // Then upload from that file...
			hr = UploadWebResource(pwszTempFile, &pstmT, pwszURL, fOverwriteFile, pwszUserName, pwszPassword);
		}

	 // If both calls succeed, we can free the old file/url location info
	 // and save the new information, otherwise restore the old info from backup...
		if (SUCCEEDED(hr))
		{
			SAFE_RELEASE_INTERFACE(pstgBkupStg);

			if ((pstmBkupStm) && (pwszBkupFile))
				FPerformShellOp(FO_DELETE, pwszBkupFile, NULL);

			SAFE_RELEASE_INTERFACE(pstmBkupStm);
			SAFE_FREESTRING(pwszBkupUrl);
			SAFE_FREESTRING(pwszBkupFile);

			m_pstmWebResource = pstmT;
			m_pwszWebResource = DsoCopyString(pwszURL);
			//m_pwszSourceFile already saved in SaveStorageToFile
			//m_pstgSourceFile already saved in SaveStorageToFile
            //m_idxSourceName already calced in SaveStorageToFile;

		}
		else
		{
			if (m_pstgSourceFile)
				m_pstgSourceFile->Release();

			if (m_pwszSourceFile)
			{
				FPerformShellOp(FO_DELETE, m_pwszSourceFile, NULL);
				DsoMemFree(m_pwszSourceFile);
			}

			m_pstmWebResource  = pstmBkupStm;
			m_pwszWebResource  = pwszBkupUrl;
			m_pwszSourceFile   = pwszBkupFile;
			m_pstgSourceFile   = pstgBkupStg;
            m_idxSourceName    = idxBkup;
		}

		if (pwszFullUrl)
			DsoMemFree(pwszFullUrl);

		DsoMemFree(pwszTempFile);

	}
	else if ((m_pstmWebResource) && (m_pwszSourceFile))
	{
        if (SUCCEEDED(hr = SaveStorageToFile(NULL, TRUE)))
		    hr = UploadWebResource(m_pwszSourceFile, &m_pstmWebResource,
                    NULL, TRUE, pwszUserName, pwszPassword);
	}

	return hr;
}


////////////////////////////////////////////////////////////////////////
// CDsoDocObject::DoOleCommand
//
//  Calls IOleCommandTarget::Exec on the active object to do a specific
//  command (like Print, SaveCopy, Zoom, etc.). 
//
STDMETHODIMP CDsoDocObject::DoOleCommand(DWORD dwOleCmdId, DWORD dwOptions, VARIANT* vInParam, VARIANT* vInOutParam)
{
	HRESULT hr;
	OLECMD cmd = {dwOleCmdId, 0};
	TRACE2("CDsoDocObject::DoOleCommand(cmd=%d, Opts=%d\n", dwOleCmdId, dwOptions);

 // Can't issue OLECOMMANDs when in print preview mode (object calls us)...
    if (InPrintPreview()) return E_ACCESSDENIED;

 // The server must support IOleCommandTarget, the CmdID being requested, and
 // the command should be enabled. If this is the case, do the command...
	if ((m_pcmdt) && SUCCEEDED(m_pcmdt->QueryStatus(NULL, 1, &cmd, NULL)) && 
		((cmd.cmdf & OLECMDF_SUPPORTED) && (cmd.cmdf & OLECMDF_ENABLED)))
	{
		TRACE1("QueryStatus say supported = 0x%X\n", cmd.cmdf);

     // Do the command asked by caller on default command group...
		hr = m_pcmdt->Exec(NULL, cmd.cmdID, dwOptions, vInParam, vInOutParam);
		TRACE1("CMT called = 0x%X\n", hr);

	 // If user canceled an Office dialog, that's OK.
		if ((dwOptions == OLECMDEXECOPT_PROMPTUSER) && (hr == 0x80040103))
			hr = S_FALSE;
	}
	else
	{
		TRACE1("Command Not supportted (%d)\n", cmd.cmdf);
		hr = DSO_E_COMMANDNOTSUPPORTED;
	}

	return hr;
}

////////////////////////////////////////////////////////////////////////
// CDsoDocObject::Close
//
//  Close down the object and disconnect us from any handlers/proxies.
//
STDMETHODIMP_(void) CDsoDocObject::Close()
{
	HRESULT hr;

	ODS("CDsoDocObject::Close\n");
    m_fInClose = TRUE;

 // Make sure we are not in print preview before close...
    if (InPrintPreview())
        ExitPrintPreview(TRUE);

 // Go ahead an IP deactivate the object...
	hr = IPDeactivateView();

 // Release the OLE object and cleanup...
    if (m_pole)
	{
        hr = m_pole->Close(OLECLOSE_NOSAVE);
		m_pole->SetClientSite(NULL);

		FreeRunningLock();
		SAFE_RELEASE_INTERFACE(m_pole);
	}

⌨️ 快捷键说明

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