You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
215 lines
6.6 KiB
215 lines
6.6 KiB
//
|
|
// 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;
|
|
}
|