📄 page.cpp
字号:
/*
* PAGE.CPP
* Patron Chapter 22
*
* Implementation of parts of the CPage class; those member
* functions dealing with mouse events are in PAGEMOUS.CPP.
*
* Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
*
* Kraig Brockschmidt, Microsoft
* Internet : kraigb@microsoft.com
* Compuserve: >INTERNET:kraigb@microsoft.com
*/
#include "patron.h"
/*
* CPage::CPage
* CPage::~CPage
*
* Constructor Parameters:
* dwID DWORD identifier for this page.
* hWnd HWND of the pages window (for repaints, etc).
* pPG PCPages to the Pages window.
*/
CPage::CPage(DWORD dwID, HWND hWnd, PCPages pPG)
{
m_dwID =dwID;
m_pIStorage=NULL;
m_cOpens=0;
m_hWnd=hWnd;
m_pPG=pPG;
m_dwIDNext =0;
m_cTenants =0;
m_hWndTenantList=NULL;
m_iTenantCur =NOVALUE; //Tenants are zero indexed.
m_pTenantCur =NULL;
m_uHTCode=HTNOWHERE;
m_uSizingFlags=0;
m_fTracking=FALSE;
m_hDC=NULL;
m_fDragPending=FALSE;
m_fSizePending=FALSE;
m_fTimer=FALSE;
//Get WIN.INI distance and delay values, with OLE defaults.
m_cxyDist=GetProfileInt(TEXT("windows"), TEXT("DragMinDist")
, DD_DEFDRAGMINDIST);
m_cDelay=GetProfileInt(TEXT("windows"), TEXT("DragDelay")
, DD_DEFDRAGDELAY);
m_fReopen=FALSE;
m_pmkFile=m_pPG->m_pmkFile;
if (NULL!=m_pmkFile)
m_pmkFile->AddRef();
m_cRef=0L;
m_dwRegROTWild=0L;
m_pImpIOleItemContainer=NULL;
//CHAPTER22MOD
m_fFirstUIActivate=TRUE; //We haven't UIActivated anyone yet
//End CHAPTER22MOD
return;
}
CPage::~CPage(void)
{
INOLE_RevokeAsRunning(&m_dwRegROTWild);
if (m_fTimer)
KillTimer(m_hWnd, IDTIMER_DEBOUNCE);
m_hWnd=NULL;
Close(FALSE);
return;
}
/*
* CPage::QueryInterface
* CPage::AddRef
* CPage::Release
*
* Purpose:
* IUnknown members for CPage object.
*/
STDMETHODIMP CPage::QueryInterface(REFIID riid, PPVOID ppv)
{
*ppv=NULL;
if (IID_IUnknown==riid)
*ppv=this;
if (IID_IOleItemContainer==riid || IID_IOleContainer==riid
|| IID_IParseDisplayName==riid)
*ppv=m_pImpIOleItemContainer;
if (NULL!=*ppv)
{
((LPUNKNOWN)*ppv)->AddRef();
return NOERROR;
}
return ResultFromScode(E_NOINTERFACE);
}
STDMETHODIMP_(ULONG) CPage::AddRef(void)
{
return ++m_cRef;
}
STDMETHODIMP_(ULONG) CPage::Release(void)
{
if (0!=--m_cRef)
return m_cRef;
delete this;
return 0;
}
/*
* CPage::GetID
*
* Return Value:
* DWORD dwID field in this page.
*/
DWORD CPage::GetID(void)
{
return m_dwID;
}
/*
* CPage::Open
*
* Purpose:
* Retrieves the IStorage associated with this page. The IStorage
* is owned by the page and thus the page always holds a reference
* count. The caller should call Close or delete this page to
* match this open.
*
* This function may be called multiple times resulting in
* additional reference counts on the storage each of which must be
* matched with a call to Close. The last Close can be done
* through delete.
*
* Parameters:
* pIStorage LPSTORAGE in which this page lives.
*
* Return Value:
* BOOL TRUE if opening succeeds, FALSE otherwise.
*/
BOOL CPage::Open(LPSTORAGE pIStorage)
{
HRESULT hr=NOERROR;
LPSTREAM pIStream;
DWORD dwMode;
OLECHAR szTemp[32];
TCHAR szCap[32];
BOOL fNew;
BOOL fCreated=FALSE;
TENANTLIST tl;
PTENANTINFO pti;
ULONG cb;
LPMALLOC pIMalloc;
UINT i;
PCTenant pTenant;
UINT cLinks;
LPOLELINK pIOleLink;
LPUNKNOWN pIUnknown;
UINT uRet;
OLEUIEDITLINKS el;
PCIOleUILinkContainer pIUILinks;
HWND hWndDoc;
fNew=(NULL==m_pIStorage);
if (!fNew)
{
m_cOpens++;
m_pIStorage->AddRef();
return TRUE;
}
if (NULL==pIStorage)
return FALSE;
/*
* Attempt to open the storage under this ID. If none,
* create one. In either case, the IStorage is either
* saved in pPage or released.
*/
GetStorageName(szTemp);
dwMode=STGM_TRANSACTED | STGM_READWRITE | STGM_SHARE_EXCLUSIVE;
hr=pIStorage->OpenStorage(szTemp, NULL, dwMode, NULL, 0
, &m_pIStorage);
if (FAILED(hr))
{
hr=pIStorage->CreateStorage(szTemp, dwMode, 0, 0
, &m_pIStorage);
fCreated=TRUE;
}
if (FAILED(hr))
return FALSE;
m_cOpens++;
if (NULL==m_hWndTenantList)
{
/*
* The first time we open this page, create the hidden
* listbox we'll use to track tenants. We give it the
* owner-draw style so we can just store pointers in it.
*/
m_hWndTenantList=CreateWindow(TEXT("listbox")
, TEXT("Tenant List"), WS_POPUP | LBS_OWNERDRAWFIXED
, 0, 0, 100, 100, HWND_DESKTOP, NULL
, m_pPG->m_hInst, NULL);
if (NULL==m_hWndTenantList)
return FALSE;
}
m_pImpIOleItemContainer=new CImpIOleItemContainer(this, this
, FALSE);
if (NULL==m_pImpIOleItemContainer)
return FALSE;
//If this is brand-new, we're done.
if (fCreated)
return TRUE;
/*
* Now open the stream we saved in Close and load all the
* tenants listed in there. If there are none, then we don't
* have to load squat.
*/
hr=m_pIStorage->OpenStream(SZSTREAMTENANTLIST, NULL, STGM_DIRECT
| STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &pIStream);
if (FAILED(hr))
return FALSE;
if (SUCCEEDED(CoGetMalloc(MEMCTX_TASK, &pIMalloc)))
{
pIStream->Read(&tl, sizeof(tl), NULL);
m_cTenants=tl.cTenants;
m_dwIDNext=tl.dwIDNext;
m_iTenantCur=0;
cb=tl.cTenants*sizeof(TENANTINFO);
if (0!=cb)
{
pti=(PTENANTINFO)pIMalloc->Alloc(cb);
if (NULL!=pti)
{
pIStream->Read(pti, cb, NULL);
for (i=0; i < m_cTenants; i++)
{
if (TenantAdd(NOVALUE, (pti+i)->dwID, &pTenant))
{
pTenant->Load(m_pIStorage, (pti+i));
//Make sure it knows about the show state.
pTenant->ShowObjectType(m_pPG->m_fShowTypes);
}
}
pIMalloc->Free(pti);
}
}
pIMalloc->Release();
}
pIStream->Release();
//Get and select the first tenant
//CHAPTER22MOD
if (TenantGet(0, &m_pTenantCur, FALSE))
m_pTenantCur->Select(TRUE, TRUE);
//End CHAPTER22MOD
//If we just saved and closed, don't bother with updating links
if (m_fReopen)
{
m_fReopen=FALSE;
return TRUE;
}
/*
* Update all the links in this page, showing the progress
* indicator as it's happening. We use the same
* IOlUILinkContainer implementation as we do for the links
* dialog, passing it to OleUIUpdateLinks which does everything
* for us.
*
* We might also optimize this to not do anything if there are
* no automatic links, but it's not a big concern.
*/
//First, count the number of automatic links.
cLinks=0;
for (i=0; i < m_cTenants; i++)
{
if (TenantGet(i, &pTenant, FALSE))
{
DWORD dw;
pTenant->ObjectGet(&pIUnknown);
hr=pIUnknown->QueryInterface(IID_IOleLink
, (PPVOID)&pIOleLink);
pIUnknown->Release();
if (FAILED(hr))
continue;
pIOleLink->GetUpdateOptions(&dw);
pIOleLink->Release();
if (OLEUPDATE_ALWAYS==dw)
cLinks++;
}
}
//If we have any automatic links, invoke the update dialog.
if (0==cLinks)
return TRUE;
//Create an IOleUILinkContainer instantiation.
if (!m_pPG->GetUILinkContainer(&pIUILinks))
return TRUE; //Guess we can't update, oh well.
hWndDoc=GetParent(m_hWnd);
LoadString(m_pPG->m_hInst, IDS_CAPTION, szCap, sizeof(szCap));
if (!OleUIUpdateLinks(pIUILinks, hWndDoc, szCap, cLinks))
{
/*
* If updating failed, ask to show the links dialog. NOTE:
* OleUIPromptUser has a variable wsprintf argument list
* after the hWnd parameter! Use appropriate typecasting!
*/
uRet=OleUIPromptUser(IDD_CANNOTUPDATELINK, hWndDoc, szCap);
#ifdef IDC_PU_LINKS
if (IDC_PU_LINKS==uRet)
#else
if (ID_PU_LINKS==uRet)
#endif
{
//Throw up the links dialog.
memset(&el, 0, sizeof(el));
el.cbStruct=sizeof(el);
el.hWndOwner=hWndDoc;
el.lpOleUILinkContainer=pIUILinks;
OleUIEditLinks(&el);
}
}
m_pPG->m_fDirty=pIUILinks->m_fDirty;
pIUILinks->Release();
return TRUE;
}
/*
* CPage::Close
*
* Purpose:
* Possibly commits the storage, then releases it reversing the
* reference count from Open.
*
* Parameters:
* fCommit BOOL indicating if we're to commit.
*
* Return Value:
* None
*/
void CPage::Close(BOOL fCommit)
{
if (NULL==m_pIStorage)
return;
if (fCommit)
Update();
m_pIStorage->Release();
//If this was the last close, make all tenants loaded->passive
if (0==--m_cOpens)
{
UINT i;
PCTenant pTenant;
m_pIStorage=NULL;
for (i=0; i < m_cTenants; i++)
{
if (TenantGet(i, &pTenant, FALSE))
{
if (NULL!=m_hWnd)
{
//Open may select again, so this repaints.
//CHAPTER22MOD
pTenant->Select(FALSE, TRUE);
//End CHAPTER22MOD
}
pTenant->Close(FALSE);
pTenant->Release();
}
}
DestroyWindow(m_hWndTenantList);
m_hWndTenantList=NULL;
m_fReopen=TRUE;
if (NULL!=m_pmkFile)
m_pmkFile->Release();
m_pmkFile=NULL;
DeleteInterfaceImp(m_pImpIOleItemContainer);
}
return;
}
/*
* CPage::Update
*
* Purpose:
* Forces a common on the page if it's open.
*
* Parameters:
* None
*
* Return Value:
* BOOL TRUE if there are any open objects on this page,
* that is, we should remain open.
*/
BOOL CPage::Update(void)
{
BOOL fOpen=FALSE;
UINT i;
PCTenant pTenant;
HRESULT hr;
LPSTREAM pIStream;
TENANTLIST tl;
PTENANTINFO pti;
ULONG cb;
LPMALLOC pIMalloc;
//Walk the list of objects and update them all as well.
for (i=0; i < m_cTenants; i++)
{
if (TenantGet(i, &pTenant, FALSE))
fOpen |= pTenant->Update();
}
//Now write our own stream containing the tenant list.
hr=m_pIStorage->CreateStream(SZSTREAMTENANTLIST, STGM_CREATE
| STGM_WRITE| STGM_DIRECT | STGM_SHARE_EXCLUSIVE, 0, 0
, &pIStream);
if (FAILED(hr))
return fOpen;
if (SUCCEEDED(CoGetMalloc(MEMCTX_TASK, &pIMalloc)))
{
tl.cTenants=m_cTenants;
tl.dwIDNext=m_dwIDNext;
pIStream->Write(&tl, sizeof(TENANTLIST), &cb);
cb=m_cTenants*sizeof(TENANTINFO);
pti=(PTENANTINFO)pIMalloc->Alloc(cb);
if (NULL!=pti)
{
for (i=0; i < m_cTenants; i++)
{
TenantGet(i, &pTenant, FALSE);
pTenant->GetInfo((pti+i));
}
pIStream->Write(pti, cb, &cb);
pIMalloc->Free(pti);
}
pIMalloc->Release();
}
pIStream->Release();
//Now commit the whole mess and we're done
if (NULL!=m_pIStorage)
m_pIStorage->Commit(STGC_DEFAULT);
return fOpen;
}
/*
* CPage::Destroy
*
* Purpose:
* Removes this page from the given storage. The caller should
* eventually delete this Page object to free the storage.
*
* Parameters:
* pIStorage LPSTORAGE contianing this page on which to call
* DestroyElement
*
* Return Value:
* None
*/
void CPage::Destroy(LPSTORAGE pIStorage)
{
if (NULL!=pIStorage)
{
OLECHAR szTemp[32];
Close(FALSE);
GetStorageName(szTemp);
pIStorage->DestroyElement(szTemp);
}
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -