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

📄 dsofdocobj.cpp

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

 // Free any temp file we might have...
	if ((m_pstmWebResource) && (m_pwszSourceFile))
		FPerformShellOp(FO_DELETE, m_pwszSourceFile, NULL);

	SAFE_RELEASE_INTERFACE(m_pstmWebResource);
	SAFE_FREESTRING(m_pwszWebResource);
	SAFE_FREESTRING(m_pwszSourceFile);
    m_idxSourceName = 0;

	if (m_fDisconnectOnQuit)
	{
		CoDisconnectObject((IUnknown*)this, 0);
		m_fDisconnectOnQuit = FALSE;
	}

	SAFE_RELEASE_INTERFACE(m_pstmview);
	SAFE_RELEASE_INTERFACE(m_pstgfile);

	ClearMergedMenu();
    m_fInClose = FALSE;
    return;
}


////////////////////////////////////////////////////////////////////////
// CDsoDocObject Notification Functions - The OCX should call these to
//  let the doc site update the object as needed.
//  

////////////////////////////////////////////////////////////////////////
// CDsoDocObject::OnNotifySizeChange
//
//  Resets the size of the site window and tells UI active object to 
//  resize as well. If we are UI active, we'll call ResizeBorder to 
//  re-negotiate toolspace (allow toolbars to shrink and grow), otherwise
//  we'll just set the IP active view rect (minus any toolspace, which
//  should be none since object is not UI active!). 
//
STDMETHODIMP_(void) CDsoDocObject::OnNotifySizeChange(LPRECT prc)
{
	RECT rc;

	SetRect(&rc, 0, 0, (prc->right - prc->left), (prc->bottom - prc->top));
	if (rc.right < 0) rc.right = 0;
	if (rc.top < 0) rc.top = 0;

 // First, resize our frame site window tot he new size (don't change focus)...
	if (m_hwnd)
	{
		m_rcViewRect = *prc;

		SetWindowPos(m_hwnd, NULL, m_rcViewRect.left, m_rcViewRect.top,
			rc.right, rc.bottom, SWP_NOACTIVATE | SWP_NOZORDER);

		UpdateWindow(m_hwnd);
	}

 // If we have an active object (i.e., Document is still UI active) we should
 // tell it of the resize so it can re-negotiate border space...
	if ((m_fObjectUIActive) && (m_pipactive))
	{
		m_pipactive->ResizeBorder(&rc, (IOleInPlaceUIWindow*)&m_xOleInPlaceFrame, TRUE);
	}
	else if ((m_fObjectIPActive) && (m_pdocv))
	{
        rc.left   += m_bwToolSpace.left;   rc.right  -= m_bwToolSpace.right;
        rc.top    += m_bwToolSpace.top;    rc.bottom -= m_bwToolSpace.bottom;
		m_pdocv->SetRect(&rc);
	}

	return;
}

////////////////////////////////////////////////////////////////////////
// CDsoDocObject::OnNotifyAppActivate
//
//  Notify doc object when the top-level frame window goes active and 
//  deactive so it can handle window focs and paiting correctly. Failure
//  to not forward this notification leads to bad behavior.
// 
STDMETHODIMP_(void) CDsoDocObject::OnNotifyAppActivate(BOOL fActive, DWORD dwThreadID)
{
 // This is critical for DocObject servers, so forward these messages
 // when the object is UI active...
	if (m_pipactive)
	{
	 // We should always tell obj server when our frame activates, but
	 // don't tell it to go deactive if the thread gaining focus is 
	 // the server's since our frame may have lost focus because of
	 // a top-level modeless dialog (ex., the RefEdit dialog of Excel)...
		//if ((fActive) || (dwThreadID != m_dwObjectThreadID))
        m_pipactive->OnFrameWindowActivate(fActive);
	}

	m_fAppWindowActive = fActive;
}

STDMETHODIMP_(void) CDsoDocObject::OnNotifyHostSetFocus()
{
    HWND hwnd;
	if ((m_pipactive) && SUCCEEDED(m_pipactive->GetWindow(&hwnd)))
        SetFocus(hwnd);
}

////////////////////////////////////////////////////////////////////////
// CDsoDocObject::OnNotifyPaletteChanged
//
//  Give the object first chance at realizing a palette. Important on
//  256 color machines, but not so critical these days when everyone is
//  running full 32-bit True Color graphic cards.
// 
STDMETHODIMP_(void) CDsoDocObject::OnNotifyPaletteChanged(HWND hwndPalChg)
{
	if ((m_fObjectUIActive) && (m_hwndUIActiveObj))
		SendMessage(m_hwndUIActiveObj, WM_PALETTECHANGED, (WPARAM)hwndPalChg, 0L);
}

