text: // 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.
  
  // GestureHandler.cpp : Implementation of CGestureHandler
  
  #include "stdafx.h"
  #include "GestureHandler.h"
  
  
  // CGestureHandler
  // IStylusAsyncPlugin Interface implementation
  
  STDMETHODIMP CGestureHandler::Packets(
              /* [in] */ IRealTimeStylus *piRtsSrc,
              /* [in] */ const StylusInfo *pStylusInfo,
              /* [in] */ ULONG cPktCount,
              /* [in] */ ULONG cPktBuffLength,
              /* [size_is][in] */ LONG *pPackets,
              /* [out][in] */ ULONG *pcInOutPkts,
              /* [out][in] */ LONG **ppInOutPkts)
  {
      return S_OK;
  }
  
  STDMETHODIMP CGestureHandler::StylusDown(
              /* [in] */ IRealTimeStylus *piRtsSrc,
              /* [in] */ const StylusInfo *pStylusInfo,
              /* [in] */ ULONG cPropCountPerPkt,
              /* [size_is][in] */ LONG *pPacket,
              /* [out][in] */ LONG **ppInOutPkt)
  {
      return S_OK;
  }
  
  STDMETHODIMP CGestureHandler::StylusUp(
              /* [in] */ IRealTimeStylus *piRtsSrc,
              /* [in] */ const StylusInfo *pStylusInfo,
              /* [in] */ ULONG cPropCountPerPkt,
              /* [size_is][in] */ LONG *pPacket,
              /* [out][in] */ LONG **ppInOutPkt)
  {
      return S_OK;
  }
  
  STDMETHODIMP CGestureHandler::Error(
              /* [in] */ IRealTimeStylus *piRtsSrc,
              /* [in] */ IStylusPlugin *piPlugin,
              /* [in] */ RealTimeStylusDataInterest dataInterest,
              /* [in] */ HRESULT hrErrorCode,
              /* [out][in] */ LONG_PTR *lptrKey)
  {
      CString strError;
      strError.Format(L"An error occured. Error code: %d", hrErrorCode);
      TRACE(strError);
      return S_OK;
  }
  
  STDMETHODIMP CGestureHandler::DataInterest(
              /* [retval][out] */ RealTimeStylusDataInterest *pDataInterest)
  {
      *pDataInterest = (RealTimeStylusDataInterest)(RTSDI_CustomStylusDataAdded | RTSDI_Error);
      return S_OK;
  }
  
  
  
  /// The remaining interface methods are not used in this sample application
  STDMETHODIMP CGestureHandler::RealTimeStylusEnabled(
              /* [in] */ IRealTimeStylus *piRtsSrc,
              /* [in] */ ULONG cTcidCount,
              /* [size_is][in] */ const TABLET_CONTEXT_ID *pTcids)
  {
      return S_OK;
  }
  
  STDMETHODIMP CGestureHandler::RealTimeStylusDisabled(
              /* [in] */ IRealTimeStylus *piRtsSrc,
              /* [in] */ ULONG cTcidCount,
              /* [size_is][in] */ const TABLET_CONTEXT_ID *pTcids)
  {
      return S_OK;
  }
  
  STDMETHODIMP CGestureHandler::StylusInRange(
              /* [in] */ IRealTimeStylus *piRtsSrc,
              /* [in] */ TABLET_CONTEXT_ID tcid,
              /* [in] */ STYLUS_ID sid)
  {
      return S_OK;
  }
  
  STDMETHODIMP CGestureHandler::StylusOutOfRange(
              /* [in] */ IRealTimeStylus *piRtsSrc,
              /* [in] */ TABLET_CONTEXT_ID tcid,
              /* [in] */ STYLUS_ID sid)
  {
      return S_OK;
  }
  
  STDMETHODIMP CGestureHandler::StylusButtonDown(
              /* [in] */ IRealTimeStylus *piRtsSrc,
              /* [in] */ STYLUS_ID sid,
              /* [in] */ const GUID *pGuidStylusButton,
              /* [out][in] */ POINT *pStylusPos)
  {
      return S_OK;
  }
  
  STDMETHODIMP CGestureHandler::StylusButtonUp(
              /* [in] */ IRealTimeStylus *piRtsSrc,
              /* [in] */ STYLUS_ID sid,
              /* [in] */ const GUID *pGuidStylusButton,
              /* [out][in] */ POINT *pStylusPos)
  {
      return S_OK;
  }
  
  STDMETHODIMP CGestureHandler::InAirPackets(
              /* [in] */ IRealTimeStylus *piRtsSrc,
              /* [in] */ const StylusInfo *pStylusInfo,
              /* [in] */ ULONG cPktCount,
              /* [in] */ ULONG cPktBuffLength,
              /* [size_is][in] */ LONG *pPackets,
              /* [out][in] */ ULONG *pcInOutPkts,
              /* [out][in] */ LONG **ppInOutPkts)
  {
      return S_OK;
  }
  
  STDMETHODIMP CGestureHandler::CustomStylusDataAdded(
              /* [in] */ IRealTimeStylus *piRtsSrc,
              /* [in] */ const GUID *pGuidId,
              /* [in] */ ULONG cbData,
              /* [in] */ const BYTE *pbData)
  {
      // Did we get passed gesture data?
      if (*pGuidId == GUID_GESTURE_DATA)
      {
          /* See if the data pointer actually points to something.
             If more than one alternate is detected ignore the
             lower alternates */
          if ((pbData != NULL) && (cbData % sizeof(GESTURE_DATA)))
          {
              // Access the data coming as a GESTURE_DATA structure
              GESTURE_DATA* pGD = (GESTURE_DATA*)pbData;
  
              CString strStatus;
              CString strGestureId;
  
              // Helper function that maps the gesture ID to a string value
              SetGestureString(pGD->gestureId, &strGestureId);
  
              strStatus.Format(L"Gesture=%s\tConfidence=%d\tStrokes=%d", strGestureId, pGD->recoConfidence, pGD->strokeCount);
              m_pStatusControl->SetWindowTextW(strStatus);
          }
          else
          {
              m_pStatusControl->SetWindowTextW(L"Not gesture data.");
          }
      }
      else
      {
          m_pStatusControl->SetWindowTextW(L"Not gesture data.");
      }
  
      return S_OK;
  }
  
  STDMETHODIMP CGestureHandler::SystemEvent(
              /* [in] */ IRealTimeStylus *piRtsSrc,
              /* [in] */ TABLET_CONTEXT_ID tcid,
              /* [in] */ STYLUS_ID sid,
              /* [in] */ SYSTEM_EVENT event,
              /* [in] */ SYSTEM_EVENT_DATA eventdata)
  {
      return S_OK;
  }
  
  STDMETHODIMP CGestureHandler::TabletAdded(
              /* [in] */ IRealTimeStylus *piRtsSrc,
              /* [in] */ IInkTablet *piTablet)
  {
      return S_OK;
  }
  
  STDMETHODIMP CGestureHandler::TabletRemoved(
              /* [in] */ IRealTimeStylus *piRtsSrc,
              /* [in] */ LONG iTabletIndex)
  {
      return S_OK;
  }
  
  STDMETHODIMP CGestureHandler::UpdateMapping(
              /* [in] */ IRealTimeStylus *piRtsSrc)
  {
      return S_OK;
  }
  
  // Helper functions
  
  // Sets a string identifying the gesture
  void CGestureHandler::SetGestureString(int gestureID, CString* strResult)
  {
      switch (gestureID)
      {
          case IAG_AllGestures:
           strResult->SetString(L"AllGestures", sizeof("AllGestures"));
           break;
  
          case IAG_NoGesture:
              strResult->SetString(L"NoGesture", sizeof("NoGesture"));
              break;
  
          case IAG_Scratchout:
              strResult->SetString(L"Scratchout", sizeof("Scratchout"));
              break;
  
          case IAG_Triangle:
              strResult->SetString(L"Triangle", sizeof("Triangle"));
              break;
  
          case IAG_Square:
              strResult->SetString(L"Square", sizeof("Square"));
              break;
  
          case IAG_Star:
              strResult->SetString(L"Star", sizeof("Star"));
              break;
  
          case IAG_Check:
              strResult->SetString(L"Check", sizeof("Check"));
              break;
  
          case IAG_Curlicue:
              strResult->SetString(L"Curlicue", sizeof("Curlicue"));
              break;
  
          case IAG_DoubleCurlicue:
              strResult->SetString(L"DoubleCurlicue", sizeof("DoubleCurlicue"));
              break;
  
          case IAG_Circle:
              strResult->SetString(L"Circle", sizeof("Circle"));
              break;
  
          case IAG_DoubleCircle:
              strResult->SetString(L"DoubleCircle", sizeof("DoubleCircle"));
              break;
  
          case IAG_SemiCircleLeft:
              strResult->SetString(L"SemiCircleLeft", sizeof("SemiCircleLeft"));
              break;
  
          case IAG_SemiCircleRight:
              strResult->SetString(L"SemiCircleRight", sizeof("SemiCircleRight"));
              break;
  
          case IAG_ChevronUp:
              strResult->SetString(L"ChevronUp", sizeof("ChevronUp"));
              break;
  
          case IAG_ChevronDown:
              strResult->SetString(L"ChevronDown", sizeof("ChevronDown"));
              break;
  
          case IAG_ChevronLeft:
              strResult->SetString(L"ChevronLeft", sizeof("ChevronLeft"));
              break;
  
          case IAG_ChevronRight:
              strResult->SetString(L"ChevronRight", sizeof("ChevronRight"));
              break;
  
          case IAG_ArrowUp:
              strResult->SetString(L"ArrowUp", sizeof("ArrowUp"));
              break;
  
          case IAG_ArrowDown:
              strResult->SetString(L"ArrowDown", sizeof("ArrowDown"));
              break;
  
          case IAG_ArrowLeft:
              strResult->SetString(L"ArrowLeft", sizeof("ArrowLeft"));
              break;
  
          case IAG_ArrowRight:
              strResult->SetString(L"ArrowRight", sizeof("ArrowRight"));
              break;
  
          case IAG_Up:
              strResult->SetString(L"Up", sizeof("Up"));
              break;
  
          case IAG_Down:
              strResult->SetString(L"Down", sizeof("Down"));
              break;
  
          case IAG_Left:
              strResult->SetString(L"Left", sizeof("Left"));
              break;
  
          case IAG_Right:
              strResult->SetString(L"Right", sizeof("Right"));
              break;
  
          case IAG_UpDown:
              strResult->SetString(L"UpDown", sizeof("UpDown"));
              break;
  
          case IAG_DownUp:
              strResult->SetString(L"UpDown", sizeof("UpDown"));
              break;
  
          case IAG_LeftRight:
              strResult->SetString(L"UpDown", sizeof("UpDown"));
              break;
  
          case IAG_RightLeft:
              strResult->SetString(L"RightLeft", sizeof("RightLeft"));
              break;
  
          case IAG_UpLeftLong:
              strResult->SetString(L"UpLeftLong", sizeof("UpLeftLong"));
              break;
  
          case IAG_UpRightLong:
              strResult->SetString(L"UpRightLong", sizeof("UpRightLong"));
              break;
  
          case IAG_DownLeftLong:
              strResult->SetString(L"DownLeftLong", sizeof("DownLeftLong"));
              break;
  
          case IAG_DownRightLong:
              strResult->SetString(L"DownRightLong", sizeof("DownRightLong"));
              break;
  
          case IAG_UpLeft:
              strResult->SetString(L"UpLeft", sizeof("UpLeft"));
              break;
  
          case IAG_UpRight:
              strResult->SetString(L"UpRight", sizeof("UpRight"));
              break;
  
          case IAG_DownLeft:
              strResult->SetString(L"DownLeft", sizeof("DownLeft"));
              break;
  
          case IAG_DownRight:
              strResult->SetString(L"DownRight", sizeof("DownRight"));
              break;
  
          case IAG_LeftUp:
              strResult->SetString(L"LeftUp", sizeof("LeftUp"));
              break;
  
          case IAG_LeftDown:
              strResult->SetString(L"LeftDown", sizeof("LeftDown"));
              break;
  
          case IAG_RightUp:
              strResult->SetString(L"RightUp", sizeof("RightUp"));
              break;
  
          case IAG_RightDown:
              strResult->SetString(L"RightDown", sizeof("RightDown"));
              break;
  
          case IAG_Exclamation:
              strResult->SetString(L"Exclamation", sizeof("Exclamation"));
              break;
  
          case IAG_Tap:
              strResult->SetString(L"Tap", sizeof("Tap"));
              break;
  
          case IAG_DoubleTap:
              strResult->SetString(L"DoubleTap", sizeof("DoubleTap"));
              break;
  
          default:
              strResult->SetString(L"Unknown", sizeof("Unknown"));
              break;
      }
  }
  