589 lines
17 KiB
C++
589 lines
17 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:
|
|
// TpcConpt.h
|
|
//
|
|
// Description:
|
|
// The header file for InkCollectorEvents, which is designed
|
|
// to be used by C++ applications as a base class for handling
|
|
// Ink Collector events. This base class is meant to be used
|
|
// as a template; application-specific event handling should
|
|
// be handled by the derived class. For an example of how to use
|
|
// this class, refer to CMyInkEvents in EventSink.h.
|
|
//
|
|
// This file contains both the class definitions and the implementation
|
|
// of the methods.
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
#ifndef TPCCONPT_H
|
|
#define TPCCONPT_H
|
|
|
|
/////////////////////////////////////////////////////////
|
|
//
|
|
// class InkCollectorEvents
|
|
//
|
|
// The InkCollectorEvents class handles passing Ink Collector
|
|
// events from the Ink Collector to the user of this class.
|
|
// It sets up the connection between the InkCollector and
|
|
// this class in AdviseInkCollector. 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.
|
|
//
|
|
// Two important points to consider when using this class:
|
|
//
|
|
// 1. You must do more than simply override the event's
|
|
// virtual function in order to handle the event. For
|
|
// all but default events, you will have to call
|
|
// IInkCollector::SetEventInterest to guarantee getting
|
|
// an event. Stroke, CursorInRange, andCursorOutOfRange are
|
|
// the only event interests that are on by default.
|
|
//
|
|
// 2. This object marshals itself free threaded so all implemented
|
|
// event handlers need to be free threaded as well. Of particular
|
|
// importance is using Window's APIs, which may cause a switch to
|
|
// another thread; the event handler is not guaranteed
|
|
// to be running on the same thread as the window connected
|
|
// with the Ink Collector.
|
|
//
|
|
/////////////////////////////////////////////////////////
|
|
class InkCollectorEvents : public _IInkCollectorEvents
|
|
{
|
|
public:
|
|
|
|
//
|
|
// IUnknown Interface
|
|
//
|
|
HRESULT __stdcall QueryInterface(REFIID riid, void **ppvObject)
|
|
{
|
|
// Validate the input
|
|
if (NULL == ppvObject)
|
|
{
|
|
return E_POINTER;
|
|
}
|
|
|
|
// This object only supports IDispatch/_IInkCollectorEvents
|
|
if ((riid == IID_IUnknown)
|
|
|| (riid == IID_IDispatch)
|
|
|| (riid == DIID__IInkCollectorEvents))
|
|
{
|
|
*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;
|
|
}
|
|
else if (riid == IID_IMarshal)
|
|
{
|
|
// Assert that the free threaded marshaller has been
|
|
// initialized. It is necessary to call Init() before
|
|
// invoking this method.
|
|
assert(NULL != m_punkFTM);
|
|
|
|
// Use free threaded marshalling.
|
|
return m_punkFTM->QueryInterface(riid, ppvObject);
|
|
}
|
|
|
|
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_ICEStroke:
|
|
Stroke(
|
|
(IInkCursor*) pdispparams->rgvarg[2].pdispVal,
|
|
(IInkStrokeDisp*) pdispparams->rgvarg[1].pdispVal,
|
|
(VARIANT_BOOL *)pdispparams->rgvarg[0].pboolVal);
|
|
break;
|
|
|
|
case DISPID_ICECursorDown:
|
|
CursorDown(
|
|
(IInkCursor*) pdispparams->rgvarg[1].pdispVal,
|
|
(IInkStrokeDisp*) pdispparams->rgvarg[0].pdispVal);
|
|
break;
|
|
|
|
case DISPID_ICENewPackets:
|
|
NewPackets(
|
|
(IInkCursor*) pdispparams->rgvarg[3].pdispVal,
|
|
(IInkStrokeDisp*) pdispparams->rgvarg[2].pdispVal,
|
|
pdispparams->rgvarg[1].lVal,
|
|
pdispparams->rgvarg[0].pvarVal);
|
|
break;
|
|
|
|
case DISPID_IPEDblClick:
|
|
DblClick(
|
|
(VARIANT_BOOL *)pdispparams->rgvarg[0].pboolVal);
|
|
break;
|
|
|
|
case DISPID_IPEMouseMove:
|
|
MouseMove(
|
|
(InkMouseButton) pdispparams->rgvarg[4].lVal,
|
|
(InkShiftKeyModifierFlags) pdispparams->rgvarg[3].lVal,
|
|
pdispparams->rgvarg[2].lVal,
|
|
pdispparams->rgvarg[1].lVal,
|
|
(VARIANT_BOOL *)pdispparams->rgvarg[0].pboolVal);
|
|
break;
|
|
|
|
case DISPID_IPEMouseDown:
|
|
MouseDown(
|
|
(InkMouseButton) pdispparams->rgvarg[4].lVal,
|
|
(InkShiftKeyModifierFlags) pdispparams->rgvarg[3].lVal,
|
|
pdispparams->rgvarg[2].lVal,
|
|
pdispparams->rgvarg[1].lVal,
|
|
(VARIANT_BOOL *)pdispparams->rgvarg[0].pboolVal);
|
|
break;
|
|
|
|
case DISPID_IPEMouseUp:
|
|
MouseUp(
|
|
(InkMouseButton) pdispparams->rgvarg[4].lVal,
|
|
(InkShiftKeyModifierFlags) pdispparams->rgvarg[3].lVal,
|
|
pdispparams->rgvarg[2].lVal,
|
|
pdispparams->rgvarg[1].lVal,
|
|
(VARIANT_BOOL *)pdispparams->rgvarg[0].pboolVal);
|
|
break;
|
|
|
|
case DISPID_IPEMouseWheel:
|
|
MouseWheel(
|
|
(InkMouseButton) pdispparams->rgvarg[5].lVal,
|
|
(InkShiftKeyModifierFlags) pdispparams->rgvarg[4].lVal,
|
|
pdispparams->rgvarg[3].lVal,
|
|
pdispparams->rgvarg[2].lVal,
|
|
pdispparams->rgvarg[1].lVal,
|
|
(VARIANT_BOOL *)pdispparams->rgvarg[0].pboolVal);
|
|
break;
|
|
|
|
case DISPID_ICENewInAirPackets:
|
|
NewInAirPackets(
|
|
(IInkCursor*) pdispparams->rgvarg[2].pdispVal,
|
|
pdispparams->rgvarg[1].lVal,
|
|
pdispparams->rgvarg[0].pvarVal);
|
|
break;
|
|
|
|
case DISPID_ICECursorButtonDown:
|
|
CursorButtonDown(
|
|
(IInkCursor*) pdispparams->rgvarg[1].pdispVal,
|
|
(IInkCursorButton*) pdispparams->rgvarg[0].pdispVal);
|
|
break;
|
|
|
|
case DISPID_ICECursorButtonUp:
|
|
CursorButtonUp(
|
|
(IInkCursor*) pdispparams->rgvarg[1].pdispVal,
|
|
(IInkCursorButton*) pdispparams->rgvarg[0].pdispVal);
|
|
break;
|
|
|
|
case DISPID_ICECursorInRange:
|
|
CursorInRange(
|
|
(IInkCursor*) pdispparams->rgvarg[2].pdispVal,
|
|
(VARIANT_BOOL) pdispparams->rgvarg[1].iVal,
|
|
pdispparams->rgvarg[0]);
|
|
break;
|
|
|
|
case DISPID_ICECursorOutOfRange:
|
|
CursorOutOfRange(
|
|
(IInkCursor*) pdispparams->rgvarg[0].pdispVal);
|
|
break;
|
|
|
|
case DISPID_ICESystemGesture:
|
|
SystemGesture(
|
|
(IInkCursor*) pdispparams->rgvarg[6].pdispVal,
|
|
(InkSystemGesture) pdispparams->rgvarg[5].lVal,
|
|
pdispparams->rgvarg[4].lVal,
|
|
pdispparams->rgvarg[3].lVal,
|
|
pdispparams->rgvarg[2].lVal,
|
|
pdispparams->rgvarg[1].bstrVal,
|
|
pdispparams->rgvarg[0].lVal);
|
|
break;
|
|
|
|
case DISPID_ICEGesture:
|
|
Gesture(
|
|
(IInkCursor*) pdispparams->rgvarg[3].pdispVal,
|
|
(IInkStrokes*) pdispparams->rgvarg[2].pdispVal,
|
|
pdispparams->rgvarg[1],
|
|
(VARIANT_BOOL *)pdispparams->rgvarg[0].pboolVal);
|
|
break;
|
|
|
|
case DISPID_ICETabletAdded:
|
|
TabletAdded(
|
|
(IInkTablet*) pdispparams->rgvarg[0].pdispVal);
|
|
break;
|
|
|
|
case DISPID_ICETabletRemoved:
|
|
TabletRemoved(
|
|
pdispparams->rgvarg[0].lVal);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//
|
|
// Events
|
|
//
|
|
|
|
virtual void Stroke(
|
|
IInkCursor* Cursor,
|
|
IInkStrokeDisp* Stroke,
|
|
VARIANT_BOOL *Cancel)
|
|
{
|
|
// This is a place holder designed to be overridden by
|
|
// user of this class.
|
|
return;
|
|
}
|
|
|
|
virtual void CursorDown(
|
|
IInkCursor* Cursor,
|
|
IInkStrokeDisp* Stroke)
|
|
{
|
|
// This is a place holder designed to be overridden by
|
|
// user of this class.
|
|
return;
|
|
}
|
|
|
|
virtual void NewPackets(
|
|
IInkCursor* Cursor,
|
|
IInkStrokeDisp* Stroke,
|
|
long PacketCount,
|
|
VARIANT* PacketData)
|
|
{
|
|
// This is a place holder designed to be overridden by
|
|
// user of this class.
|
|
return;
|
|
}
|
|
|
|
virtual void DblClick(
|
|
VARIANT_BOOL *Cancel)
|
|
{
|
|
// This is a place holder designed to be overridden by
|
|
// user of this class.
|
|
return;
|
|
}
|
|
|
|
virtual void MouseMove(
|
|
InkMouseButton Button,
|
|
InkShiftKeyModifierFlags Shift,
|
|
long pX,
|
|
long pY,
|
|
VARIANT_BOOL *Cancel)
|
|
{
|
|
// This is a place holder designed to be overridden by
|
|
// user of this class.
|
|
return;
|
|
}
|
|
|
|
virtual void MouseDown(
|
|
InkMouseButton Button,
|
|
InkShiftKeyModifierFlags Shift,
|
|
long pX,
|
|
long pY,
|
|
VARIANT_BOOL *Cancel)
|
|
{
|
|
// This is a place holder designed to be overridden by
|
|
// user of this class.
|
|
return;
|
|
}
|
|
|
|
virtual void MouseUp(
|
|
InkMouseButton Button,
|
|
InkShiftKeyModifierFlags Shift,
|
|
long pX,
|
|
long pY,
|
|
VARIANT_BOOL *Cancel)
|
|
{
|
|
// This is a place holder designed to be overridden by
|
|
// user of this class.
|
|
return;
|
|
}
|
|
|
|
virtual void MouseWheel(
|
|
InkMouseButton Button,
|
|
InkShiftKeyModifierFlags Shift,
|
|
long Delta,
|
|
long X,
|
|
long Y,
|
|
VARIANT_BOOL *Cancel)
|
|
{
|
|
// This is a place holder designed to be overridden by
|
|
// user of this class.
|
|
return;
|
|
}
|
|
|
|
virtual void NewInAirPackets(
|
|
IInkCursor* Cursor,
|
|
long lPacketCount,
|
|
VARIANT* PacketData)
|
|
{
|
|
// This is a place holder designed to be overridden by
|
|
// user of this class.
|
|
return;
|
|
}
|
|
|
|
virtual void CursorButtonDown(
|
|
IInkCursor* Cursor,
|
|
IInkCursorButton* Button)
|
|
{
|
|
// This is a place holder designed to be overridden by
|
|
// user of this class.
|
|
return;
|
|
}
|
|
|
|
virtual void CursorButtonUp(
|
|
IInkCursor* Cursor,
|
|
IInkCursorButton* Button)
|
|
{
|
|
// This is a place holder designed to be overridden by
|
|
// user of this class.
|
|
return;
|
|
}
|
|
|
|
virtual void CursorInRange(
|
|
IInkCursor* Cursor,
|
|
VARIANT_BOOL NewCursor,
|
|
VARIANT ButtonsState)
|
|
{
|
|
// This is a place holder designed to be overridden by
|
|
// user of this class.
|
|
return;
|
|
}
|
|
|
|
virtual void CursorOutOfRange(
|
|
IInkCursor* Cursor)
|
|
{
|
|
// This is a place holder designed to be overridden by
|
|
// user of this class.
|
|
return;
|
|
}
|
|
|
|
virtual void SystemGesture(
|
|
IInkCursor* Cursor,
|
|
InkSystemGesture Id,
|
|
long X,
|
|
long Y,
|
|
long Modifier,
|
|
BSTR Character,
|
|
long CursorMode)
|
|
{
|
|
// This is a place holder designed to be overridden by
|
|
// user of this class.
|
|
return;
|
|
}
|
|
|
|
virtual void Gesture(
|
|
IInkCursor* Cursor,
|
|
IInkStrokes* Strokes,
|
|
VARIANT Gestures,
|
|
VARIANT_BOOL* Cancel)
|
|
{
|
|
// This is a place holder designed to be overridden by
|
|
// user of this class.
|
|
return;
|
|
}
|
|
|
|
virtual void TabletAdded(
|
|
IInkTablet* Tablet)
|
|
{
|
|
// This is a place holder designed to be overridden by
|
|
// user of this class.
|
|
return;
|
|
}
|
|
|
|
virtual void TabletRemoved(
|
|
long TabletId)
|
|
{
|
|
// This is a place holder designed to be overridden by
|
|
// user of this class.
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Methods
|
|
//
|
|
|
|
// Constructor: initialize memory to null.
|
|
InkCollectorEvents()
|
|
{
|
|
m_pIConnectionPoint = NULL;
|
|
m_punkFTM = NULL;
|
|
}
|
|
|
|
// Destructor: free resources
|
|
~InkCollectorEvents()
|
|
{
|
|
UnadviseInkCollector();
|
|
|
|
if (m_punkFTM != NULL)
|
|
{
|
|
m_punkFTM->Release();
|
|
}
|
|
}
|
|
|
|
// Init: set up free threaded marshaller.
|
|
// It is necessary to call this method before using
|
|
// this class to handle events.
|
|
HRESULT Init()
|
|
{
|
|
return CoCreateFreeThreadedMarshaler(this, &m_punkFTM);
|
|
}
|
|
|
|
// Set up connection between sink and Ink Collector
|
|
HRESULT AdviseInkCollector(
|
|
IInkCollector *pIInkCollector)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
// Check to ensure that the sink is not currently connected
|
|
// with another Ink Collector...
|
|
if (NULL == m_pIConnectionPoint)
|
|
{
|
|
// Get the connection point container
|
|
IConnectionPointContainer *pIConnectionPointContainer;
|
|
hr = pIInkCollector->QueryInterface(
|
|
IID_IConnectionPointContainer,
|
|
(void **) &pIConnectionPointContainer);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
// Find the connection point for Ink Collector events
|
|
hr = pIConnectionPointContainer->FindConnectionPoint(
|
|
__uuidof(_IInkCollectorEvents), &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 an Ink Collector, return a
|
|
// failure; only one Ink Collector can be attached at any given time.
|
|
else
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
// Remove the connection of the sink to the Ink Collector
|
|
HRESULT UnadviseInkCollector()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
// If there the ink collector 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 InkCollector
|
|
IConnectionPoint *m_pIConnectionPoint;
|
|
|
|
// Cookie returned from advise
|
|
DWORD m_dwCookie;
|
|
|
|
// Free threaded marshaler.
|
|
IUnknown *m_punkFTM;
|
|
};
|
|
|
|
#endif // TPCCONPT_H
|