Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

jscript events (not in IE)

44 views
Skip to first unread message

Steve Alpert

unread,
Aug 27, 2004, 11:07:32 AM8/27/04
to
I've been asked to consider using JScript as a scripting engine and have
built a prototype along the lines of Q223139 "add support for hosting
VBScript to ATL..." but replaced the VBScript guid by one for JScript.
I have perused earlier postings without success.

However, I'd like to support events. From all I've seen, if Event2 is
an event, I need (in script)

MyObject.Event2 = EvtFcn;

function EvtFcn(arg) {
// process event here
}

However, this doesn't work. What must I do? I have a modest
implementation of IActiveScriptSite. Do I have to expose a metchod such
as the following. If so, what type of parameter is the EvtFcn here.

MyObject.AddEvent("Event2",EvtFcn);

tnx,
/steveA

--
Steve Alpert
my email Fgrir_Nycreg @ vqk.pbz is encrypted with ROT13 (www.rot13.org)
and spaces

Steven Cheng[MSFT]

unread,
Aug 28, 2004, 4:27:46 AM8/28/04
to
Hi Steve,

Thank you for the posting . Regarding on the issue, I am
finding proper resource to assist you and we will update as soon as posible.

Regards,

Steven Cheng
Microsoft Online Support

Get Secure! www.microsoft.com/security(This posting is provided "AS IS",
with no warranties, and confers no rights.)

Jason Cone

unread,
Aug 28, 2004, 8:59:36 AM8/28/04
to
"Steve Alpert" <s...@newsgroups.nospam> wrote in message
news:uS0WBfEj...@TK2MSFTNGP09.phx.gbl...

> I've been asked to consider using JScript as a scripting engine and have
> built a prototype along the lines of Q223139 "add support for hosting
> VBScript to ATL..." but replaced the VBScript guid by one for JScript.
> I have perused earlier postings without success.
>
> However, I'd like to support events. From all I've seen, if Event2 is
> an event, I need (in script)
>
> MyObject.Event2 = EvtFcn;
>
> function EvtFcn(arg) {
> // process event here
> }
>
> However, this doesn't work. What must I do? I have a modest
> implementation of IActiveScriptSite. Do I have to expose a metchod such
> as the following. If so, what type of parameter is the EvtFcn here.
>
> MyObject.AddEvent("Event2",EvtFcn);


Both of the aforementioned approaches are effectively the same.
Specifically, in either case, 'EvtFcn' is a pointer to an IDispatch
interface on which the default method (dispid 0) is invoked to execute the
event function.

With the 'MyObject.Event2' property approach, 'Event2' is also an
IDispatch*-based value and the regular interface reference rules apply.

With the 'MyObject.AddEvent' method approach, I'm assuming that you would
have some sort of internal BSTR -> IDispatch* mapping.

This is, of course, assuming that you're not talking about using connection
points (and containers) to handle your event notifications. If you are
wanting to use connection points, forget everything that I've said so far.
:-) Unfortunately, I don't have experience with advising/unadvising
connection point containers in the context of a scripting engine.

Regards,

Jason Cone

Steve Alpert

unread,
Aug 29, 2004, 10:53:43 AM8/29/04
to
However, if I run VBScript, my driver has to do nothing else to fire an
event a la
Sub MyObject_Event2(msg)
...
End Sub

However, neither of the approaches I tried for JavaScript resulted in
the call. Do I have to explicitly use a ParseScriptText (or similar)
and look for MyObject::Event2 or add a method like the AddEvent to hook
it in? In DHTML, the <For...> construct seems similar to the latter
process. I'd be interested in seeing some code that does this.

thanks,

[MSFT]

unread,
Aug 30, 2004, 3:47:44 AM8/30/04
to
Hi Steve,

I have taken a deep research on this issue. But I think the defination for
the JScript function should be like:

function MyObject::EvtFcn(arg) {
// process event here
}

Will this help?

Luke

Steve Alpert

unread,
Aug 30, 2004, 7:50:09 AM8/30/04
to
[MSFT] wrote:
> Hi Steve,
>
> I have taken a deep research on this issue. But I think the defination for
> the JScript function should be like:
>
> function MyObject::EvtFcn(arg) {
> // process event here
> }
Luke:
This didn't help. I put a break in the Fire_Event2() call:

