|
|
#include "stdafx.h"
#include "Ctrl.h"
#include "Extension.h"
#if ENABLE_MSGTABLE_API
/***************************************************************************\
***************************************************************************** * * class DuExtension * ***************************************************************************** \***************************************************************************/
static const GUID guidAysncDestroy = { 0xbfe02331, 0xc17d, 0x45ea, { 0x96, 0x35, 0xa0, 0x7a, 0x90, 0x37, 0xfe, 0x34 } }; // {BFE02331-C17D-45ea-9635-A07A9037FE34}
MSGID DuExtension::s_msgidAsyncDestroy = 0;
/***************************************************************************\
* * DuExtension::~DuExtension * * ~DuExtension() checks that resources were properly cleaned up before the * DuExtension was destroyed. * \***************************************************************************/
DuExtension::~DuExtension() { //
// Ensure proper destruction
//
}
//------------------------------------------------------------------------------
HRESULT DuExtension::InitClass() { s_msgidAsyncDestroy = RegisterGadgetMessage(&guidAysncDestroy); return s_msgidAsyncDestroy != 0 ? S_OK : (HRESULT) GetLastError(); }
/***************************************************************************\
* * DuExtension::Create * * Create() initializes a new DuExtension and attaches it to the subject Gadget * being modified. * \***************************************************************************/
HRESULT DuExtension::Create( IN Visual * pgvSubject, // Gadget being "extended"
IN PRID pridExtension, // Short ID for DuExtension
IN UINT nOptions) // Options
{ AssertMsg(pridExtension > 0, "Must have valid PRID");
//
// Do not allow attaching a DuExtension to a Gadget that has already started
// the destruction process.
//
HGADGET hgadSubject = DUserCastHandle(pgvSubject);
BOOL fStartDelete; if ((!IsStartDelete(hgadSubject, &fStartDelete)) || fStartDelete) { return DU_E_STARTDESTROY; }
//
// Setup options
//
m_fAsyncDestroy = TestFlag(nOptions, oAsyncDestroy);
//
// Determine if this DuExtension is already attached to the Gadget being
// extended.
//
DuExtension * pbExist; if (SUCCEEDED(pgvSubject->GetProperty(pridExtension, (void **) &pbExist))) { AssertMsg(pbExist != NULL, "Existing Extension must not be NULL"); if (TestFlag(nOptions, oUseExisting)) { return DU_S_ALREADYEXISTS; } else { //
// Already attached, but can't use the existing one. We need to
// remove the existing DuExtension before attaching the new one.
// After calling RemoveExisting(), the DuExtension should no longer
// be attached to the Gadget.
//
pbExist->GetStub()->OnRemoveExisting(); Assert(FAILED(pgvSubject->GetProperty(pridExtension, (void **) &pbExist))); } }
//
// Setup a listener to be notifyed when the RootGadget is destroyed.
//
HRESULT hr = S_OK; m_pgvSubject = pgvSubject; m_pridListen = pridExtension;
if (FAILED(pgvSubject->SetProperty(pridExtension, this)) || FAILED(pgvSubject->AddHandlerG(GM_DESTROY, GetStub()))) {
hr = E_OUTOFMEMORY; goto Error; }
//
// Successfully created the DuExtension
//
return S_OK;
Error: return hr; }
/***************************************************************************\
* * DuExtension::Destroy * * Destroy() is called from the derived class to cleanup resources associated * with the DuExtension. * \***************************************************************************/
void DuExtension::Destroy() { //
// Since the DuExtension is being destroyed, need to ensure that it is no
// longer "attached" to the Gadget being extended
//
if ((m_pridListen != 0) && (m_pgvSubject != NULL)) { DuExtension * pb; if (SUCCEEDED(m_pgvSubject->GetProperty(m_pridListen, (void **) &pb))) { if (pb == this) { m_pgvSubject->RemoveProperty(m_pridListen); } } }
Delete(); }
/***************************************************************************\
* * DuExtension::DeleteHandle * * DeleteHandle() starts the destruction process for the DuExtension. * \***************************************************************************/
void DuExtension::DeleteHandle() { Delete(); }
//------------------------------------------------------------------------------
HRESULT DuExtension::ApiOnEvent(EventMsg * pmsg) { switch (GET_EVENT_DEST(pmsg)) { case GMF_DIRECT: if (m_fAsyncDestroy && (pmsg->nMsg == s_msgidAsyncDestroy)) { GetStub()->OnAsyncDestroy(); return DU_S_PARTIAL; } break;
case GMF_EVENT: if (pmsg->nMsg == GM_DESTROY) { if (((GMSG_DESTROY *) pmsg)->nCode == GDESTROY_FINAL) { GetStub()->OnDestroySubject(); return DU_S_PARTIAL; } } break; }
return SListener::ApiOnEvent(pmsg); }
/***************************************************************************\
* * DuExtension::ApiOnRemoveExisting * * ApiOnRemoveExisting() is called when creating a new DuExtension to remove * an existing DuExtension already attached to the subject Gadget. * \***************************************************************************/
HRESULT DuExtension::ApiOnRemoveExisting(Extension::OnRemoveExistingMsg *) { return S_OK; }
/***************************************************************************\
* * DuExtension::ApiOnDestroySubject * * ApiOnDestroySubject() notifies the derived DuExtension that the subject * Gadget being modified has been destroyed. * \***************************************************************************/
HRESULT DuExtension::ApiOnDestroySubject(Extension::OnDestroySubjectMsg *) { return S_OK; }
/***************************************************************************\
* * DuExtension::ApiOnAsyncDestroy * * ApiOnAsyncDestroy() is called when the DuExtension receives an asynchronous * destruction message that was previously posted. This provides the derived * DuExtension an opportunity to start the destruction process without being * nested several levels. * \***************************************************************************/
HRESULT DuExtension::ApiOnAsyncDestroy(Extension::OnAsyncDestroyMsg *) { return S_OK; }
/***************************************************************************\
* * DuExtension::PostAsyncDestroy * * PostAsyncDestroy() queues an asynchronous destruction message. This * provides the derived DuExtension an opportunity to start the destruction * process without being nested several levels. * \***************************************************************************/
void DuExtension::PostAsyncDestroy() { AssertMsg(m_fAsyncDestroy, "Must create DuExtension with oAsyncDestroy if want to destroy asynchronously"); Assert(s_msgidAsyncDestroy != 0); EventMsg msg; ZeroMemory(&msg, sizeof(msg)); msg.cbSize = sizeof(msg); msg.hgadMsg = GetHandle(); msg.nMsg = s_msgidAsyncDestroy;
DUserPostEvent(&msg, 0); }
/***************************************************************************\
* * DuExtension::GetExtension * * GetExtension() retrieves the DuExtension of a specific type currently * attached to the subject Gadget. * \***************************************************************************/
DuExtension * DuExtension::GetExtension(Visual * pgvSubject, PRID prid) { DuExtension * pbExist; if (SUCCEEDED(pgvSubject->GetProperty(prid, (void **) &pbExist))) { AssertMsg(pbExist != NULL, "Attached DuExtension must be valid"); return pbExist; } return NULL; }
#endif // ENABLE_MSGTABLE_API
|