|
|
//
// compart.cpp
//
// Compartment example.
//
#include "globals.h"
#include "mark.h"
//+---------------------------------------------------------------------------
//
// _InitCompartment
//
// Initialize a compartment on a particular context.
//
// The Mark sample doesn't really do any with its context compartment, this
// code is purely for demonstration purposes.
//----------------------------------------------------------------------------
BOOL CMarkTextService::_InitContextCompartment(ITfContext *pContext) { ITfCompartmentMgr *pCompartmentMgr; ITfCompartment *pCompartment; VARIANT varValue; HRESULT hr;
// we want the mgr associated with pContext
if (pContext->QueryInterface(IID_ITfCompartmentMgr, (void **)&pCompartmentMgr) != S_OK) return FALSE;
hr = E_FAIL;
if (pCompartmentMgr->GetCompartment(c_guidMarkContextCompartment, &pCompartment) != S_OK) goto Exit;
// if we don't initialize the value, it will be VT_EMPTY
// but let's initialize it to 0
// NB: to keep things simple, we use a VT_I4
// but you could use VT_UNKNOWN and store a pointer to anything
varValue.vt = VT_I4; varValue.lVal = 0; // arbitrary value
hr = pCompartment->SetValue(_tfClientId, &varValue);
pCompartment->Release();
Exit: pCompartmentMgr->Release();
return (hr == S_OK); }
//+---------------------------------------------------------------------------
//
// _UninitCompartment
//
// Uninitialize a compartment on a particular context.
//
// The Mark sample doesn't really do any with its context compartment, this
// code is purely for demonstration purposes.
//----------------------------------------------------------------------------
void CMarkTextService::_UninitCompartment(ITfContext *pContext) { ITfCompartmentMgr *pCompartmentMgr;
// we want the mgr associated with pContext
if (pContext->QueryInterface(IID_ITfCompartmentMgr, (void **)&pCompartmentMgr) != S_OK) return;
pCompartmentMgr->ClearCompartment(_tfClientId, c_guidMarkContextCompartment);
pCompartmentMgr->Release(); }
//+---------------------------------------------------------------------------
//
// _Menu_OnSetGlobalCompartment
//
// Callback for the "Set Global Compartment" menu item.
// Set the value of our global compartment. This will trigger a callback
// on our compartment change sinks in every thread/instance of this service.
//----------------------------------------------------------------------------
/* static */ void CMarkTextService::_Menu_OnSetGlobalCompartment(CMarkTextService *_this) { ITfCompartmentMgr *pCompartmentMgr; ITfCompartment *pCompartment; VARIANT varValue;
// we want the global mgr
if (_this->_pThreadMgr->GetGlobalCompartment(&pCompartmentMgr) != S_OK) return;
if (pCompartmentMgr->GetCompartment(c_guidMarkGlobalCompartment, &pCompartment) != S_OK) { pCompartment = NULL; goto Exit; }
// let's toggle the value
// notice that global compartments are persisted, unlike all others
if (FAILED(pCompartment->GetValue(&varValue))) // will return S_FALSE if varValue.vt == VT_EMPTY
goto Exit;
if (varValue.vt == VT_EMPTY) { // if we get here, the compartment has never been initialized
varValue.vt = VT_I4; varValue.lVal = 0; }
// toggle value
varValue.lVal = ~varValue.lVal;
pCompartment->SetValue(_this->_tfClientId, &varValue);
Exit: SafeRelease(pCompartment); pCompartmentMgr->Release(); }
//+---------------------------------------------------------------------------
//
// _InitGlobalCompartment
//
// Ininit a change sink on our global compartment. The system will call us
// back anytime the compartment is modified from any thread in the desktop.
//
// NB: ITfCompartmentEventSink's attached to thread local compartments will
// only get callbacks to changes that occur within a single thread. Global
// compartments are different.
//----------------------------------------------------------------------------
BOOL CMarkTextService::_InitGlobalCompartment() { ITfCompartmentMgr *pCompartmentMgr; ITfCompartment *pCompartment; BOOL fRet;
// we want the global mgr
if (_pThreadMgr->GetGlobalCompartment(&pCompartmentMgr) != S_OK) return FALSE;
fRet = FALSE;
if (pCompartmentMgr->GetCompartment(c_guidMarkGlobalCompartment, &pCompartment) != S_OK) goto Exit;
fRet = AdviseSink(pCompartment, (ITfCompartmentEventSink *)this, IID_ITfCompartmentEventSink, &_dwGlobalCompartmentEventSinkCookie);
pCompartment->Release();
if (!fRet) { // don't try to unadvise a bogus cookie later
_dwGlobalCompartmentEventSinkCookie = TF_INVALID_COOKIE; }
Exit: pCompartmentMgr->Release(); return fRet; }
//+---------------------------------------------------------------------------
//
// _UninitCompartment
//
// Unitialize the global compartment if we have previously accessed it.
// This method only frees resources the system has allocated in this thread.
// Other threads can still access the global compartment, and the value (which
// is persisted across the desktop) does not change.
//
// Also, uninit the change sink we attached to the compartment.
//----------------------------------------------------------------------------
void CMarkTextService::_UninitGlobalCompartment() { ITfCompartmentMgr *pCompartmentMgr; ITfCompartment *pCompartment;
// we want the global mgr
if (_pThreadMgr->GetGlobalCompartment(&pCompartmentMgr) != S_OK) return;
// unadvise our event sink
if (pCompartmentMgr->GetCompartment(c_guidMarkGlobalCompartment, &pCompartment) == S_OK) { UnadviseSink(pCompartment, &_dwGlobalCompartmentEventSinkCookie); pCompartment->Release(); }
// let the system free resources associated with the compartment on this
// thread
pCompartmentMgr->ClearCompartment(_tfClientId, c_guidMarkGlobalCompartment);
pCompartmentMgr->Release(); }
//+---------------------------------------------------------------------------
//
// ITfCompartmentEventSink::OnChange
//
// TSF calls this method anytime our private global compartment is modified,
// even from other threads/processes.
//----------------------------------------------------------------------------
STDAPI CMarkTextService::OnChange(REFGUID rguidCompartment) { // nothing to do in this sample
return S_OK; }
|