////////////////////////////////////////////////////////////////////////
// CDsoDocObject::OnNotifyChangeToolState
//
//  This should be called to get object to show/hide toolbars as needed.
//
STDMETHODIMP_(void) CDsoDocObject::OnNotifyChangeToolState(BOOL fShowTools)
{
 // Can't change toolbar state in print preview (sorry)...
    if (InPrintPreview()) return;

 // If we want to show/hide toolbars, we can do the following...
	if (fShowTools != (BOOL)m_fDisplayTools)
	{
		OLECMD cmd;
		cmd.cmdID = OLECMDID_HIDETOOLBARS;

		m_fDisplayTools = fShowTools;

	 // Use IOleCommandTarget(OLECMDID_HIDETOOLBARS) to toggle on/off. We have
	 // to check that server supports it and if its state matches our own so
	 // when toggle, we do the correct thing by the user...
		if ((m_pcmdt) && SUCCEEDED(m_pcmdt->QueryStatus(NULL, 1, &cmd, NULL)) && 
			((cmd.cmdf & OLECMDF_SUPPORTED) || (cmd.cmdf & OLECMDF_ENABLED)))
		{
			if (((fShowTools) && (cmd.cmdf & OLECMDF_LATCHED)) ||
				(!(fShowTools) && !(cmd.cmdf & OLECMDF_LATCHED)))
			{
				m_pcmdt->Exec(NULL, OLECMDID_HIDETOOLBARS, OLECMDEXECOPT_PROMPTUSER, NULL, NULL);
			}

		 // There can be focus issues when turning them off, so make sure
		 // the object is on top of the z-order...
			if ((!m_fDisplayTools) && (m_hwndIPObject))
				BringWindowToTop(m_hwndIPObject);

		 // If user toggles off the toolbar while the object is UI active, and
		 // we are not still in activation process, we need to explictly tell Office
		 // apps to also hide the "Web" toolbar. For Office, OLECMDID_HIDETOOLBARS puts
		 // the app into a "web view" which (in some apps) brings up the web toolbar.
		 // Since we intend to have no tools, we have to turn it off by code...
			if ((!m_fDisplayTools) && (m_fObjectUIActive) && (m_fObjectActivateComplete))
				TurnOffWebToolbar();

		}
		else if (m_pdocv)
		{
		 // If we have a DocObj server, but no IOleCommandTarget, do things the hard
		 // way and resize. When server attempts to resize window it will have to
		 // re-negotiate BorderSpace and we fail there, so server "should" not
		 // display its tools (at least that is the idea!<g>)...
			RECT rc; GetClientRect(m_hwnd, &rc);
			MapWindowPoints(m_hwnd, m_hwndCtl, (LPPOINT)&rc, 2);
			OnNotifySizeChange(&rc);
		}
	}
	return;
}


////////////////////////////////////////////////////////////////////////
// CDsoDocObject Protected Functions -- Helpers
//

////////////////////////////////////////////////////////////////////////
// CDsoDocObject::CreateObjectStorage (protected)
//
//  Makes the internal IStorage to host the object and assigns the CLSID.
//
STDMETHODIMP CDsoDocObject::CreateObjectStorage(REFCLSID rclsid)
{
	HRESULT hr;
	LPWSTR pwszName;
	DWORD dwid;
	CHAR szbuf[256];

	if ((!m_pstgroot)) return E_UNEXPECTED;

 // Next, create a new object storage (with unique name) in our
 // temp root storage "file" (this keeps an OLE integrity some servers
 // need to function correctly instead of IP activating from file directly).

 // We make a fake object storage name...
	dwid = ((rclsid.Data1)|GetTickCount());
	wsprintf(szbuf, "OLEDocument%X", dwid);

	if (!(pwszName = DsoConvertToLPWSTR(szbuf)))
		return E_OUTOFMEMORY;

 // Create the sub-storage...
	hr = m_pstgroot->CreateStorage(pwszName,
		STGM_TRANSACTED | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &m_pstgfile);

	DsoMemFree(pwszName);

	if (FAILED(hr)) return hr;

 // We'll also create a stream for OLE view settings (non-critical)...
	if (pwszName = DsoConvertToLPWSTR(szbuf))
	{
		m_pstgroot->CreateStream(pwszName,
			STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &m_pstmview);
		DsoMemFree(pwszName);
	}

 // Finally, write out the CLSID for the new substorage...
	hr = WriteClassStg(m_pstgfile, rclsid);
	return hr;
}

////////////////////////////////////////////////////////////////////////
// CDsoDocObject::SaveObjectStorage (protected)
//
//  Saves the object back to the internal IStorage. Returns S_FALSE if
//  there is no file storage for this document (it depends on how file
//  was loaded). In most cases we should have one, and this copies data
//  into the internal storage for save.
//
STDMETHODIMP CDsoDocObject::SaveObjectStorage()
{
	HRESULT hr = S_FALSE;
	IPersistStorage *pipstg = NULL;

 // Got to have object to save state...
	if (!m_pole) return E_UNEXPECTED;

 // If we have file storage, ask for IPersist and Save (commit changes)...
	if ((m_pstgfile) && 
        SUCCEEDED(hr = m_pole->QueryInterface(IID_IPersistStorage, (void**)&pipstg)))
	{
		if (SUCCEEDED(hr = pipstg->Save(m_pstgfile, TRUE)))
			hr = pipstg->SaveCompleted(NULL);

		hr = m_pstgfile->Commit(STGC_DEFAULT);
		pipstg->Release();
	}

 // Go ahead and save the view state if view still active (non-critical)...
	if ((m_pdocv) && (m_pstmview))
	{
		m_pdocv->SaveViewState(m_pstmview);
		m_pstmview->Commit(STGC_DEFAULT);
	}

	return hr;
}