HRESULT Fire_Event2( BSTR msg)
{
HRESULT hr = S_OK;
T * pThis = static_cast<T *>(this);
int cConnections = m_vec.GetSize();
...
and cConnections was zero!

I used a simple script (where I've implemented "alert"):

alert("got here...");
function MyObject::Event2(msg) {
alert("event2: " + msg);
}
alert("past definition");

The "got here..." and "past definition" work fine but the Fire_Event2()
doesn't work. Following the sample, I created:

CMyScriptSite *pMySite;
IActiveScript *pAS;
IActiveScriptParse *pASP;

as part of my dialog class so they would remain available past the call
to my "run" button. I have another button that calls Fire_Event2()
passing in the text from and edit box but have the problem described above.

If I switch back to VBScript and use

alert("got here...");
sub MyObject_Event2(msg) {
alert("event2: " + msg);
end sub
alert("past definition");

It works just fine! Is there something I'm missing in the JScript case?
btw - I'm on XP SP1..

Am I missing an interface for MyObject in the JScript case?

class ATL_NO_VTABLE CMyObject :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CMyObject, &CLSID_MyObject>,
public IConnectionPointContainerImpl<CMyObject>,
public CProxy_IMyObjectEvents<CMyObject>,
public IDispatchImpl<IMyObject, &IID_IMyObject,
&LIBID_ScriptAppLib, /*wMajor =*/ 1, /*wMinor =*/ 0>
...

Jason Cone

unread,
Aug 30, 2004, 8:38:44 AM8/30/04
to
"Steve Alpert" <s...@newsgroups.nospam> wrote in message
news:eHlh%23fdjE...@TK2MSFTNGP15.phx.gbl...

> However, if I run VBScript, my driver has to do nothing else to fire an
> event a la
> Sub MyObject_Event2(msg)
> ...
> End Sub
>
> However, neither of the approaches I tried for JavaScript resulted in
> the call. Do I have to explicitly use a ParseScriptText (or similar)
> and look for MyObject::Event2 or add a method like the AddEvent to hook
> it in? In DHTML, the <For...> construct seems similar to the latter
> process. I'd be interested in seeing some code that does this.


OK, so you are wanting to use connection points. Like I said, my experience
in sinking events on host objects from script is limited, but the "Hosting -
Objects & Events" section of Mark Baker's Active Scripting FAQ appears to
have several useful pointers. For more information, see
http://www.mindspring.com/~mark_baker/toc.htm.

Regards,

Jason Cone

Steve Alpert

unread,
Aug 30, 2004, 12:23:45 PM8/30/04
to

Jason:

Alas, been all through the FAQ with no luck..

[MSFT]

unread,
Aug 31, 2004, 2:53:00 AM8/31/04
to
Hi Steve,

I found a old thread seems to discuss for same issue. You may refer to it
to see if it will help:

http://groups.google.com/groups?hl=zh-CN&lr=&ie=UTF-8&threadm=01bc4332%24bc2
7c500%24c7014999%40gerry&rnum=6&prev=/groups%3Fq%3DIActiveScript%2Bevent%2Bj
script%26hl%3Dzh-CN%26lr%3D%26ie%3DUTF-8%26selm%3D01bc4332%2524bc27c500%2524
c7014999%2540gerry%26rnum%3D6

Also, here is a useful article:

http://www.microsoft.com/msj/1099/Visualprog/visualprog1099.aspx

Hope this help,

Luke

Steve Alpert

unread,
Aug 31, 2004, 7:33:52 AM8/31/04
to
[MSFT] wrote:
> Hi Steve,
>
> I found a old thread seems to discuss for same issue. You may refer to it
> to see if it will help:
>
> http://groups.google.com/groups?hl=zh-CN&lr=&ie=UTF-8&threadm=01bc4332%24bc2
> 7c500%24c7014999%40gerry&rnum=6&prev=/groups%3Fq%3DIActiveScript%2Bevent%2Bj
> script%26hl%3Dzh-CN%26lr%3D%26ie%3DUTF-8%26selm%3D01bc4332%2524bc27c500%2524
> c7014999%2540gerry%26rnum%3D6
>

The above article suggests something like:

MyObject.Event2 = test;

function test(msg) {
alert("event2: " + msg);
}

However, my test program reports an error on line 1 column 1 so it
doesn't appear to like this format.

I've tried MyObject::test and __JSHandler__MyObject_test but none of
them work for me. Doesn't someone know how this really works?

This article suggests essentially parsing the script to find defined
functions so you can manually call them via IDispatch. That is the
antithesis of what the prior reference suggests; namely, that you
shouldn't have to do all that work!

sigh,

Steve Alpert

unread,
Aug 31, 2004, 10:59:35 AM8/31/04
to
Luke:

I've observed the following:

when running VBScript, the GetItemInfo receives 3 calls
SCRIPTINFO_IUNKNOWN (from ParseScriptText)
SCRIPTINFO_IUNKNOWN (from SetScriptState to CONNECTED)
and
SCRIPTINFO_ITYPEINFO (from SetScriptState)
and I can fire events to MyObject_Event2

when running JScript, the GetItemInfo receives only one call
SCRIPTINFO_IUNKNOWN (from ParseScriptText)
and I cannot fire events. Why no calls from SetScriptState?

Now, in JScript
MyObject.Event2 = test; function test... results in a script error
function MyObject::Event2() runs but as above does not fire
function __JSHandler__MyObject_Event2() runs but as above does not
fire

Does my scriptsite object need more interfaces than


public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CMyObject, &CLSID_MyObject>,
public IConnectionPointContainerImpl<CMyObject>,
public CProxy_IMyObjectEvents<CMyObject>,
public IDispatchImpl<IMyObject, &IID_IMyObject,
&LIBID_ScriptAppLib, /*wMajor =*/ 1, /*wMinor =*/ 0>

I suspect the latter hint (__JSHandler__...) was for the case where you
would call the IDispatch pointer on the engine and enumerate all the
functions to look for where the user wanted events to be called via
GetTypeInfo. I really don't want to have to do all that work just
because the user might want to use JScript rather than VBScript!

[MSFT]

unread,
Sep 1, 2004, 3:16:44 AM9/1/04
to
Hi Steve,

When a Script engine start running the script, SCRIPTSTATE_CONNECTED flag
will be set by the IActiveScript::SetScriptState method. This call would
likely perform any scripting engine construction work, including static
binding, hooking up to events. Since it didn't fire for JScript. I suspect
it failed when hooking up the events.

Luke

Steve Alpert

unread,
Sep 1, 2004, 8:05:47 AM9/1/04
to
However, since the identical code (on my part) is used for both VBScript
and JScript tests (with the exception of the CLSID) and the
SetScriptState method is called in both cases, I have to assume the
problem is that the jscript.dll just doesn't support the event hooks
like the vbscript.dll does. That would explain why dhtml has the
<FOR...> construct to wire up JScript events. If you think this is not
true, I'd be glad to email to you my small test application.

[MSFT]

unread,
Sep 2, 2004, 2:33:43 AM9/2/04
to
Please remove "online" to get my actual email address. You may send me a
simple project to research.

Thanks.

Luke

Jim Christopher

unread,
Sep 2, 2004, 11:15:41 AM9/2/04
to

"Steve Alpert" <s...@newsgroups.nospam> wrote in message
news:eYuY0wBk...@TK2MSFTNGP15.phx.gbl...

> [MSFT] wrote:
> > Hi Steve,
> >
> > When a Script engine start running the script, SCRIPTSTATE_CONNECTED
flag
> > will be set by the IActiveScript::SetScriptState method. This call would
> > likely perform any scripting engine construction work, including static
> > binding, hooking up to events. Since it didn't fire for JScript. I
suspect
> > it failed when hooking up the events.
> >
> > Luke
> >
> However, since the identical code (on my part) is used for both VBScript
> and JScript tests (with the exception of the CLSID) and the
> SetScriptState method is called in both cases, I have to assume the
> problem is that the jscript.dll just doesn't support the event hooks
> like the vbscript.dll does. That would explain why dhtml has the
> <FOR...> construct to wire up JScript events. If you think this is not
> true, I'd be glad to email to you my small test application.
>
> /steveA

IE never actually pushes the JScript engine into the CONNECTED state. It
can avoid the overhead since JScript is able to assign event handlers via
function reference properties. Until recently VBScript could not assign
function or procedure references because the language did not support that
construct until the GetRef routine was added in Windows Script 5, so in
order for a VBScript developer to handle DOM events, the vbscript engine had
to be throttled to the CONNECTED state. IE 6, from what I can tell, still
treats the engines differently in this regard even though it is no longer
necessary.

Here is a checklist of common pitfalls related to automagic event handling.
It's from a chapter of a book that I could never get published on Agile
Application Development. I hope it helps.

1.. Your source object must support the IConnectionPointContainer
interface, since it is through this interface that the script engine will
advise the object of the event handlers. Make sure this is implemented
appropriately.
2.. Make sure the source object is an object added using
IActiveScript::AddNamedItem, and also ensure that the object is added with
the SCRIPTINFO_ISSOURCE constant specified. These are the only objects in
the scripting name space for which automagic events will work. If you're
using the IActiveScriptParse::AddScriptlet method to define your event
handlers, make sure the objects aren't added with the SCRIPTITEM_NOCODE flag
specified; the IActiveScriptParse::AddScriptlet requires that the object
have an associated named scripting context to house the event handling code.
3.. Make sure that your script site's implementation of
IActiveScriptSite::GetItemInfo is returning the appropriate interface
pointers at the appropriate times. If the dwReturnMask parameter has the
SCRIPTINFO_IUNKNOWN bit set, then you must return the IUnknown for the
object in the ppunkItem parameter; if the SCRIPTINFO_ITYPEINFO bit is set,
then you must return the ITypeInfo for the object's *class* in the
ppTypeInfo parameter.
4.. Check that your implementation of IActiveScriptSite::GetItemInfo is
returning the correct type information. The script engine needs the type
information for the object's class, not for the object's primary interface.
This is probably the most common mistake I've seen people make, so take the
time to double-check this if your events handlers aren't working properly.
5.. Confirm that the event handlers are defined correctly in your script
code. Check the spelling and, if the language is case-sensitive, the case
of the object and event names. Check the signature of the event handlers
against the object's type library; if the code for the source object is
available, step through the connection point code and see if an error is
returned when the event is fired. Try calling the event handler routine by
hand to ensure that it is recognized by the engine and functioning
correctly. If the source code for the source object is available, step
through the connection point code to see if the event handler invocation is
returning an error code.
6.. Verify that the engine enters the SCRIPTSTATE_CONNECTED state ( I
generally add tracing code or a breakpoint in the
IActiveScriptSite::OnStateChange implementation ). The engine must enter
this state in order for automagic event handlers to be hooked up to their
source objects. This is another of the more commonly missed steps in the
process.
obliged,
jim christopher


Steve Alpert

unread,
Sep 3, 2004, 7:36:56 AM9/3/04
to

...[stuff deleted]...

jim:

You are a bit late to the party. I am trying to use the script engine
OUTSIDE of IE. I still have not heard any convincing evidence of how a
user (of just JScript) can syntactically define an event function (based
on events of my object) that work. I believe all of what you have
suggested in your hints is already in my test program.

Jason Cone

unread,
Sep 3, 2004, 8:49:41 AM9/3/04
to
"Steve Alpert" <s...@newsgroups.nospam> wrote in message
news:ekRcBqak...@TK2MSFTNGP14.phx.gbl...
>
> [...]

>
> I am trying to use the script engine OUTSIDE of IE. I still have not
> heard any convincing evidence of how a user (of just JScript) can
> syntactically define an event function (based on events of my object)
> that work.


Steve,

Have you come across the following conversations?


http://groups.google.com/groups?hl=en&threadm=OfIblN2i%23GA.260%40cppssbbsa03

http://groups.google.com/groups?hl=en&threadm=er7oOvSh%23GA.262%40cppssbbsa03

http://groups.google.com/groups?hl=en&threadm=78a86h%24o1k%241%40remarQ.com


They all speak of the enigmatic IBindEventHandler interface to some extent.
I'm curious if you've played around with said interface and, if so, what the
outcomes of your experiments were.

Regards,

Jason Cone

Steve Alpert

unread,
Sep 3, 2004, 12:47:46 PM9/3/04
to
Jason Cone wrote:

Thanks for the tip - I'll try to muck with it this afternoon.

Jim Christopher

unread,
Sep 3, 2004, 1:42:30 PM9/3/04
to

"Steve Alpert" <s...@newsgroups.nospam> wrote in message
news:ekRcBqak...@TK2MSFTNGP14.phx.gbl...

> Jim Christopher wrote:
> > IE never actually pushes the JScript engine into the CONNECTED state.
It
> > can avoid the overhead since JScript is able to assign event handlers
via
> > function reference properties. Until recently VBScript could not assign
> > function or procedure references because the language did not support
that
> > construct until the GetRef routine was added in Windows Script 5, so in
> > order for a VBScript developer to handle DOM events, the vbscript engine
had
> > to be throttled to the CONNECTED state. IE 6, from what I can tell,
still
> > treats the engines differently in this regard even though it is no
longer
> > necessary.
>
> ...[stuff deleted]...
>
> jim:
>
> You are a bit late to the party. I am trying to use the script engine
> OUTSIDE of IE. I still have not heard any convincing evidence of how a
> user (of just JScript) can syntactically define an event function (based
> on events of my object) that work. I believe all of what you have
> suggested in your hints is already in my test program.

I understand what you are trying to do. I am merely pointing out that you
cannot use the fact that automagic events do not work for JScript within IE
to assume that they do not work at all for that engine.

The syntax for the automagic event handlers in jscript is:
function ObjectName::EventName( ...)

If you follow that syntax and the checklist I posted before, the event
handlers will work.

jim


Steve Alpert

unread,
Sep 3, 2004, 3:45:32 PM9/3/04
to
Jim:
1. My object (ATL project) implements IConnectionPointContainer
2. AddNamedItem is called passing the object (MyObject) with
SCRIPTITEM_ISVISIBLE | SCRIPTITEM_ISSOURCE
3/4. GetItemInfo:
virtual HRESULT __stdcall GetItemInfo(LPCOLESTR pstrName,
DWORD dwReturnMask, IUnknown **ppunkItem, ITypeInfo **ppti) {
// Is it expecting an ITypeInfo?
if(ppti) {
// Default to NULL.
*ppti = NULL;

// See if asking about ITypeInfo...
// doesn't appear to be called in jscript case
if(dwReturnMask & SCRIPTINFO_ITYPEINFO) {
*ppti = m_pTypeInfo;
// shouldn't we do an AddRef here? add it!
m_pTypeInfo->AddRef();
}
}

// Is the engine passing an IUnknown buffer?
if(ppunkItem) {
// Default to NULL.
*ppunkItem = NULL;

// Is Script Engine looking for an IUnknown for our object?
if(dwReturnMask & SCRIPTINFO_IUNKNOWN) {
// Check for our object name...
if (!_wcsicmp(L"MyObject", pstrName)) {
// Provide our object.
*ppunkItem = m_pUnkScriptObject;
// Addref our object...
m_pUnkScriptObject->AddRef();
}
}
}

return S_OK;
}

5. Event handlers defined: (alert is just msgbox)
alert("start");

function MyObject::Event2(msg) {
alert( "event2: " + msg);
}

alert("end");

6. via debugging, SCRIPTSTATE_CONNECTED state is reached.

However, no call to GetItemInfo with ITYPEINFO bit is made (it IS in
VBScript) and when I try Fire_Event2, the cConnections is zero.

Can you see the error? (I can send code - it's a small ATL VC7 project)

[MSFT]

unread,
Sep 8, 2004, 5:01:09 AM9/8/04
to
Hi Steve,

How is it going now? If the problem still existed, I may involve more
resource to assist you on this issue. If you need further assistance,
please feel free to let me know.

Luke

Steve Alpert

unread,
Sep 8, 2004, 7:48:17 AM9/8/04
to
I have not made much progress on handling event sinking from JScript. I
note that if I do

JScript:

function MyObject.Event2(msg) {...}

and have defined a PROPERTY Event2(IDispatch *), the property's put
method is called. However, I haven't tried a GetIDsofNames or other
mechanism to figure out how to call the JScript code. That's where I'm
stuck at the moment. It just seems I have to add a lot of extra
overhead to support JScript (vs VBScript).

Did you get a chance to look at the code I sent you?

Jim Christopher

unread,
Sep 8, 2004, 11:23:04 AM9/8/04
to
Steve;

"Steve Alpert" <s...@newsgroups.nospam> wrote in message

news:OOjornZl...@TK2MSFTNGP11.phx.gbl...

> I have not made much progress on handling event sinking from JScript. I
> note that if I do
>
> JScript:
>
> function MyObject.Event2(msg) {...}
>
> and have defined a PROPERTY Event2(IDispatch *), the property's put
> method is called. However, I haven't tried a GetIDsofNames or other
> mechanism to figure out how to call the JScript code. That's where I'm
> stuck at the moment. It just seems I have to add a lot of extra
> overhead to support JScript (vs VBScript).

You just need to call IDispatch::Invoke on the IDispatch* passed to your
property put method, passing 0 for the dispidMember parameter.

You may also wish to specify the source object as the "this" reference for
the event handler. This is done by passing the IDispatch* of the source
object as the first entry in the pDispParams array, with a
DISPPARAMS::rgdispidNamedArgs value of DISPID_THIS.

Automagic event handling will work if your source objects implement
IProvideClassInfo or a derivative interface ( or IBindEventHandler ).

jim


0 new messages