我用atl写了一个简单的ActiveX控件,这个控件里就一个简单的ATL对象,同时实现了连接点接口。打包成cab文件后,在网页中用javascript取访问这个控件,可以调用这个控件的普通接口函数,但是始终无法实现javascript和这个空间的连接点接口(也就是事件绑定),请高手一定帮帮忙,谢谢!
下面是我这个activex的idl文件
import "oaidl.idl";
import "ocidl.idl";
[
object,
uuid(913D8579-1156-4A5A-84CC-A647225CF54C),
dual,
helpstring("IDemo Interface"),
pointer_default(unique)
]
interface IDemo : IDispatch
{
[id(1), helpstring("method Test")] HRESULT Test([in]BSTR bMsg, [out, retval]BSTR* bVal);
};
[
uuid(1BC8A5CA-44B1-40FD-B3AF-614665C73052),
version(1.0),
helpstring("Proxy 1.0 Type Library")
]
library PROXYLib
{
importlib("stdole32.tlb");
importlib("stdole2.tlb");
[
uuid(0128A377-CE08-4BF9-AB7B-B51281E41952),
helpstring("_IDemoEvents Interface")
]
dispinterface _IDemoEvents
{
properties:
methods:
[id(1), helpstring("method CardIn")] HRESULT CardIn();
[id(2), helpstring("method CardOut")] HRESULT CardOut();
};
[
uuid(ACF3262F-7EDB-40F8-BC51-2291884F809B),
helpstring("Demo Class")
]
coclass Demo
{
[default] interface IDemo;
[default, source] dispinterface _IDemoEvents;
};
};
下面是Test函数的实现:
STDMETHODIMP CDemo::Test(BSTR bMsg, BSTR *bVal)
{
// TODO: Add your implementation code here
char* msg = CUtil::BSTRToChar(bMsg);
*bVal = CUtil::CharToBSTR(msg);
if(0 == strcmp(msg, "in"))
{
Fire_CardIn();
}
else if(0 == strcmp(msg, "out"))
{
Fire_CardOut();
}
delete [] msg;
msg = NULL;
return S_OK;
}
以下是测试用的网页
<object id="Demo" classid="clsid:ACF3262F-7EDB-40F8-BC51-2291884F809B"
codebase="http://192.168.3.240/test/proxy.cab">
</object>
<script type="text/javascript">
function Call()
{
var cmd = document.getElementById("cmd").value;
var result = Demo.test(cmd);
alert(result);
}
</script>
<script language="javascript" FOR="Demo" EVENT="CardIn">
alert("The card is in!");
</script>
<script language="javascript" FOR="Demo" EVENT="CardOut">
alert("The card is out!");
</script>
<html>
<title>
Test ActiveX Server Component
</title>
<body>
<input id="cmd" width="20">
<input value="CallActiveX" type="button" onclick="Call()">
</body>
</html>
------解决方案--------------------
1、这个问题不该发到java论坛,估计这里面做过com程序的人不多。应该发到win32/com相关的论坛。
2、我觉得javascript与com控件交互时,不是用连接点模型来做事件处理的,连接点是com与com之间进行事件处理时用的。楼主可以用别的方式来处理,具体如下:
在IDemo接口中声明两个属性(property),分别是onCardIn和onCardOut,属性值的类型都是IDispatch指针。用atl的话,会自动生成对应的get/set方法(你手工自己加也一样)。这样,在你Fire_cardIn的时候判断onCardIn属性的值,如果不为NULL,也就是赋过值,就调用IDispatch.invoke()。
这样在你的页面里,可以直接用Demo.onCardIn = function() { alert("The card is in!"; }给属性赋值。你再调用test()的时候,如果触发了cardIn事件,就会调用到你的js函数。
3、以上方法可以解决楼主的需要。但是还是不能用<script language="javascript" FOR="Demo" EVENT="CardIn">这种事件声明的形式,怎么写com控件来兼容这种形式我也挺想知道的。如果有哪位高人知道方法,希望不吝赐教 :)
------解决方案--------------------
方法就是lz说的方法.