使用C#构建带事件的签名ActiveX组件具体办法:
第一步 创建ActiveX项目 使用NET语言编写的ActiveX控件的主体就是一个类库首先我们来创建这个类库项目打开Visual Studio File>New>Project选择Class Library创建一个类库项目
创建ActiveX项目
第二步 编写ActiveX主体 ActiveX的主体包括方法定义接口事件定义接口(可选)实现这些接口的ActiveX主体类三个部分下面是笔者原创的Demo
首先我们创建方法定义接口:
///<summary>
/// 该接口定义了ActiveX的方法
///</summary>
[
Guid(FBDFEBFBDFDDDF)
InterfaceType(ComInterfaceTypeInterfaceIsDual)
ComVisible(true)]
publicinterfaceIBosnMaActiveX
{
[DispId()]
void Start();
[DispId()]
void Stop();
}
该接口内的成员会暴露给外部调用这里我们提供两个简单方法Start和Stop使用工具(Visual Studio > Tools > Create GUID)生成自己的GUID
接下来定义事件接口:
///<summary>
/// 该接口定义了ActiveX的事件
///</summary>
[ComVisible(true)]
[Guid(CFFFBeDBAC)]
[InterfaceType(ComInterfaceTypeInterfaceIsIDispatch)]
publicinterfaceBosnMaActiveXEvents
{
[DispId()]
void OnRecorderStarted();
[DispId()]
void OnRecorderStopped();
[DispId()]
void OnRecorderVolumeChanged(int value);
}
这里我们为ActiveX定义三个事件分别为OnRecorderStartedOnRecorderStopped OnRecorderVolumeChanged(带一个int参数)
最后我们编写集成方法接口和事件接口的ActiveX主体类:
[
Guid(ECEECbBCFFCA)
ProgId(ActiveXOfBosnMaBosnMaActiveX)
ClassInterface(ClassInterfaceTypeNone)
ComDefaultInterface(typeof(IBosnMaActiveX))
ComSourceInterfaces(typeof(BosnMaActiveXEvents))
ComVisible(true)
]
publicclassBosnAcX : IBosnMaActiveX IObjectSafety
{
#region Events Handlers Instances
publicdelegatevoidVolumeChangedHandler(int value);
publicdelegatevoidSimpleHandler();
publiceventVolumeChangedHandler OnRecorderVolumeChanged;
publiceventSimpleHandler OnRecorderStarted;
publiceventSimpleHandler OnRecorderStopped;
#endregion
#region Implementation of IBosnMaActiveX
///<summary>
/// 调用该方法将引发OnRecorderStarted事件并在秒后引发OnRecorderVolumeChanged
///</summary>
publicvoid Start()
{
OnRecorderStarted();
SimpleHandler d = Work;
dBeginInvoke(null null);
}
publicvoid Work()
{
ThreadSleep();
OnRecorderVolumeChanged();
}
///<summary>
/// 调用该方法将引发OnRecorderStopped事件
///</summary>
publicvoid Stop()
{
OnRecorderStopped();
}
#endregion
}
这里要注意主体类的事件名称要与事件接口(在上例中为BosnMaActiveXEvents)中的方法名相同在BosnAcX中我们实现了IBosnMaActiveX中的方法当调用Start()时引发一个OnRecorderStarted事件并在秒后引发一个OnRecorderVolumeChanged事件在调用Stop()时引发一个OnRecorderStopped事件
编译并注册ActiveX
编译整个项目将输出dll
图 编译ActiveX项目生成dll文件
然后我们启动命令行CMD(如果是Vista/Win使用管理员方式打开)使用以下命令注册控件
C:\>D: //转到dll所在目录笔者为了方便将dll copy到了D盘根目录
D:\>regasm activexofbosnmadll /codebase /tlb
*regasm命令在%systemroot%\MicrosoftNET\Framework\vxxxxx\目录下将该目录注册到用户环境变量中即可不使用完全限定名运行该命令
*使用regasm activexofbosnmadll /codebase /tlb /unregister可以反注册在ActiveX代码变更时重编译后需要先反注册再注册
图 注册和反注册ActiveX控件
测试ActiveX
最后我们创建一个html页面来测试该ActiveX
<html>
<headrunat=server>
<title></title>
<objectid=myAcXname=myAcXclassid=clsid:ECEECbBCFFCA>
</object>
<scriptlanguage=javascriptfor=myAcXtype=text/javascriptevent=OnRecorderVolumeChanged(v);>
MyDivinnerHTML = In javascript: Get Volume:+v;
</script>
<scriptlanguage=javascriptfor=myAcXtype=text/javascriptevent=OnRecorderStarted>
MyDivinnerHTML = In javascript: OnRecorderStarted;
</script>
<scriptlanguage=javascriptfor=myAcXtype=text/javascriptevent=OnRecorderStopped>
MyDivinnerHTML = In javascript: OnRecorderStopped;
</script>
</head>
<body>
<form>
<scriptlanguage=javascripttype=text/jscript>
function Button_onclick() {
myAcXStart();
}
function Button_onclick() {
myAcXStop();
}
function RecorderVolumeChanged(v) {
alert(volume: + v);
}
</script>
<divid=MyDiv>Nothing happened</div>
<p>
<inputid=Buttontype=buttonvalue=Startonclick=Button_onclick()/>
<inputid=Buttontype=buttonvalue=Stoponclick=Button_onclick()/></p>
</form>
</body>
</html>
测试效果 首先使用IE打开测试页面
允许ActiveX交互后进入主界面点击Start按钮会收到ActiveX返回的OnRecorderStarted事件
三秒过后收到Volume事件
最后点击Stop按钮会收到OnRecorderStopped事件
安全性
为了标记ActiveX控件为安全的(避免弹出该控件是不安全的警告)需要实现IObjectSafety接口
using System;
using SystemCollectionsGeneric;
using SystemRuntimeInteropServices;
using SystemComponentModel;
using SystemText;
namespace ActiveXOfBosnMa
{
[
Serializable
ComVisible(true)
]
publicenumObjectSafetyOptions
{
INTERFACESAFE_FOR_UNTRUSTED_CALLER = x
INTERFACESAFE_FOR_UNTRUSTED_DATA = x
INTERFACE_USES_DISPEX = x
INTERFACE_USES_SECURITY_MANAGER = x
};
//
// MS IObjectSafety Interface definition
//
[
ComImport()
Guid(CBBDCCCFFFCD)
InterfaceType(ComInterfaceTypeInterfaceIsIUnknown)
]
publicinterfaceIObjectSafety
{
[PreserveSig]
long GetInterfaceSafetyOptions(refGuid iid outint pdwSupportedOptions outint pdwEnabledOptions);
[PreserveSig]
long SetInterfaceSafetyOptions(refGuid iid int dwOptionSetMask int dwEnabledOptions);
};
//
// Provides a default Implementation for
// safe scripting
// This basically means IE wont complain about the
// ActiveX object not being safe
//
publicclassIObjectSafetyImpl : IObjectSafety
{
privateObjectSafetyOptions m_options =
ObjectSafetyOptionsINTERFACESAFE_FOR_UNTRUSTED_CALLER |
ObjectSafetyOptionsINTERFACESAFE_FOR_UNTRUSTED_DATA;
#region [IObjectSafety implementation]
publiclong GetInterfaceSafetyOptions(refGuid iid outint pdwSupportedOptions outint pdwEnabledOptions)
{
pdwSupportedOptions = (int)m_options;
pdwEnabledOptions = (int)m_options;
return ;
}
publiclong SetInterfaceSafetyOptions(refGuid iid int dwOptionSetMask int dwEnabledOptions)
{
return ;
}
#endregion
};
}
并实现以下两个方法:
#region Implementation of IObjectSafety
privateObjectSafetyOptions m_options =
ObjectSafetyOptionsINTERFACESAFE_FOR_UNTRUSTED_CALLER |
ObjectSafetyOptionsINTERFACESAFE_FOR_UNTRUSTED_DATA;
publiclong GetInterfaceSafetyOptions(refGuid iid outint pdwSupportedOptions outint pdwEnabledOptions)
{
pdwSupportedOptions = (int)m_options;
pdwEnabledOptions = (int)m_options;
return ;
}
publiclong SetInterfaceSafetyOptions(refGuid iid int dwOptionSetMask int dwEnabledOptions)
{
return ;
}
#endregion