////////////////////////////////////////////////////////////////////////
// CDsoDocObject::ValidateDocObjectServer (protected)
//
//  Quick validation check to see if CLSID is for DocObject server.
//
//  Officially, the only way to determine if a server supports ActiveX
//  Document embedding is to IP activate it and ask for IOleDocument, 
//  but that means going through the IP process just to fail if IOleDoc
//  is not supported. Therefore, we are going to rely on the server's 
//  honesty in setting its reg keys to include the "DocObject" sub key 
//  under their CLSID.
//
//  This is 99% accurate. For those servers that fail, too bad charlie!
//
STDMETHODIMP CDsoDocObject::ValidateDocObjectServer(REFCLSID rclsid)
{
	HRESULT hr = DSO_E_INVALIDSERVER;
	CHAR  szKeyCheck[256];
	LPSTR pszClsid;
	HKEY  hkey;

 // We don't handle MSHTML even though it is DocObject server...
    const GUID CLSID_MSHTMLDOC = {0x25336920,0x03F9,0x11CF,{0x8F,0xD0,0x00,0xAA,0x00,0x68,0x6F,0x13}};
    if (rclsid == CLSID_MSHTMLDOC) return hr;

 // Convert the CLSID to a string and check for DocObject sub key...
	if (pszClsid = DsoCLSIDtoLPSTR(rclsid))
	{
		wsprintf(szKeyCheck, "CLSID\\%s\\DocObject", pszClsid);

		if (RegOpenKeyEx(HKEY_CLASSES_ROOT, szKeyCheck, 0, KEY_READ, &hkey) == ERROR_SUCCESS)
		{
			hr = S_OK;
			RegCloseKey(hkey);
		}

		DsoMemFree(pszClsid);
	}
	else hr = E_OUTOFMEMORY;

	return hr;
}

////////////////////////////////////////////////////////////////////////
// CDsoDocObject::ValidateFileExtension (protected)
//
//  Adds a default extension to save file path if user didn't provide
//  one (uses CLSID and registry to determine default extension).
//
STDMETHODIMP_(BOOL) CDsoDocObject::ValidateFileExtension(WCHAR* pwszFile, WCHAR** ppwszOut)
{
	BOOL   fHasExt = FALSE;
	BOOL   fChangedExt = FALSE;
	LPWSTR pwszT;
	LPSTR  pszClsid;
	DWORD  dw;

	if ((pwszFile) && (dw = lstrlenW(pwszFile)) && (ppwszOut))
	{
		*ppwszOut = NULL;

		pwszT = (pwszFile + dw);
		while ((pwszT != pwszFile) && 
			   (*(--pwszT)) && ((*pwszT != L'\\') && (*pwszT != L'/')))
		{
			if (*pwszT == L'.') fHasExt = TRUE;
		}
		
		if (!(fHasExt) && (pszClsid = DsoCLSIDtoLPSTR(m_clsidObject)))
		{
			HKEY hk;
			DWORD dwType, dwSize;
			LPWSTR pwszExt;
			CHAR szkey[255];
			CHAR szbuf[128];

			wsprintf(szkey, "CLSID\\%s\\DefaultExtension", pszClsid);
			if (RegOpenKeyEx(HKEY_CLASSES_ROOT, szkey, 0, KEY_READ, &hk) == ERROR_SUCCESS)
			{
				LPSTR pszT = szbuf;
				dwSize = 128;

				if (RegQueryValueEx(hk, NULL, 0, &dwType, (BYTE*)pszT, &dwSize) == ERROR_SUCCESS)
				{
					while (*(pszT++) && (*pszT != ','))
						(void)(0);
					*pszT = '\0';
				}
				else lstrcpy(szbuf, ".ole");

				RegCloseKey(hk);
			}
			else lstrcpy(szbuf, ".ole");

			if (pwszExt = DsoConvertToLPWSTR(szbuf))
				*ppwszOut = DsoCopyStringCat(pwszFile, pwszExt);

			fChangedExt = ((*ppwszOut) != NULL);
			DsoMemFree(pszClsid);
		}
	}

	return fChangedExt;
}


////////////////////////////////////////////////////////////////////////
// CDsoDocObject::CreateRosebudIPP (protected)
//
//  Returns an instance of MSDAIPP (a.k.a., "Rosebud") which is used by
//  Office/Windows for Web Folders (HTTP with DAV/FPSE). 
//
//  This is used to open web resources, lock them for editing, and save
//  changes back up to the server as needed. If the provider is not 
//  installed or cannot be initialized, the functions returns NULL.
//
STDMETHODIMP_(IUnknown*) CDsoDocObject::CreateRosebudIPP()
{
	HRESULT           hr;
	IDBProperties*    pdbprops = NULL;
	IBindResource*    pres    = NULL;
	DBPROPSET         rdbpset;

⌨️ 快捷键说明

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