Listen For CursorDown Event - Happy to pay if someone can figure this out!
Listen For CursorDown Event - Happy to pay if someone can figure this out!
I'm using a stylus to draw on the screen using GDIP and there is a small delay between when the stylus touches the screen and the line starts drawing.
After a bit of research i found the below article that describes the timeline of events when a stylus is used.
https://docs.microsoft.com/en-us/windows/desktop/tablet/timeline-of-mouse-messages-and-system-events
A Image from the article below shows where the delay is happening. So I was wondering if there is any way to listen for the CursorDown Event. I found a couple of articles on MSDN with examples in other languages but i have no idea how to convert them to AHK or even if they can be converted.
https://docs.microsoft.com/en-us/previous-versions/ms827586%28v%3dmsdn.10%29
https://docs.microsoft.com/en-us/previous-versions/aa510879(v=msdn.10)
If anyone has any ideas it would be greatly appreciated.
thanks GRIMBOTO
Edit: Still trying to figure this out happy to compensate your time if you can find a solution. Currently using AHKHID.ahk but as stated above the small delay is there and it makes writing on the screen quickly difficult.
After a bit of research i found the below article that describes the timeline of events when a stylus is used.
https://docs.microsoft.com/en-us/windows/desktop/tablet/timeline-of-mouse-messages-and-system-events
A Image from the article below shows where the delay is happening. So I was wondering if there is any way to listen for the CursorDown Event. I found a couple of articles on MSDN with examples in other languages but i have no idea how to convert them to AHK or even if they can be converted.
https://docs.microsoft.com/en-us/previous-versions/ms827586%28v%3dmsdn.10%29
https://docs.microsoft.com/en-us/previous-versions/aa510879(v=msdn.10)
If anyone has any ideas it would be greatly appreciated.
thanks GRIMBOTO
Edit: Still trying to figure this out happy to compensate your time if you can find a solution. Currently using AHKHID.ahk but as stated above the small delay is there and it makes writing on the screen quickly difficult.
Re: Listen For CursorDown Event - Happy to pay if someone can figure this out!
bump still looking for a solution for this if anyone has any ideas?
Re: Listen For CursorDown Event - Happy to pay if someone can figure this out!
There is always the brute-force method of running a timer and checking the mouse position, though you may be looking for something more direct or more efficient.
Re: Listen For CursorDown Event - Happy to pay if someone can figure this out!
idk if this can be used the way u intend to(as a blanket hook). seems like these CursorDown events are sent to specific "controls"(eg InkCollector), which need to be associated with a particular hwnd.
which is probably why the docs keep saying
v2 is better for working with COM, backporting this to v1 was absolute cancer
which is probably why the docs keep saying
here's lifting the pen off of the usb tablet vertically and moving it off of the associated window. u can see that no events get captured when interacting with an unrelated window behind the GUIWhen a given action is performed, the system events (prefixed with ISG_) are sent and received almost instantaneously by the application. The mouse messages (prefixed with WM_) are sent when the action is performed and are received by the application after the time it takes for the event to be processed by the Microsoft Windows messaging service.
...
Applications can listen to system events by using the InkCollector object and listening for the SystemGesture event on it. You can set which events an application listens to.
Code: Select all
#NoEnv
#SingleInstance Force
#Requires AutoHotkey v1.1.33+
if !InkObjDll := DllCall("LoadLibrary", "Str", "C:\Program Files\Common Files\microsoft shared\ink\InkObj.dll", "Ptr")
{
MsgBox % "InkObj.dll not found: " A_LastError
ExitApp
}
CLSID_InkCollector := "{43FB1553-AD74-4ee8-88E4-3E6DAAC915DB}"
IID_IInkCollector := "{F0F060B5-8B1F-4a7c-89EC-880692588A4F}"
pInkCollector := ComObjCreate(CLSID_InkCollector, IID_IInkCollector)
pInkCollectorVtbl := NumGet(pInkCollector+0, "Ptr")
; 8: HRESULT STDMETHODCALLTYPE put_hWnd(/* [in] */ LONG_PTR NewWindow)
pput_hWnd := NumGet(pInkCollectorVtbl + (8 * A_PtrSize), "Ptr")
; 10: HRESULT STDMETHODCALLTYPE put_Enabled(/* [in] */ VARIANT_BOOL Collecting)
pput_Enabled := NumGet(pInkCollectorVtbl + (10 * A_PtrSize), "Ptr")
; 46: HRESULT STDMETHODCALLTYPE SetEventInterest(/* [in] */ InkCollectorEventInterest EventId, /* [in] */ VARIANT_BOOL Listen)
pSetEventInterest := NumGet(pInkCollectorVtbl + (46 * A_PtrSize), "Ptr")
ICEI_CursorDown := 0
VARIANT_TRUE := -1
S_OK := 0
; need to say u want to track a certain event
hr := DllCall(pSetEventInterest, "Ptr", pInkCollector, "Int", ICEI_CursorDown, "Short", VARIANT_TRUE, "Ptr")
if (hr != S_OK)
{
MsgBox % "InkCollector::SetEventInterest failed, HRESULT was " hr ". ErrorLevel was " ErrorLevel
ExitApp
}
; the hwnd of a window, which will host the InkCollector, is required, so we create our own
Gui New, +HwndhGui +AlwaysOnTop
Gui Show, w400 h200, write inside me
; associate the InkCollector with our GUI
hr := DllCall(pput_hWnd, "Ptr", pInkCollector, "Ptr", hGui, "Ptr")
if (hr != S_OK)
{
MsgBox % "InkCollector::put_hWnd failed, HRESULT was " hr ". ErrorLevel was " ErrorLevel
ExitApp
}
; an u also need to switch the InkCollector on, apparently
hr := DllCall(pput_Enabled, "Ptr", pInkCollector, "Short", VARIANT_TRUE, "Ptr")
if (hr != S_OK)
{
MsgBox % "InkCollector::put_Enabled failed, HRESULT was " hr ". ErrorLevel was " ErrorLevel
ExitApp
}
VT_UNKNOWN := 0xD
InkCollector := ComObject(VT_UNKNOWN, pInkCollector, 1) ; wrap into a comobject, because ComObjConnect requires one, instead of a raw pointer
ComObjConnect(InkCollector, "_IInkCollectorEvents_")
Escape::
GuiClose:
GuiEscape:
ExitApp
; void CursorDown([in] IInkCursor *Cursor, [in] IInkStrokeDisp *Stroke);
_IInkCollectorEvents_CursorDown(pIInkCursor, pIInkStrokeDisp, OriginalInkCollectorComObj) {
ToolTip % A_ThisFunc "`n" A_TickCount
}
; void CursorInRange([in] IInkCursor *Cursor, [in] VARIANT_BOOL NewCursor, [in] VARIANT ButtonsState);
_IInkCollectorEvents_CursorInRange(pIInkCursor, NewCursor, ButtonsState, OriginalInkCollectorComObj) {
ToolTip % A_ThisFunc "`n" A_TickCount
}
; void CursorOutOfRange([in] IInkCursor *Cursor)
_IInkCollectorEvents_CursorOutOfRange(pIInkCursor, OriginalInkCollectorComObj) {
ToolTip % A_ThisFunc "`n" A_TickCount
}
v2 is better for working with COM, backporting this to v1 was absolute cancer
Code: Select all
#Requires AutoHotkey v2.0-a136-feda41f4
#SingleInstance Force
#DllLoad 'C:\Program Files\Common Files\microsoft shared\ink\InkObj.dll'
CLSID_InkCollector := '{43FB1553-AD74-4ee8-88E4-3E6DAAC915DB}'
IID_IInkCollector := '{F0F060B5-8B1F-4a7c-89EC-880692588A4F}'
InkCollector := ComObject(CLSID_InkCollector, IID_IInkCollector)
ICEI_CursorDown := 0
VARIANT_TRUE := -1
; 46: HRESULT STDMETHODCALLTYPE SetEventInterest(/* [in] */ InkCollectorEventInterest EventId, /* [in] */ VARIANT_BOOL Listen)
ComCall(46, InkCollector, 'Int', ICEI_CursorDown, 'Short', VARIANT_TRUE)
G := Gui('+AlwaysOnTop', 'write inside me')
G.Show('w400 h200')
G.OnEvent('Close', (*) => ExitApp())
G.OnEvent('Escape', (*) => ExitApp())
Esc::ExitApp()
; 8: HRESULT STDMETHODCALLTYPE put_hWnd(/* [in] */ LONG_PTR NewWindow)
ComCall(8, InkCollector, 'Ptr', G.Hwnd)
; 10: HRESULT STDMETHODCALLTYPE put_Enabled(/* [in] */ VARIANT_BOOL Collecting)
ComCall(10, InkCollector, 'Short', VARIANT_TRUE)
ComObjConnect(InkCollector, '_IInkCollectorEvents_')
; void CursorDown([in] IInkCursor *Cursor, [in] IInkStrokeDisp *Stroke);
_IInkCollectorEvents_CursorDown(pIInkCursor, pIInkStrokeDisp, *) => ToolTip(A_ThisFunc '`n' A_TickCount)
; void CursorInRange([in] IInkCursor *Cursor, [in] VARIANT_BOOL NewCursor, [in] VARIANT ButtonsState);
_IInkCollectorEvents_CursorInRange(pIInkCursor, NewCursor, ButtonsState, *) => ToolTip(A_ThisFunc '`n' A_TickCount)
; void CursorOutOfRange([in] IInkCursor *Cursor)
_IInkCollectorEvents_CursorOutOfRange(pIInkCursor, *) => ToolTip(A_ThisFunc '`n' A_TickCount)
Re: Listen For CursorDown Event - Happy to pay if someone can figure this out!
What are real benefits?v2 is better for working with COM, backporting this to v1 was absolute cancer
I see only small changing in syntax how to call com methods.
Instead of this:
Code: Select all
DllCall(NumGet(NumGet(InkCollector+0)+46*A_PtrSize), "ptr", InkCollector)
Code: Select all
ComCall(46, InkCollector)
Re: Listen For CursorDown Event - Happy to pay if someone can figure this out!
u get automatic error reporting, cleanup, parameter/type validation
generally, if ure trying to do something wrong, chances are v2 will complain about it
whereas in v1, ur script either crashes or does nothing. good luck debugging it, unless u specifically know what to look out for. i guess this wouldnt matter as much if u were already a COM god. most ppl arent, though
generally, if ure trying to do something wrong, chances are v2 will complain about it
whereas in v1, ur script either crashes or does nothing. good luck debugging it, unless u specifically know what to look out for. i guess this wouldnt matter as much if u were already a COM god. most ppl arent, though
Re: Listen For CursorDown Event - Happy to pay if someone can figure this out!
Thanks @swagfag that looks very helpful. Do you know if its possible to monitor the events without displaying the gui on the screen? I tried a transparent gui with window style +E0x20 to make it so i can click through but then it stopped receiving the events. If not would you have a link to where i can find the functions to change the color of the pen and clear all current ink?
thanks
thanks
Re: Listen For CursorDown Event - Happy to pay if someone can figure this out!
It would be easier to help you if you shared the code you are using. Can you share what you are working with so far?
Re: Listen For CursorDown Event - Happy to pay if someone can figure this out!
The code I'm currently using is part of a much larger script and hard to separate into just the part I want to uses this for. I'm basically making a touch interface for a old program that doesn't have one.
So the user draws on the screen then it gets converted into a line in the program.
My main goal is to replace AHKHID with the cursor down event. currently i'm just recording the mouse position while the mouse button is down drawing a line in the program. Looking at the inkcollector documents i might be able to use the stroke event to get this information aswell.
demo of current script
thanks GRimboto
So the user draws on the screen then it gets converted into a line in the program.
My main goal is to replace AHKHID with the cursor down event. currently i'm just recording the mouse position while the mouse button is down drawing a line in the program. Looking at the inkcollector documents i might be able to use the stroke event to get this information aswell.
demo of current script
thanks GRimboto
Re: Listen For CursorDown Event - Happy to pay if someone can figure this out!
So I've been having a look around and it looks like I should be using the RealTimeStylus object instead of the InkCollector Object as it suits my needs better.
I've managed to create the RealTimeStylus object and it appears to work but i'm having trouble connecting to the events. I need to create a IStylusSyncPlugin object to handle the events but I can't figure out how to get it done.
My Current Code:
rtsHeaderFile https://github.com/tpn/winsdk-7/blob/master/v7.1A/Include/RTSCOM.h
Example of the plugin being created - from https://github.com/microsoft/Windows-classic-samples/blob/master/Samples/Win7Samples/Touch/MTScratchpadRTStylus/cpp/MTScratchpadRTStylus.cpp
sample from MSDN -- https://docs.microsoft.com/en-us/windows/win32/tablet/realtimestylus-plug-in-sample
If anyone has any Ideas on how i can get this working that would be great.
Thanks Grimbot
I've managed to create the RealTimeStylus object and it appears to work but i'm having trouble connecting to the events. I need to create a IStylusSyncPlugin object to handle the events but I can't figure out how to get it done.
My Current Code:
Code: Select all
#NoEnv
#SingleInstance Force
#Requires AutoHotkey v1.1.33+
if !RtsCOMDll := DllCall("LoadLibrary", "Str", "C:\Program Files\Common Files\microsoft shared\ink\rtscom.dll", "Ptr")
{
MsgBox % "rtscom.dll not found: " A_LastError
ExitApp
}
CLSID_IRealTimeStylus := "{E26B366D-F998-43ce-836F-CB6D904432B0}"
IID_IRealTimeStylus := "{A8BB5D22-3144-4a7b-93CD-F34A16BE513A}"
IID_IStylusSyncPlugin := "{A157B174-482F-4d71-A3F6-3A41DDD11BE9}"
pRealTimeStylus := ComObjCreate(CLSID_IRealTimeStylus, IID_IRealTimeStylus)
pRealTimeStylusVtbl := NumGet(pRealTimeStylus+0, "Ptr")
pput_hWnd := NumGet(pRealTimeStylusVtbl + (6 * A_PtrSize), "Ptr")
pput_Enabled := NumGet(pRealTimeStylusVtbl + (4 * A_PtrSize), "Ptr")
pAddStylusSyncPlugin := NumGet(pRealTimeStylusVtbl + (9 * A_PtrSize), "Ptr")
VARIANT_TRUE := -1
VARIANT_False := 0
S_OK := 0
; the hwnd of a window, which will host the InkCollector, is required, so we create our own
Gui New, +HwndhGui +AlwaysOnTop ; -Caption
Gui Show, w400 h200, write inside me
WinSet, Transparent , 100, ahk_id %hGui%
; associate the InkCollector with our GUI
hr := DllCall(pput_hWnd, "Ptr", pRealTimeStylus, "Ptr", hGui, "Ptr")
if (hr != S_OK)
{
MsgBox % "pRealTimeStylus::put_hWnd failed, HRESULT was " hr ". ErrorLevel was " ErrorLevel
ExitApp
}
; RTS must be disabled to Add a StylusPlugin
hr := DllCall(pput_Enabled, "Ptr", pRealTimeStylus, "Short", VARIANT_False, "Ptr")
if (hr != S_OK)
{
MsgBox % "pRealTimeStylus::put_Enabled failed, HRESULT was " hr ". ErrorLevel was " ErrorLevel
ExitApp
}
/*
HRESULT ( STDMETHODCALLTYPE *AddStylusSyncPlugin )(
__RPC__in IRealTimeStylus * This,
/* [in] */ ULONG iIndex,
/* [in] */ __RPC__in_opt IStylusSyncPlugin *piPlugin);
*/
iIndex := 0
StylusSyncPlugin := new IStylusPlugin
hr := DllCall(pAddStylusSyncPlugin, "Ptr", pRealTimeStylus, "UInt", iIndex, "Ptr", StylusSyncPlugin, "Ptr")
if (hr != S_OK)
{
MsgBox % "pRealTimeStylus::AddStylusSyncPlugin, HRESULT was " hr ". ErrorLevel was " ErrorLevel
ExitApp
}
;enable RTS anfer Plugin is added
hr := DllCall(pput_Enabled, "Ptr", pRealTimeStylus, "Short", VARIANT_true, "Ptr")
if (hr != S_OK)
{
MsgBox % "pRealTimeStylus::put_Enabled failed, HRESULT was " hr ". ErrorLevel was " ErrorLevel
ExitApp
}
return
class IStylusPlugin
{
QueryInterface(thisInst,riid,ppvObject){
traytip, , testing
}
AddRef(thisInst){
}
Release(thisInst){
}
RealTimeStylusEnabled(thisInst,piRtsSrc,cTcidCount,pTcids){
}
RealTimeStylusDisabled(thisInst,piRtsSrc,cTcidCount,pTcids){
}
StylusInRange(thisInst,piRtsSrc,tcid,sid){
}
StylusOutOfRange(thisInst,piRtsSrc,tcid,sid){
}
StylusDown(thisInst,piRtsSrc,pStylusInfo,cPropCountPerPkt,pPacket,ppInOutPkt){
}
StylusUp(thisInst,piRtsSrc,pStylusInfo,cPropCountPerPkt,pPacket,ppInOutPkt){
}
StylusButtonDown(thisInst,piRtsSrc,sid,pGuidStylusButton,pStylusPos){
}
StylusButtonUp(thisInst,piRtsSrc,sid,pGuidStylusButton,pStylusPos){
}
InAirPackets(thisInst,piRtsSrc,pStylusInfo,cPktCount,cPktBuffLength,pPackets,pcInOutPkts,ppInOutPkts){
}
Packets(thisInst,piRtsSrc,pStylusInfo,cPktCount,cPktBuffLength,pPackets,pcInOutPkts,ppInOutPkts){
}
CustomStylusDataAdded(thisInst,piRtsSrc,pGuidId,cbData,pbData){
}
SystemEvent(thisInst,piRtsSrc,tcid,sid,event,eventdata){
}
TabletAdded(thisInst,piRtsSrc,piTablet){
}
TabletRemoved(thisInst,piRtsSrc,iTabletIndex){
}
Error(thisInst,piRtsSrc,piPlugin,dataInterest,hrErrorCode,lptrKey){
}
UpdateMapping(thisInst,piRtsSrc){
}
DataInterest(thisInst,pDataInterest){
}
}
Example of the plugin being created - from https://github.com/microsoft/Windows-classic-samples/blob/master/Samples/Win7Samples/Touch/MTScratchpadRTStylus/cpp/MTScratchpadRTStylus.cpp
Code: Select all
///////////////////////////////////////////////////////////////////////////////
// Real Time Stylus sync event handler
// Synchronous plugin, notitification receiver that changes pen color.
class CSyncEventHandlerRTS : public IStylusSyncPlugin
{
CSyncEventHandlerRTS();
virtual ~CSyncEventHandlerRTS();
public:
// Factory method
static IStylusSyncPlugin* Create(IRealTimeStylus* pRealTimeStylus);
// IStylusSyncPlugin methods
// Handled IStylusSyncPlugin methods, they require nontrivial implementation
STDMETHOD(StylusDown)(IRealTimeStylus* piSrcRtp, const StylusInfo* pStylusInfo, ULONG cPropCountPerPkt, LONG* pPacket, LONG** ppInOutPkt);
STDMETHOD(StylusUp)(IRealTimeStylus* piSrcRtp, const StylusInfo* pStylusInfo, ULONG cPropCountPerPkt, LONG* pPacket, LONG** ppInOutPkt);
STDMETHOD(Packets)(IRealTimeStylus* piSrcRtp, const StylusInfo* pStylusInfo, ULONG cPktCount, ULONG cPktBuffLength, LONG* pPackets, ULONG* pcInOutPkts, LONG** ppInOutPkts);
STDMETHOD(DataInterest)(RealTimeStylusDataInterest* pEventInterest);
// IStylusSyncPlugin methods with trivial inline implementation, they all return S_OK
STDMETHOD(RealTimeStylusEnabled)(IRealTimeStylus*, ULONG, const TABLET_CONTEXT_ID*) { return S_OK; }
STDMETHOD(RealTimeStylusDisabled)(IRealTimeStylus*, ULONG, const TABLET_CONTEXT_ID*) { return S_OK; }
STDMETHOD(StylusInRange)(IRealTimeStylus*, TABLET_CONTEXT_ID, STYLUS_ID) { return S_OK; }
STDMETHOD(StylusOutOfRange)(IRealTimeStylus*, TABLET_CONTEXT_ID, STYLUS_ID) { return S_OK; }
STDMETHOD(InAirPackets)(IRealTimeStylus*, const StylusInfo*, ULONG, ULONG, LONG*, ULONG*, LONG**) { return S_OK; }
STDMETHOD(StylusButtonUp)(IRealTimeStylus*, STYLUS_ID, const GUID*, POINT*) { return S_OK; }
STDMETHOD(StylusButtonDown)(IRealTimeStylus*, STYLUS_ID, const GUID*, POINT*) { return S_OK; }
STDMETHOD(SystemEvent)(IRealTimeStylus*, TABLET_CONTEXT_ID, STYLUS_ID, SYSTEM_EVENT, SYSTEM_EVENT_DATA) { return S_OK; }
STDMETHOD(TabletAdded)(IRealTimeStylus*, IInkTablet*) { return S_OK; }
STDMETHOD(TabletRemoved)(IRealTimeStylus*, LONG) { return S_OK; }
STDMETHOD(CustomStylusDataAdded)(IRealTimeStylus*, const GUID*, ULONG, const BYTE*) { return S_OK; }
STDMETHOD(Error)(IRealTimeStylus*, IStylusPlugin*, RealTimeStylusDataInterest, HRESULT, LONG_PTR*) { return S_OK; }
STDMETHOD(UpdateMapping)(IRealTimeStylus*) { return S_OK; }
// IUnknown methods
STDMETHOD_(ULONG,AddRef)();
STDMETHOD_(ULONG,Release)();
STDMETHOD(QueryInterface)(REFIID riid, LPVOID *ppvObj);
private:
LONG m_cRefCount; // COM object reference count
IUnknown* m_punkFTMarshaller; // free-threaded marshaller
int m_nContacts; // number of fingers currently in the contact with the touch digitizer
};
// CSyncEventHandlerRTS constructor.
CSyncEventHandlerRTS::CSyncEventHandlerRTS()
: m_cRefCount(1),
m_punkFTMarshaller(NULL),
m_nContacts(0)
{
}
// CSyncEventHandlerRTS destructor.
CSyncEventHandlerRTS::~CSyncEventHandlerRTS()
{
if (m_punkFTMarshaller != NULL)
{
m_punkFTMarshaller->Release();
}
}
// CSyncEventHandlerRTS factory method: creates new CSyncEventHandlerRTS and adds it to the synchronous
// plugin list of the RTS object.
// in:
// pRealTimeStylus RTS object
// returns:
// CSyncEventHandlerRTS object through IStylusSyncPlugin interface, or NULL on failure
IStylusSyncPlugin* CSyncEventHandlerRTS::Create(IRealTimeStylus* pRealTimeStylus)
{
// Check input argument
if (pRealTimeStylus == NULL)
{
ASSERT(pRealTimeStylus != NULL && L"CSyncEventHandlerRTS::Create: invalid argument RealTimeStylus");
return NULL;
}
// Instantiate CSyncEventHandlerRTS object
CSyncEventHandlerRTS* pSyncEventHandlerRTS = new CSyncEventHandlerRTS();
if (pSyncEventHandlerRTS == NULL)
{
ASSERT(pSyncEventHandlerRTS != NULL && L"CSyncEventHandlerRTS::Create: cannot create instance of CSyncEventHandlerRTS");
return NULL;
}
// Create free-threaded marshaller for this object and aggregate it.
HRESULT hr = CoCreateFreeThreadedMarshaler(pSyncEventHandlerRTS, &pSyncEventHandlerRTS->m_punkFTMarshaller);
if (FAILED(hr))
{
ASSERT(SUCCEEDED(hr) && L"CSyncEventHandlerRTS::Create: cannot create free-threaded marshaller");
pSyncEventHandlerRTS->Release();
return NULL;
}
// Add CSyncEventHandlerRTS object to the list of synchronous plugins in the RTS object.
hr = pRealTimeStylus->AddStylusSyncPlugin(
0, // insert plugin at position 0 in the sync plugin list
pSyncEventHandlerRTS); // plugin to be inserted - event handler CSyncEventHandlerRTS
if (FAILED(hr))
{
ASSERT(SUCCEEDED(hr) && L"CEventHandlerRTS::Create: failed to add CSyncEventHandlerRTS to the RealTimeStylus plugins");
pSyncEventHandlerRTS->Release();
return NULL;
}
return pSyncEventHandlerRTS;
}
// Pen-down notification.
// Sets the color for the newly started stroke and increments finger-down counter.
// in:
// piRtsSrc RTS object that has sent this event
// pStylusInfo StylusInfo struct (context ID, cursor ID, etc)
// cPropCountPerPkt number of properties per packet
// pPacket packet data (layout depends on packet description set)
// in/out:
// ppInOutPkt modified packet data (same layout as pPackets)
// returns:
// HRESULT error code
HRESULT CSyncEventHandlerRTS::StylusDown(
IRealTimeStylus* /* piRtsSrc */,
const StylusInfo* /* pStylusInfo */,
ULONG /* cPropCountPerPkt */,
LONG* /* pPacket */,
LONG** /* ppInOutPkt */)
{
// Get DrawingAttributes of DynamicRenderer
IInkDrawingAttributes* pDrawingAttributesDynamicRenderer;
HRESULT hr = g_pDynamicRenderer->get_DrawingAttributes(&pDrawingAttributesDynamicRenderer);
if (FAILED(hr))
{
ASSERT(SUCCEEDED(hr) && L"CSyncEventHandlerRTS::StylusDown: failed to get RTS's drawing attributes");
return hr;
}
// Set new stroke color to the DrawingAttributes of the DynamicRenderer
// If there are no fingers down, this is a primary contact
hr = pDrawingAttributesDynamicRenderer->put_Color(GetTouchColor(m_nContacts == 0));
if (FAILED(hr))
{
ASSERT(SUCCEEDED(hr) && L"CSyncEventHandlerRTS::StylusDown: failed to set color");
pDrawingAttributesDynamicRenderer->Release();
return hr;
}
pDrawingAttributesDynamicRenderer->Release();
++m_nContacts; // Increment finger-down counter
return S_OK;
}
// Pen-up notification.
// Decrements finger-down counter.
// in:
// piRtsSrc RTS object that has sent this event
// pStylusInfo StylusInfo struct (context ID, cursor ID, etc)
// cPropCountPerPkt number of properties per packet
// pPacket packet data (layout depends on packet description set)
// in/out:
// ppInOutPkt modified packet data (same layout as pPackets)
// returns:
// HRESULT error code
HRESULT CSyncEventHandlerRTS::StylusUp(
IRealTimeStylus* /* piRtsSrc */,
const StylusInfo* /* pStylusInfo */,
ULONG /* cPropCountPerPkt */,
LONG* /* pPacket */,
LONG** /* ppInOutPkt */)
{
--m_nContacts; // Decrement finger-down counter
return S_OK;
}
// Pen-move notification.
// In this case, does nothing, but likely to be used in a more complex application.
// RTS framework does stroke collection and rendering for us.
// in:
// piRtsRtp RTS object that has sent this event
// pStylusInfo StylusInfo struct (context ID, cursor ID, etc)
// cPktCount number of packets
// cPktBuffLength pPacket buffer size, in elements, equal to number of packets times number of properties per packet
// pPackets packet data (layout depends on packet description set)
// in/out:
// pcInOutPkts modified number of packets
// ppInOutPkts modified packet data (same layout as pPackets)
// returns:
// HRESULT error code
HRESULT CSyncEventHandlerRTS::Packets(
IRealTimeStylus* /* piSrcRtp */,
const StylusInfo* /* pStylusInfo */,
ULONG /* cPktCount */,
ULONG /* cPktBuffLength */,
LONG* /* pPackets */,
ULONG* /* pcInOutPkts */,
LONG** /* ppInOutPkts */)
{
return S_OK;
}
// Defines which handlers are called by the framework. We set the flags for pen-down, pen-up and pen-move.
// in/out:
// pDataInterest flags that enable/disable notification handlers
// returns:
// HRESULT error code
HRESULT CSyncEventHandlerRTS::DataInterest(RealTimeStylusDataInterest *pDataInterest)
{
*pDataInterest = (RealTimeStylusDataInterest)(RTSDI_StylusDown | RTSDI_Packets | RTSDI_StylusUp);
return S_OK;
}
// Increments reference count of the COM object.
// returns:
// reference count
ULONG CSyncEventHandlerRTS::AddRef()
{
return InterlockedIncrement(&m_cRefCount);
}
// Decrements reference count of the COM object, and deletes it
// if there are no more references left.
// returns:
// reference count
ULONG CSyncEventHandlerRTS::Release()
{
ULONG cNewRefCount = InterlockedDecrement(&m_cRefCount);
if (cNewRefCount == 0)
{
delete this;
}
return cNewRefCount;
}
// Returns a pointer to any interface supported by this object.
// If IID_IMarshal interface is requested, delegate the call to the aggregated
// free-threaded marshaller.
// If a valid pointer is returned, COM object reference count is increased.
// returns:
// pointer to the interface requested, or NULL if the interface is not supported by this object
HRESULT CSyncEventHandlerRTS::QueryInterface(REFIID riid, LPVOID *ppvObj)
{
if ((riid == IID_IStylusSyncPlugin) || (riid == IID_IUnknown))
{
*ppvObj = this;
AddRef();
return S_OK;
}
else if ((riid == IID_IMarshal) && (m_punkFTMarshaller != NULL))
{
return m_punkFTMarshaller->QueryInterface(riid, ppvObj);
}
*ppvObj = NULL;
return E_NOINTERFACE;
}
If anyone has any Ideas on how i can get this working that would be great.
Thanks Grimbot