locked
IRealTimeStylus

    Question

  • Hi ,
    I don' t find how to use the RealTimeStylus interfaces to create plugins in C++.
    I only want to grab pressure information and subpixels coordinates of the tablet input.
    Here is my test, but it crashes.

    Someone can help me ?
    Thx.
    //------------------------------------------------------------------------
    class cStylusAsyncPlugin : public IStylusAsyncPlugin
    {
    public:
        /** The destructor. */
        virtual  ~cStylusAsyncPlugin()
        {
        }

        /** The constructor. */
        cStylusAsyncPlugin() :
            IStylusAsyncPlugin()
        {
        }

        virtual HRESULT STDMETHODCALLTYPE RealTimeStylusEnabled(  IRealTimeStylus *piRtsSrc, ULONG cTcidCount, const TABLET_CONTEXT_ID *pTcids)
        {
            return 0;
        }
       
        virtual HRESULT STDMETHODCALLTYPE RealTimeStylusDisabled(
            /* [in] */ IRealTimeStylus *piRtsSrc,
            /* [range][in] */ ULONG cTcidCount,
            /* [size_is][in] */ const TABLET_CONTEXT_ID *pTcids)
        {
            return 0;
        }

        virtual HRESULT STDMETHODCALLTYPE StylusInRange(
            /* [in] */ IRealTimeStylus *piRtsSrc,
            /* [in] */ TABLET_CONTEXT_ID tcid,
            /* [in] */ STYLUS_ID sid)
        {
            return 0;
        }
       
        virtual HRESULT STDMETHODCALLTYPE StylusOutOfRange(
            /* [in] */ IRealTimeStylus *piRtsSrc,
            /* [in] */ TABLET_CONTEXT_ID tcid,
            /* [in] */ STYLUS_ID sid)
        {
            return 0;
        }
       
        virtual HRESULT STDMETHODCALLTYPE StylusDown(
            /* [in] */ IRealTimeStylus *piRtsSrc,
            /* [in] */ const StylusInfo *pStylusInfo,
            /* [range][in] */ ULONG cPropCountPerPkt,
            /* [size_is][in] */ LONG *pPacket,
            /* [out][in] */ LONG **ppInOutPkt)
        {
            return 0;
        }
        virtual HRESULT STDMETHODCALLTYPE StylusUp(
            /* [in] */ IRealTimeStylus *piRtsSrc,
            /* [in] */ const StylusInfo *pStylusInfo,
            /* [range][in] */ ULONG cPropCountPerPkt,
            /* [size_is][in] */ LONG *pPacket,
            /* [out][in] */ LONG **ppInOutPkt)
        {
            return 0;
        }
        virtual HRESULT STDMETHODCALLTYPE StylusButtonDown(
            /* [in] */ IRealTimeStylus *piRtsSrc,
            /* [in] */ STYLUS_ID sid,
            /* [in] */ const GUID *pGuidStylusButton,
            /* [out][in] */ POINT *pStylusPos)
        {
            return 0;
        }
        virtual HRESULT STDMETHODCALLTYPE StylusButtonUp(
            /* [in] */ IRealTimeStylus *piRtsSrc,
            /* [in] */ STYLUS_ID sid,
            /* [in] */ const GUID *pGuidStylusButton,
            /* [out][in] */ POINT *pStylusPos)
        {
            return 0;
        }
        virtual HRESULT STDMETHODCALLTYPE InAirPackets(
            /* [in] */ IRealTimeStylus *piRtsSrc,
            /* [in] */ const StylusInfo *pStylusInfo,
            /* [in] */ ULONG cPktCount,
            /* [range][in] */ ULONG cPktBuffLength,
            /* [size_is][in] */ LONG *pPackets,
            /* [out][in] */ ULONG *pcInOutPkts,
            /* [out][in] */ LONG **ppInOutPkts)
        {
            return 0;
        }
        virtual HRESULT STDMETHODCALLTYPE Packets(
            /* [in] */ IRealTimeStylus *piRtsSrc,
            /* [in] */ const StylusInfo *pStylusInfo,
            /* [in] */ ULONG cPktCount,
            /* [range][in] */ ULONG cPktBuffLength,
            /* [size_is][in] */ LONG *pPackets,
            /* [out][in] */ ULONG *pcInOutPkts,
            /* [out][in] */ LONG **ppInOutPkts)
        {
            return 0;
        }
        virtual HRESULT STDMETHODCALLTYPE CustomStylusDataAdded(
            /* [in] */ IRealTimeStylus *piRtsSrc,
            /* [in] */ const GUID *pGuidId,
            /* [range][in] */ ULONG cbData,
            /* [unique][size_is][in] */ const BYTE *pbData)
        {
            return 0;
        }
        virtual HRESULT STDMETHODCALLTYPE SystemEvent(
            /* [in] */ IRealTimeStylus *piRtsSrc,
            /* [in] */ TABLET_CONTEXT_ID tcid,
            /* [in] */ STYLUS_ID sid,
            /* [in] */ SYSTEM_EVENT event,
            /* [in] */ SYSTEM_EVENT_DATA eventdata)
        {
            return 0;
        }
        virtual HRESULT STDMETHODCALLTYPE TabletAdded(
            /* [in] */ IRealTimeStylus *piRtsSrc,
            /* [in] */ IInkTablet *piTablet)
        {
            return 0;
        }
        virtual HRESULT STDMETHODCALLTYPE TabletRemoved(
            /* [in] */ IRealTimeStylus *piRtsSrc,
            /* [in] */ LONG iTabletIndex)
        {
            return 0;
        }
        virtual HRESULT STDMETHODCALLTYPE Error(
            /* [in] */ IRealTimeStylus *piRtsSrc,
            /* [in] */ IStylusPlugin *piPlugin,
            /* [in] */ RealTimeStylusDataInterest dataInterest,
            /* [in] */ HRESULT hrErrorCode,
            /* [out][in] */ LONG_PTR *lptrKey)
        {
            return 0;
        }
        virtual HRESULT STDMETHODCALLTYPE UpdateMapping(
            /* [in] */ IRealTimeStylus *piRtsSrc)
        {
            return 0;
        }
        virtual HRESULT STDMETHODCALLTYPE DataInterest(
            /* [retval][out] */ RealTimeStylusDataInterest *pDataInterest)
        {
            *pDataInterest = RTSDI_AllData;
            return S_OK;
        }


        HRESULT QueryInterface(    REFIID riid, void **ppvObject)
        {
           // Validate the input
            if (NULL == ppvObject)
            {
                return E_POINTER;
            }

            if ((riid == IID_IUnknown)
                || (riid == IID_IStylusPlugin)
                || (riid == IID_IStylusAsyncPlugin))
            {
                *ppvObject = this;
                return S_OK;
            }
            *ppvObject = 0;
            return E_NOINTERFACE;
        }

        virtual ULONG AddRef()
        {
            return 1;
        }
       
        virtual ULONG Release()
        {
            return 1;
        }
       
    };

    static cStylusAsyncPlugin sgStylusAsyncPlugin;
    static IRealTimeStylus* sgRealTimeStylus=0;

    static HRESULT Init(HWND iHWnd)
    {
        HRESULT hr = CoCreateInstance(CLSID_RealTimeStylus, NULL, CLSCTX_ALL, IID_IRealTimeStylus, (void **)&sgRealTimeStylus);
        if (FAILED(hr))
        {
            return hr;
        }

        hr = sgRealTimeStylus->AddStylusAsyncPlugin(0, &sgStylusAsyncPlugin);
        if (FAILED(hr))
        {
            return hr;
        }

        hr = sgRealTimeStylus->put_HWND((long)iHWnd);
        if (FAILED(hr))
        {
            return hr;
        }
        return sgRealTimeStylus->put_Enabled(VARIANT_TRUE);

    }



    Friday, January 19, 2007 1:54 PM

Answers

  • Herve,
    With RTS, both COM and Managed versions, you can obtain the pressure from the 'Packets' event. This event is fired for every incoming packet to the RealTimeStylus.


    A Packet consists of X, Y coordinates as well as other data that the digitizer supports, such as Pressure. On the StylusDown event, you can call the IRealTimeStylus::GetPacketDescriptionData Method (http://msdn2.microsoft.com/en-us/library/ms700633.aspx ) to determine the order of the packets (you can even request which packets you want via the IRealTimeStylus::SetDesiredPacketDescription Method. Mouse and resistive Digitizers (Touch) will likely have only X and Y, while Electro-magnetic Digitizers (found in Tablet PC's or some external digitizers) will also have the pressure value.

    Here is what you are probably looking for - the code to do it.

    I have added pressure sensitivity to the CPP version of the RealTimeStylusPlugin sample that ships with the Windows Vista SDK. If you build that sample, just replace the handler for 'Packets' in the CustomRenderer.cpp with the following:

    STDMETHODIMP CCustomRenderer::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)

    {

    ULONG cPropertyCount = cPktBuffLength/cPktCount;

    // For each new packet received, extract the X,Y data and draw a small circle around the result

    for (ULONG i = 0; i < cPktCount; i += cPropertyCount)

    {

    // Packet data always has X followed by Y followed by the rest

    LONG x = pPackets[ i ];

    LONG y = pPackets[i+1];

    LONG pressure = 1;

    if(cPropertyCount > 2) // Make sure there are enough packets of interest 

    {

    pressure = pPackets[i+2];

    // Reduce the 0-255 value to something smaller

    pressure = (LONG)((float)pressure / 10.0);

    }

    // Since the packet data is in ink space coordinates, we need to convert to pixels...

    HiMetricToPixel(&x, &y);

    // Draw a circle corresponding to the packet (using the pressure value to change the size of the ellipse)

    Ellipse(m_hDC, x-2, y-2, x+pressure, y+pressure);

    }

    return S_OK;

    }

    Friday, February 23, 2007 11:10 PM