Part of the IDL generated from the AgentObjectLib from Smalltalk is as
follows (note the section 'methods:'). But in the class _AgentEvents, it does not implement the selector #AcvitateInput:. // IDL generated by Dolphin Smalltalk from: // 'C:\WINNT\msagent\AgentCtl.dll' ... dispinterface _AgentEvents { properties: methods: [id(0x00000001)] void ActivateInput( BSTR CharacterID); I have a similar definition with another ActiveX server application that uses this type of method as a CallBack mechanism to inter-communicate. How do you define this method in Dolphin Smalltalk? // IDL generated by Dolphin Smalltalk from: // 'D:\HomeSeer\homeseer.exe' ... [ uuid(65FCD2C9-1AAC-466C-BA40-3E3B4603FA7E), hidden, oleautomation, nonextensible ] dispinterface __Application { properties: methods: [id(0x00000001)] void AHEvent( [in, out] BSTR* evstr); }; Thanks, Scott |
"Scott" <[hidden email]> wrote in message
news:[hidden email]... > Part of the IDL generated from the AgentObjectLib from Smalltalk is as > follows (note the section 'methods:'). But in the class _AgentEvents, > it does not implement the selector #AcvitateInput:. > It is not needed. See: http://groups.google.com/groups?q=AXEventSink&hl=en&safe=off&btnG=Google+Sea rch&meta=site%3Dgroups%26group%3Dcomp.lang.smalltalk.dolphin (Bearing in mind that the URL will probably get split into multiple lines and need reforming). > I have a similar definition with another ActiveX server application > that > uses this type of method as a CallBack mechanism to inter-communicate. > How do > you define this method in Dolphin Smalltalk? You should be able to use AXEventSink in much the same way. Regards Blair |
I did get that MSAgent example to work just fine. Thanks. I followed
the same steps for the HomeSeer activeX with tracing enabled, but nothing comes through. The HomeSeer activeX server documentation states that the callback be registered using a RegisterEventCB call (see idl below). I tried passing sink (see step 2 below) as the argument in step 5, but I get an Index 3 is out of bounds error (wrong argument type?). Any suggestions or other advice as to what agrument I should pass would be great or other ways to get notifications bach from HomeSeer. 1) hs := HS_Application createObject: 'HomeSeer.Application'. 2) sink := AXEventSink target: nil sourceTypeInfo: HS__Application typeInfo. 3) sink connect: hs. (returns 123048476 but MSAgent example returns 1) 4) sink isTracingEnabled: true. 5) hs registerEventCB: 3 obj: sink interface _Application : IDispatch { ... [id(0x6003000a)] HRESULT __stdcall RegisterEventCB( [in, out] long* evtype, [in, out] IDispatch** obj); ... }; dispinterface __Application { properties: methods: [id(0x00000001)] void AHEvent( [in, out] BSTR* evstr); }; Thanks, Scott "Blair McGlashan" <[hidden email]> wrote in message news:<9naqce$6jg75$[hidden email]>... > "Scott" <[hidden email]> wrote in message > news:[hidden email]... > > Part of the IDL generated from the AgentObjectLib from Smalltalk is as > > follows (note the section 'methods:'). But in the class _AgentEvents, > > it does not implement the selector #AcvitateInput:. > > > > It is not needed. See: > > http://groups.google.com/groups?q=AXEventSink&hl=en&safe=off&btnG=Google+Sea > rch&meta=site%3Dgroups%26group%3Dcomp.lang.smalltalk.dolphin > > (Bearing in mind that the URL will probably get split into multiple lines > and need reforming). > > > I have a similar definition with another ActiveX server application > > that > > uses this type of method as a CallBack mechanism to inter-communicate. > > How do > > you define this method in Dolphin Smalltalk? > > You should be able to use AXEventSink in much the same way. > > Regards > > Blair |
Any other suggestions?
> I did get that MSAgent example to work just fine. Thanks. I followed > the same steps for the HomeSeer activeX with tracing enabled, but > nothing comes through. > > The HomeSeer activeX server documentation states that the callback be > registered using a RegisterEventCB call (see idl below). I tried > passing sink (see step 2 below) as the argument in step 5, but I get > an Index 3 is out of bounds error (wrong argument type?). Any > suggestions or other advice as to what agrument I should pass would be > great or other ways to get notifications bach from HomeSeer. > > > 1) hs := HS_Application createObject: 'HomeSeer.Application'. > 2) sink := AXEventSink target: nil sourceTypeInfo: HS__Application > typeInfo. > 3) sink connect: hs. (returns 123048476 but MSAgent example returns 1) > 4) sink isTracingEnabled: true. > 5) hs registerEventCB: 3 obj: sink > > interface _Application : IDispatch { > ... > [id(0x6003000a)] > HRESULT __stdcall RegisterEventCB( > [in, out] long* evtype, > [in, out] IDispatch** obj); > ... > }; > > dispinterface __Application { > properties: > methods: > [id(0x00000001)] > void AHEvent( > [in, out] BSTR* evstr); > }; > > Thanks, > Scott > |
Scott
"Scott" <[hidden email]> wrote in message news:[hidden email]... > Any other suggestions? > > > I did get that MSAgent example to work just fine. Thanks. I followed > > the same steps for the HomeSeer activeX with tracing enabled, but > > nothing comes through. That is because it doesn't appear to use connection points, in which case AXEventSink will not work. > > > > The HomeSeer activeX server documentation states that the callback be > > registered using a RegisterEventCB call (see idl below). Sigh. Yet another custom event mechanism when there is a perfectly good "standard" one. >...I tried > > passing sink (see step 2 below) as the argument in step 5, but I get > > an Index 3 is out of bounds error (wrong argument type?). Any > > suggestions or other advice as to what agrument I should pass would be > > great or other ways to get notifications bach from HomeSeer. You'll need to create a custom implementation of IDispatch to pass to the RegisterEventCB method. If you subclass it off AXDispatchImpAbstract you need only implement the two 'subclass responsibility methods'. If you don't now how to implement them then (a) look at AXEventSink (but it is a generic implementation that reads type info. so this may confuse more than help) (b) Do a bit of XP, i.e just create your AXDispatchImpAbstract subclass, calling it, say, HomeSeerEventSink, and create empty implementations of the two subclass responsibility methods that contain only 'self halt' statements. Now run: hs := HS_Application createObject: 'HomeSeer.Application'. sink := HomeSeerEventSink new. hs registerEventCB: 3 obj: (sink queryInterface: IDispatch). Shortly you'll hit one of the breakpoints, probably in #invokeId:flags:withArguments: (since this is an event interface you may find that #idOfNames:whenNotKnown: never gets called). Go into the Debugger and using all the "context" you now have (argument types and values) flesh out the implementation. You'll should find that the first (id) argument matches that in the IDL for the single method in __Application, i.e. 1. If it is 1, then the control is sending you an AHEvent(), if not then it is invoking some other method that is not declared in the IDL, which is unlikely. You can ignore the flags argument in this case, and the final array argument should contain a single element being the evstr. Since the AHMethod()'s argument is being passed by reference (probably incorrectly), I can't be sure how it will show up in the argument array, but I think it will be an LPWSTR object that points at the actual string, so you will need to de-ref it again (send it #value). Having written the method, save it, debug through it, and continue execution when you are happy. Quite a reasonable implementation would be something like this: HomeSeerEventSink>>invokeId: dispid flags: callTypeFlags withArguments: argArray | selector | selector := IdMap at: dispid ifAbsent: [^HRESULTError signalWith: E_NOTIMPL]. ^self perform: selector withArguments: argArray Where IdMap is a class variable containing a lookup table initialized something like this: IdMap := (LookupTable new) at: 1 put: ahEvent:; yourself. You'll need of course to implement the #ahEvent: method as well to do whatever you want, and it will get invoked with the LPWSTR argument I mentioned that will reference the actual string parameter. If the parameter were 'in' only, then you would get a String directly. > > > > interface _Application : IDispatch { > > ... > > [id(0x6003000a)] > > HRESULT __stdcall RegisterEventCB( > > [in, out] long* evtype, > > [in, out] IDispatch** obj); > > ... > > }; By the way, always be suspicious of COM interfaces with in-out parameters, their presence always make me suspicious of the quality of the implementation. in-out parameters have their uses, but I suspect all the parameters in the IDL fragments you posted should be 'in' only. Regards Blair |
Hi Blair,
> > > interface _Application : IDispatch { > > > ... > > > [id(0x6003000a)] > > > HRESULT __stdcall RegisterEventCB( > > > [in, out] long* evtype, > > > [in, out] IDispatch** obj); > > > ... > > > }; > > > By the way, always be suspicious of COM interfaces with in-out parameters, > their presence always make me suspicious of the quality of the > implementation. in-out parameters have their uses, but I suspect all the > parameters in the IDL fragments you posted should be 'in' only. My hunch is that the author(s) copied an example that passes an IID by reference. I agree that there's no reason for the component to tell us which interface pointer to use when we're bypassing the connectable objects framework :) Have a good one, Bill -- Wilhelm K. Schwab, Ph.D. [hidden email] |
In reply to this post by Blair McGlashan
"Blair McGlashan" <[hidden email]> wrote in message news:<9nlc72$8dls7$[hidden email]>...
> Scott > > "Scott" <[hidden email]> wrote in message > news:[hidden email]... > > Any other suggestions? > > > > > I did get that MSAgent example to work just fine. Thanks. I followed > > > the same steps for the HomeSeer activeX with tracing enabled, but > > > nothing comes through. > > That is because it doesn't appear to use connection points, in which case > AXEventSink will not work. > > > > > > > The HomeSeer activeX server documentation states that the callback be > > > registered using a RegisterEventCB call (see idl below). > > Sigh. Yet another custom event mechanism when there is a perfectly good > "standard" one. > difficult. > >...I tried > > > passing sink (see step 2 below) as the argument in step 5, but I get > > > an Index 3 is out of bounds error (wrong argument type?). Any > > > suggestions or other advice as to what agrument I should pass would be > > > great or other ways to get notifications bach from HomeSeer. > > You'll need to create a custom implementation of IDispatch to pass to the > RegisterEventCB method. If you subclass it off AXDispatchImpAbstract you > need only implement the two 'subclass responsibility methods'. If you don't > now how to implement them then > > (a) look at AXEventSink (but it is a generic implementation that reads type > info. so this may confuse more than help) > (b) Do a bit of XP, i.e just create your AXDispatchImpAbstract subclass, > calling it, say, HomeSeerEventSink, and create empty implementations of the > two subclass responsibility methods that contain only 'self halt' > statements. Now run: > > hs := HS_Application createObject: 'HomeSeer.Application'. > sink := HomeSeerEventSink new. > hs registerEventCB: 3 obj: (sink queryInterface: IDispatch). > > Shortly you'll hit one of the breakpoints, probably in > #invokeId:flags:withArguments: (since this is an event interface you may > find that #idOfNames:whenNotKnown: never gets called). Go into the Debugger > and using all the "context" you now have (argument types and values) flesh > out the implementation. You'll should find that the first (id) argument > matches that in the IDL for the single method in __Application, i.e. 1. If > it is 1, then the control is sending you an AHEvent(), if not then it is > invoking some other method that is not declared in the IDL, which is > unlikely. You can ignore the flags argument in this case, and the final > array argument should contain a single element being the evstr. Since the > AHMethod()'s argument is being passed by reference (probably incorrectly), I > can't be sure how it will show up in the argument array, but I think it will > be an LPWSTR object that points at the actual string, so you will need to > de-ref it again (send it #value). Having written the method, save it, debug > through it, and continue execution when you are happy. After putting in the 2 methods with #halt, #idOfNames:whenNotKnown: is called with anOrderedCollection with a value of 'HSEvent'. I will try playing around more now that you got me started. Thanks for the help. > By the way, always be suspicious of COM interfaces with in-out parameters, > their presence always make me suspicious of the quality of the > implementation. in-out parameters have their uses, but I suspect all the > parameters in the IDL fragments you posted should be 'in' only. Thanks for the warning. Scott |
I got HomeSeer to invoke my message #ahEvent: using the following:
hs := HS_Application createObject: 'HomeSeer.Application'. hs when: #AHEvent: send: #ahEvent: to: hs. cb := HSEventSink target: hs sourceTypeInfo: HS__Application typeInfo. cb isTracingEnabled: true. hs registerEventCB: 3 obj: (cb queryInterface: IDispatch). where HSEventSink is a subclass of AXEventSink. #idsOfNames:anArray whenNotKnown: aBlock |ids | ids := #('HSEvent'). ^anArray collect: [:each | ids indexOf: each] and I had to comment out the 'lcid' (the value is 1033 and was returning E_INVALIDARG) checking in the following method: #Invoke: dispid riid: riid lcid: lcid wFlags: wFlags pdispparams: pDispParams pvarResult: pVarResult pexcepinfo: pExcepInfo puArgErr: puArgErr "(lcid == 0 or: [lcid = LOCALE_USER_DEFAULT or: [lcid = LOCALE_SYSTEM_DEFAULT]]) ifFalse: [^E_INVALIDARG]." Now my question has to do with the arguments to #ahEvent:. I am getting aLPVOID(an ExternalAddress(16rC67478)). It is my opinion that this should be a collection of objects as the following documentation of VB states: Public Sub HSEvent(parms As Variant) Debug.Print "HS_EVENT" Select Case parms(0) Case EV_TYPE_X10 Text1 = Text1 + "HS EVENT: " + Str(parms(0)) + " Dev:" + parms(1) + " HC: " + parms(2) + " CMD: " + Str(parms(3)) + vbCrLf Case EV_TYPE_LOG Text1 = Text1 + "HS EVENT: " + Str(parms(0)) + " Date/Time:" + parms(1) + " Type: " + parms(2) + " Msg: " + parms(3) + vbCrLf End Select End Sub Any suggestions as how to convert the arguments into something I can use or get lcid to be LOCALE_USER_DEFAULT or LOCALE_SYSTEM_DEFAULT. Thanks, Scott |
Any ideas?
Scott [hidden email] (Scott) wrote in message news:<[hidden email]>... > I got HomeSeer to invoke my message #ahEvent: using the following: > > hs := HS_Application createObject: 'HomeSeer.Application'. > hs when: #AHEvent: send: #ahEvent: to: hs. > cb := HSEventSink target: hs sourceTypeInfo: HS__Application typeInfo. > cb isTracingEnabled: true. > hs registerEventCB: 3 obj: (cb queryInterface: IDispatch). > > where HSEventSink is a subclass of AXEventSink. > #idsOfNames:anArray whenNotKnown: aBlock > |ids | > ids := #('HSEvent'). > ^anArray collect: [:each | ids indexOf: each] > and I had to comment out the 'lcid' (the value is 1033 and was > returning E_INVALIDARG) checking in the following method: > #Invoke: dispid riid: riid lcid: lcid wFlags: wFlags pdispparams: > pDispParams pvarResult: pVarResult pexcepinfo: pExcepInfo > puArgErr: puArgErr > "(lcid == 0 or: [lcid = LOCALE_USER_DEFAULT > or: [lcid = LOCALE_SYSTEM_DEFAULT]]) > ifFalse: [^E_INVALIDARG]." > > Now my question has to do with the arguments to #ahEvent:. I am > getting > aLPVOID(an ExternalAddress(16rC67478)). It is my opinion that > this should be a collection of objects as the following documentation > of VB states: > > Public Sub HSEvent(parms As Variant) > Debug.Print "HS_EVENT" > > Select Case parms(0) > Case EV_TYPE_X10 > Text1 = Text1 + "HS EVENT: " + Str(parms(0)) + " Dev:" + > parms(1) + " HC: " + parms(2) + " CMD: " + Str(parms(3)) + vbCrLf > Case EV_TYPE_LOG > Text1 = Text1 + "HS EVENT: " + Str(parms(0)) + " > Date/Time:" + parms(1) + " Type: " + parms(2) + " Msg: " + parms(3) + > vbCrLf > End Select > End Sub > > Any suggestions as how to convert the arguments into something I can > use or get lcid to be LOCALE_USER_DEFAULT or LOCALE_SYSTEM_DEFAULT. > > Thanks, > Scott |
Free forum by Nabble | Edit this page |