📄 page.cpp
字号:
TENANTINFO ti;
UINT uRet;
HCURSOR hCur;
BOOL fActivate=fNoServer;
SIZEL szl;
if (NULL==m_pTenantCur)
return FALSE;
tType=m_pTenantCur->TypeGet();
if (TENANTTYPE_STATIC==tType)
{
MessageBeep(0);
return FALSE;
}
//Get object information we may want.
m_pTenantCur->GetInfo(&ti);
//Fill the structure.
memset(&ct, 0, sizeof(ct));
ct.cbStruct=sizeof(OLEUICONVERT);
ct.hWndOwner=hWndFrame;
ct.fIsLinkedObject=(TENANTTYPE_LINKEDOBJECT==tType);
ct.dvAspect=ti.fe.dwAspect;
m_pTenantCur->ObjectClassFormatAndIcon(&ct.clsid, &ct.wFormat
, &ct.lpszUserType, &ct.hMetaPict, &ct.lpszDefLabel);
uRet=OleUIConvert(&ct);
if (OLEUI_OK==uRet)
{
//Potentially a long operation.
hCur=SetCursor(LoadCursor(NULL, IDC_WAIT));
//Prevent multiple repaints.
m_pTenantCur->EnableRepaint(FALSE);
//First, let's bother with the iconic aspect switch.
if ((DVASPECT_ICON==ct.dvAspect && ct.fObjectsIconChanged)
|| ct.dvAspect!=ti.fe.dwAspect)
{
HGLOBAL hMem=NULL;
//Only pass non-NULL handle for icon aspects.
if (DVASPECT_ICON==ct.dvAspect)
hMem=ct.hMetaPict;
m_pPG->m_fDirty=m_pTenantCur->SwitchOrUpdateAspect(hMem
, FALSE);
}
//Now change types around.
if ((CF_SELECTCONVERTTO & ct.dwFlags)
&& ct.clsid!=ct.clsidNew)
{
LPSTORAGE pIStorage;
/*
* User selected convert, so:
* 1. Unload the object (back to passive state)
* 2. Call INOLE_DoConvert, which calls WriteClassStg,
* WriteFmtUserTypeStg, and SetConvertStg.
* 3. Reload the object and force an update.
*/
//This should be the only close necessary.
m_pTenantCur->StorageGet(&pIStorage);
m_pTenantCur->Close(TRUE);
hr=INOLE_DoConvert(pIStorage, ct.clsidNew);
//Need to commit the new type and format
pIStorage->Commit(STGC_DEFAULT);
pIStorage->Release();
if (SUCCEEDED(hr))
{
LPUNKNOWN pObj;
LPOLEOBJECT pIOleObject;
//Reload and update.
m_pTenantCur->Load(m_pIStorage, &ti);
m_pTenantCur->ObjectGet(&pObj);
pObj->QueryInterface(IID_IOleObject
, (PPVOID)&pIOleObject);
pIOleObject->Update();
pIOleObject->Release();
pObj->Release();
}
m_pPG->m_fDirty=TRUE;
}
if (CF_SELECTACTIVATEAS & ct.dwFlags)
{
/*
* User selected Activate As, so:
* 1. Add the TreatAs entry in the registry
* through CoTreatAsClass
* 2. Unload all objects of the old CLSID that you
* have loaded.
* 3. Reload objects as desired
* 4. Activate the current object.
*/
hr=CoTreatAsClass(ct.clsid, ct.clsidNew);
if (SUCCEEDED(hr))
{
PCTenant pTenant;
UINT i;
for (i=0; i < m_cTenants; i++)
{
if (TenantGet(i, &pTenant, FALSE))
{
pTenant->GetInfo(&ti);
pTenant->Close(FALSE);
pTenant->Load(m_pIStorage, &ti);
}
}
fActivate=TRUE;
}
}
//These two steps insure the object knows of the size.
m_pTenantCur->SizeGet(&szl, FALSE);
m_pTenantCur->SizeSet(&szl, FALSE, TRUE);
m_pTenantCur->EnableRepaint(TRUE);
m_pTenantCur->Repaint();
if (fActivate)
//CHAPTER22MOD
m_pTenantCur->Activate(OLEIVERB_SHOW, NULL);
//End CHAPTER22MOD
SetCursor(hCur);
}
CoTaskMemFree((void*)ct.lpszUserType);
INOLE_MetafilePictIconFree(ct.hMetaPict);
return TRUE;
}
/*
* CPages::FQueryLinksInPage
*
* Purpose:
* Pass through to current page to see if there are any linked
* objects.
*
* Parameters:
* None
*
* Return Value:
* None
*/
BOOL CPage::FQueryLinksInPage()
{
PCTenant pTenant;
UINT i;
BOOL fRet=FALSE;
for (i=0; i < m_cTenants; i++)
{
if (TenantGet(i, &pTenant, FALSE))
fRet |= (pTenant->TypeGet()==TENANTTYPE_LINKEDOBJECT);
}
return fRet;
}
//CHAPTER22MOD
/*
* CPage::ScrolledWindow
*
* Purpose:
* Instructs the page to call CTenant::UpdateInPlaceObjectRects
* for the current tenant when the window is scrolled.
*
* Parameters:
* None
*
* Return Value:
* None
*/
void CPage::ScrolledWindow(void)
{
UINT i;
PCTenant pTenant;
/*
* Tell all tenants to update the position of in-place objects.
* If you do not support inside-out, only the selected object
* need be notified.
*/
for (i=0; i < m_cTenants; i++)
{
if (!TenantGet(i, &pTenant, FALSE))
continue;
pTenant->UpdateInPlaceObjectRects(NULL, TRUE);
}
return;
}
/*
* CPage::SwitchActiveTenant
*
* Purpose:
* Changes the activation of in-place objects from the current
* one known to the page to the new one passed to this function.
* This is called from IOleInPlaceSite::OnUIDeactivate.
*
* Parameters:
* pTenant PCTenant that is becoming active.
*
* Return Value:
* None
*/
void CPage::SwitchActiveTenant(PCTenant pTenant)
{
BOOL fSelect;
/*
* If we're UI activating the selected tenant, don't
* bother changing selection--just so activation.
*/
fSelect=(pTenant!=m_pTenantCur);
/*
* The first time we UI Activate we're not switching
* anything so avoid the whole sequence.
*/
if (m_fFirstUIActivate)
{
m_fFirstUIActivate=FALSE;
return;
}
if (NULL!=m_pTenantCur && fSelect)
m_pTenantCur->Select(FALSE, TRUE);
m_pTenantCur=pTenant;
//Select the new tenant, but don't activate it again
if (NULL!=m_pTenantCur)
{
UINT i;
if (fSelect)
m_pTenantCur->Select(TRUE, FALSE);
//Find the new tenant in our list and move to the top
for (i=0; i < m_cTenants; i++)
{
PCTenant pTenList;
if (TenantGet(i, &pTenList, FALSE))
{
if (pTenList==m_pTenantCur)
{
HWND hWndObj;
m_iTenantCur=0;
//Remove the tenant and add to the top again.
SendMessage(m_hWndTenantList, LB_DELETESTRING
, i, 0L);
SendMessage(m_hWndTenantList, LB_INSERTSTRING
, 0, (LONG)pTenant);
hWndObj=pTenant->ObjectWindow();
if (NULL!=hWndObj)
{
SetWindowPos(hWndObj, HWND_TOP, 0, 0, 0, 0
, SWP_NOMOVE | SWP_NOSIZE
| SWP_NOACTIVATE);
}
break;
}
}
}
}
return;
}
//End CHAPTER22MOD
/*
* CPage::TenantGet
* (Protected)
*
* Purpose:
* Returns a tenant of a given index returning a BOOL so it's
* simple to use this function inside if statements.
*
* Parameters:
* iTenant UINT tenant to retrieve 0 based.
* ppTenant PCPage * in which to return the tenant
* pointer
* fOpen BOOL indicating if we should open this
* tenant as well.
*
* Return Value:
* BOOL TRUE if successful, FALSE otherwise.
*/
BOOL CPage::TenantGet(UINT iTenant, PCTenant *ppTenant
, BOOL fOpen)
{
if (NULL==ppTenant)
return FALSE;
if (LB_ERR!=SendMessage(m_hWndTenantList, LB_GETTEXT
, iTenant, (LONG)ppTenant))
{
if (fOpen)
(*ppTenant)->Open(m_pIStorage);
return TRUE;
}
return FALSE;
}
/*
* CPage::TenantGetFromID
* (Protected)
*
* Purpose:
* Finds a tenant pointer from an ID for use from
* IOleItemContainer::GetObject
*
* Parameters:
* dwID DWORD identifier of the tenant to find.
* ppTenant PCTenant * in which to return the tenant
* pointer
* fOpen BOOL indicating if we should open this tenant as
* well.
*
* Return Value:
* BOOL TRUE if successful, FALSE otherwise.
*/
BOOL CPage::TenantGetFromID(DWORD dwID, PCTenant *ppTenant
, BOOL fOpen)
{
UINT i;
PCTenant pTenant;
if (NULL==ppTenant)
return FALSE;
for (i=0; i < m_cTenants; i++)
{
if (!TenantGet(i, &pTenant, FALSE))
continue;
if (pTenant->GetID()==dwID)
{
if (fOpen)
pTenant->Open(m_pIStorage);
*ppTenant=pTenant;
return TRUE;
}
}
return FALSE;
}
/*
* CPage::TenantAdd
* (Protected)
*
* Purpose:
* Creates a new tenant initialized to the given values. The new
* tenants's storage is created if it does not already exist. If
* fOpenStorage is set the the tenants's storage is opened and left
* opened.
*
* Parameters:
* iTenant UINT Location at which to insert tenant; new
* tenant is inserted after this position. NOVALUE
* for the end.
* dwID DWORD ID for this tenant.
* ppNew PCTenant * in which to store the new tenant.
*
* Return Value:
* BOOL TRUE if the function succeeded, FALSE otherwise.
*/
BOOL CPage::TenantAdd(UINT iTenant, DWORD dwID
, PCTenant *ppNew)
{
PCTenant pTenant;
LRESULT lr;
if (NULL!=ppNew)
*ppNew=NULL;
pTenant=new CTenant(dwID, m_hWnd, m_pPG);
if (NULL==pTenant)
return FALSE;
//The constructor doesn't AddRef, so we need to.
pTenant->AddRef();
//Now try to add to the listbox.
lr=SendMessage(m_hWndTenantList, LB_INSERTSTRING, iTenant
, (LONG)pTenant);
if (lr < 0)
{
pTenant->Release();
return FALSE;
}
*ppNew=pTenant;
return TRUE;
}
/*
* CPage::TransferObjectCreate
* (Protected)
*
* Purpose:
* Creates a DataTransferObject and stuff the current selection's
* data into it.
*
* Parameters:
* pptl PPOINTL containing the pick point in device
* units applicable only to drag-drop; since
* drag-drop is inherently mouse oriented, we use
* device units for the point. Ignored if NULL.
*
* Return Value:
* LPDATAOBJECT Pointer to the object created, NULL on failure
*/
LPDATAOBJECT CPage::TransferObjectCreate(PPOINTL pptl)
{
LPDATAOBJECT pIDataObject;
LPDATAOBJECT pIDataT;
PPATRONOBJECT ppo;
RECTL rcl;
LPUNKNOWN pObj;
FORMATETC fe;
STGMEDIUM stm;
HRESULT hr;
HGLOBAL hMem;
m_pTenantCur->ObjectGet(&pObj);
hr=CoCreateInstance(CLSID_DataTransferObject, NULL
, CLSCTX_INPROC_SERVER, IID_IDataObject
, (PPVOID)&pIDataObject);
if (FAILED(hr))
return NULL;
//Go get the data we should hold on to.
hr=pObj->QueryInterface(IID_IDataObject, (PPVOID)&pIDataT);
if (FAILED(hr))
{
pIDataObject->Release();
pObj->Release();
return NULL;
}
//Copy from known obj into transfer obj. Ordering is important!
//Generate placeable object structure
stm.tymed=TYMED_HGLOBAL;
stm.pUnkForRelease=NULL;
stm.hGlobal=GlobalAlloc(GHND, sizeof(PATRONOBJECT));
if (NULL==stm.hGlobal)
{
pIDataObject->Release();
pObj->Release();
return NULL;
}
ppo=(PPATRONOBJECT)GlobalLock(stm.hGlobal);
m_pTenantCur->SizeGet(&ppo->szl, FALSE);
ppo->szl.cy=-ppo->szl.cy; //Negate to make absolute size
m_pTenantCur->RectGet(&rcl, FALSE);
ppo->ptl.x=rcl.left;
ppo->ptl.y=rcl.top;
if (NULL==pptl)
{
ppo->ptlPick.x=0;
ppo->ptlPick.y=0;
}
else
ppo->ptlPick=*pptl;
m_pTenantCur->FormatEtcGet(&ppo->fe, FALSE);
//If this is a linked object, just copy a presentation
if (TENANTTYPE_LINKEDOBJECT==m_pTenantCur->TypeGet())
m_pTenantCur->FormatEtcGet(&ppo->fe, TRUE);
SETDefFormatEtc(fe, m_pPG->m_cf, TYMED_HGLOBAL);
pIDataObject->SetData(&fe, &stm, TRUE);
/*
* Here now we have to include CFSTR_EMBEDDEDOBJECT and
* CFSTR_OBJECTDESCRIPTOR when what we have selected is, in
* fact, a compound document object. We'll just ask the tenant
* to set these in pIDataObject since it knows what the object.
* If we copy embedded object data, make sure the PATRONOBJECT
* structure has the right format in it as well.
*/
m_pTenantCur->CopyEmbeddedObject(pIDataObject, &ppo->fe, pptl);
hMem=stm.hGlobal;
//Copy the actual presentation.
m_pTenantCur->FormatEtcGet(&fe, TRUE);
pIDataT->GetData(&fe, &stm);
pIDataObject->SetData(&fe, &stm, TRUE);
//Copy a link to this tenant if it's embedded
m_pTenantCur->CopyLinkedObject(pIDataObject, &ppo->fe, pptl);
GlobalUnlock(hMem); //ppo
pIDataT->Release();
pObj->Release();
return pIDataObject; //Caller now responsible
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -