ActiveX question

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

ActiveX question

Scott
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


Reply | Threaded
Open this post in threaded view
|

Re: ActiveX question

Blair McGlashan
"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


Reply | Threaded
Open this post in threaded view
|

Re: ActiveX question

Scott
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


Reply | Threaded
Open this post in threaded view
|

Re: ActiveX question

Scott
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
>


Reply | Threaded
Open this post in threaded view
|

Re: ActiveX question

Blair McGlashan
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


Reply | Threaded
Open this post in threaded view
|

Re: ActiveX question

Bill Schwab
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]


Reply | Threaded
Open this post in threaded view
|

Re: ActiveX question

Scott
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.
>
Just my luck, the first ActiveX project I want to do and it has to be
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


Reply | Threaded
Open this post in threaded view
|

Re: ActiveX question

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


Reply | Threaded
Open this post in threaded view
|

Re: ActiveX question

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