2025-11-28 00:35:46 +09:00

259 lines
7.0 KiB
C++

// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// Module:
// EventSinks.h
//
// Description:
// This file contains definitions of the event sink templates,
// further inherited by the CMathInputControlEventListener class.
//
// Event source interface used is:
// _IMathInputControlEvents
//
//--------------------------------------------------------------------------
#pragma once
// IDispEventSimpleImpl requires a constant as a sink id
#define SINK_ID 1
/////////////////////////////////////////////////////////
//
// IMathInputControlEvents
//
// The IMathInputControlEvents class handles passing of Math Input Control
// events from Math Input Control to the user of this class.
// It sets up connection between the IMathInputControl and
// this class in AdviseMathInputControl method. In the Invoke method,
// it converts the IDispatch event notification into a
// call to a virtual function which the user of this class
// can override to process a particular event.
//
/////////////////////////////////////////////////////////
class IMathInputControlEvents: public _IMathInputControlEvents
{
public:
//
// IUnknown Interface
//
HRESULT __stdcall QueryInterface(REFIID riid, void **ppvObject)
{
// Validate the input
if (NULL == ppvObject)
{
return E_POINTER;
}
// This object only supports IDispatch/_IMathInputControlEvents
if ((riid == IID_IUnknown)
|| (riid == IID_IDispatch)
|| (riid == DIID__IMathInputControlEvents))
{
*ppvObject = (IDispatch *) this;
// Note: we do not AddRef here because the lifetime
// of this object does not depend on reference counting
// but on the duration of the connection set up by
// the user of this class.
return S_OK;
}
return E_NOINTERFACE;
}
virtual ULONG STDMETHODCALLTYPE AddRef()
{
// Note: we do not AddRef here because the lifetime
// of this object does not depend on reference counting
// but on the duration of the connection set up by
// the user of this class.
return 1;
}
virtual ULONG STDMETHODCALLTYPE Release()
{
// Note: we do not do Release here because the lifetime
// of this object does not depend on reference counting
// but on the duration of the connection set up by
// the user of this class.
return 1;
}
//
// IDispatch Interface
//
STDMETHOD(GetTypeInfoCount)(UINT* /*pctinfo*/)
{
// This method is not needed for processing events
return E_NOTIMPL;
}
STDMETHOD(GetTypeInfo)(
UINT /*itinfo*/,
LCID /*lcid*/,
ITypeInfo** /*pptinfo*/)
{
// This method is not needed for processing events
return E_NOTIMPL;
}
STDMETHOD(GetIDsOfNames)(
REFIID /*riid*/,
LPOLESTR* /*rgszNames*/,
UINT /*cNames*/,
LCID /*lcid*/,
DISPID* /*rgdispid*/)
{
// This method is not needed for processing events
return E_NOTIMPL;
}
// Invoke translates from IDispatch to an event callout
// that can be overriden by a subclass of this class
STDMETHOD(Invoke)(
DISPID dispidMember,
REFIID /*riid*/,
LCID /*lcid*/,
WORD /*wFlags*/,
DISPPARAMS* pdispparams,
VARIANT* /*pvarResult*/,
EXCEPINFO* /*pexcepinfo*/,
UINT* /*puArgErr*/)
{
switch(dispidMember)
{
case DISPID_MICInsert:
OnMICInsert((BSTR)pdispparams->rgvarg[0].bstrVal);
break;
case DISPID_MICClose:
OnMICClose();
break;
case DISPID_MICClear:
OnMICClear();
break;
default:
break;
}
return S_OK;
}
//
// Events
// Pure virtual functions that will be overriden in the main class
//
virtual HRESULT OnMICInsert(BSTR RecoResult) = 0;
virtual HRESULT OnMICClose(void) = 0;
virtual HRESULT OnMICClear(void) = 0;
//
// Methods
//
// Constructor
IMathInputControlEvents()
{
m_pIConnectionPoint = NULL;
}
// Destructor
~IMathInputControlEvents()
{
UnadviseMathInputControl();
}
// Set up connection between sink and Math Input Control
HRESULT AdviseMathInputControl(
IMathInputControl *pIMathInputControl)
{
HRESULT hr = S_OK;
// Check to ensure that the sink is not currently connected
// with another Math Input Control...
if (NULL == m_pIConnectionPoint)
{
// Get the connection point container
IConnectionPointContainer *pIConnectionPointContainer;
hr = pIMathInputControl->QueryInterface(
IID_IConnectionPointContainer,
(void **) &pIConnectionPointContainer);
if (FAILED(hr))
{
return hr;
}
// Find the connection point for Math Input Control events
hr = pIConnectionPointContainer->FindConnectionPoint(
__uuidof(_IMathInputControlEvents), &m_pIConnectionPoint);
if (SUCCEEDED(hr))
{
// Hook up sink to connection point
hr = m_pIConnectionPoint->Advise(this, &m_dwCookie);
}
if (FAILED(hr))
{
// Clean up after an error
if (m_pIConnectionPoint)
{
m_pIConnectionPoint->Release();
m_pIConnectionPoint = NULL;
}
}
// We don't need the connection point container any more
pIConnectionPointContainer->Release();
}
// If the sink is already connected to a Math Input Control, return a
// failure. Only one Math Input Control can be attached at any given time.
else
{
hr = E_FAIL;
}
return hr;
}
// Remove the connection of the sink to the Math Input Control
HRESULT UnadviseMathInputControl()
{
HRESULT hr = S_OK;
// If some Math Input Control is connected to the sink,
// remove it. Otherwise, do nothing (there is nothing
// to unadvise).
if (m_pIConnectionPoint != NULL)
{
hr = m_pIConnectionPoint->Unadvise(m_dwCookie);
m_pIConnectionPoint->Release();
m_pIConnectionPoint = NULL;
}
return hr;
}
private:
//
// Data Members
//
// Connection point on Math Input Control
IConnectionPoint *m_pIConnectionPoint;
// Cookie returned from advise
DWORD m_dwCookie;
};