关于ActiveX控件的开发,网上很多例子,昨天也整整研究一天才捋顺了.

网上大部分例子都是js调用控件的方法,由于要实现在html页面"相应"控件的事件,整整折腾一天.

关键点在于 "创建ActiveX控件" 的 第2,和第7

该技术局限性较大,如浏览器端需安装 .net 框架,仅限于IE浏览器.

关于ActiveX的证书及浏览器安装时设置,可参考 http://www.cnblogs.com/weixing/archive/2013/06/28/3161165.html 这也是我看到比较详细的介绍了.

创建ActiveX控件
1.创建一个类库;
2.项目属性-应用程序-程序集信息-"使程序集COM可见"勾上;
3.项目属性-生成-"为COM互操作注册"勾上.(这个折腾一天,否则注册事件不可用);
4.创建接口: IObjectSafety (注意GUID不能变);
5.创建ActiveX控件的基类并实现IObjectSafety,ActiveX控件可以继承它来减少代码;
6.创建一个ActiveX自定义控件如:ActiveXDemo1;
7.定义ActiveXDemo1的"方法接口"及"事件接口".(如使用自定义事件需用此方式), "事件接口"成员应加上[DispId(x)]标识;
8.创建ActiveX控件完成.

IObjectSafety  接口定义

    [ComImport, Guid("4A359FBB-C9A4-494E-B048-AC068DB4FCB2")] //该GUID不能变
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IObjectSafety
{
[PreserveSig]
int GetInterfaceSafetyOptions(ref Guid riid, [MarshalAs(UnmanagedType.U4)] ref int pdwSupportedOptions, [MarshalAs(UnmanagedType.U4)] ref int pdwEnabledOptions); [PreserveSig()]
int SetInterfaceSafetyOptions(ref Guid riid, [MarshalAs(UnmanagedType.U4)] int dwOptionSetMask, [MarshalAs(UnmanagedType.U4)] int dwEnabledOptions);
}
}

ActiveX控件基类(ActiveXControlBase)

    public class ActiveXControlBase : IObjectSafety
{
#region IObjectSafety 成员 private const string _IID_IDispatch = "{00020400-0000-0000-C000-000000000046}";
private const string _IID_IDispatchEx = "{a6ef9860-c720-11d0-9337-00a0c90dcaa9}";
private const string _IID_IPersistStorage = "{0000010A-0000-0000-C000-000000000046}";
private const string _IID_IPersistStream = "{00000109-0000-0000-C000-000000000046}";
private const string _IID_IPersistPropertyBag = "{37D84F60-42CB-11CE-8135-00AA004BB851}"; private const int INTERFACESAFE_FOR_UNTRUSTED_CALLER = 0x00000001;
private const int INTERFACESAFE_FOR_UNTRUSTED_DATA = 0x00000002;
private const int S_OK = 0;
private const int E_FAIL = unchecked((int)0x80004005);
private const int E_NOINTERFACE = unchecked((int)0x80004002); private bool _fSafeForScripting = true;
private bool _fSafeForInitializing = true; public int GetInterfaceSafetyOptions(ref Guid riid, ref int pdwSupportedOptions, ref int pdwEnabledOptions)
{
int Rslt = E_FAIL; string strGUID = riid.ToString("B");
pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;
switch (strGUID)
{
case _IID_IDispatch:
case _IID_IDispatchEx:
Rslt = S_OK;
pdwEnabledOptions = 0;
if (_fSafeForScripting == true)
pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;
break;
case _IID_IPersistStorage:
case _IID_IPersistStream:
case _IID_IPersistPropertyBag:
Rslt = S_OK;
pdwEnabledOptions = 0;
if (_fSafeForInitializing == true)
pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA;
break;
default:
Rslt = E_NOINTERFACE;
break;
} return Rslt;
} public int SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions)
{
int Rslt = E_FAIL; string strGUID = riid.ToString("B");
switch (strGUID)
{
case _IID_IDispatch:
case _IID_IDispatchEx:
if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_CALLER) &&
(_fSafeForScripting == true))
Rslt = S_OK;
break;
case _IID_IPersistStorage:
case _IID_IPersistStream:
case _IID_IPersistPropertyBag:
if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_DATA) &&
(_fSafeForInitializing == true))
Rslt = S_OK;
break;
default:
Rslt = E_NOINTERFACE;
break;
} return Rslt;
} #endregion
}

  自定义ActiveX控件

    [ComVisible(true)]
[Guid("684AAD87-C086-4F27-AE55-941A1AAC7212")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IThreadDemoEvent
{
[DispId(1)] //使用事件,必须加上该标识
void ShowMessage1(string str_Msg);
[DispId(2)]
void ShowMessage2(string str_Msg);
} [ComVisible(true)]
[Guid("4D12136B-9545-423B-A110-B9405ADF8B30")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IThreadDemo
{
string StartTimer();
string StopTimer();
} [Guid("2B4FCB85-A3B7-43BD-B104-7380E7F3483F"),
ClassInterface(ClassInterfaceType.AutoDual),
ComDefaultInterface(typeof(IThreadDemo)),
ComSourceInterfaces(typeof(IThreadDemoEvent)),
ComVisible(true)
]
public class ActivexThreadDemo : ActiveXControlBase, IThreadDemo
{
~ActivexThreadDemo()
{
ShowMessage1("释放了啊");
} Thread _th;
bool _isStop; public event ShowMessageHandle ShowMessage1;
public event ShowMessageHandle ShowMessage2; void ThreadMethd()
{
while (true)
{
Thread.Sleep(3000);
if (ShowMessage1 != null)
{
ShowMessage1.Invoke(DateTime.Now.ToString());
}
if (_isStop) break;
}
_th.Abort();
_th = null;
} public string StartTimer()
{
if (_th == null)
{
_isStop = false;
_th = new Thread(ThreadMethd);
_th.IsBackground = false;
_th.Start();
return "开起计时";
}
if (ShowMessage2 != null)
{
ShowMessage2("执行了 StartTimer");
}
return "已经开起过计时;";
} public string StopTimer()
{
if (_isStop)
{
return "已经停止计时了!";
}
else
{
_isStop = true;
return "停止计时";
}
}
}

  

注意:
不能使用泛型委托来声明事件,如:public event Action<T> ShowMessageHandle;
当类里面包含 static成员,刷新页面不会清空
跨线程触发事件: [事件].Invoke(参数1,参数2 ...);

ActiveX控件Setup
1.创建Installer项目;
2.右击项目 添加->项目输出 打开添加项目输出组对话框,并选择ActiveX控件类库;
3.主输出文件的属性 Register 值为 vsdrpCOM (关键),RemovePreviousVersions 设置为true

web页面测试;
1.创建一个object 标签,calassid为控件GUID
<object id="ActiveXObj1" classid="clsid:3BCF612C-91CF-4543-83BB-FD2331FDDCB6" ></object>
2.调用控件方法
var r = document.ActiveXObj1.Test1();
3."注册控件的事件"
<script language="javascript" type="text/javascript" for="ActiveXObj1" event="ShowMessage1(msg)">
alert("ActiveXObj1 :"+ msg )
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>ActiveX测试页面</title> <script type="text/javascript"> function test1() {
var r = document.ActiveXObj1.Test1();
window.status = r;
} function StartTimer() {
alert(document.ActiveThreadEvent);
var r = document.ActiveThreadEvent.StartTimer();
window.status = r;
}
function StopTimer() {
var r = document.ActiveThreadEvent.StopTimer();
window.status = r;
}
</script>
<!--事件的注册-->
<script language="javascript" type="text/javascript" for="ActiveXObj1" event="ShowMessage1(msg)">
alert("ActiveXObj1 :"+ msg )
</script>
<script language="javascript" type="text/javascript" for="ActiveXObj1" event="ShowMessage2(msg)">
alert("ActiveXObj1:" + msg)
</script> <!--线程事件注册-->
<script language="javascript" type="text/javascript" for="ActiveThreadEvent" event="ShowMessage1(msg)">
alert("ActiveThreadEvent :"+ msg )
</script>
<script language="javascript" type="text/javascript" for="ActiveThreadEvent" event="ShowMessage2(msg)">
alert("ActiveThreadEvent:" + msg)
</script>
</head>
<body>
<object id="ActiveXObj1" classid="clsid:3BCF612C-91CF-4543-83BB-FD2331FDDCB6" ></object>
<br />
<object id="ActiveThreadEvent" classid="clsid:2B4FCB85-A3B7-43BD-B104-7380E7F3483F" ></object>
<br />
<br />
<input type="button" value="测试4-相应事件!" onclick="test1();" /><br />
<input type="button" value="开始计时!" onclick="StartTimer();" /><br />
<input type="button" value="停止计时!" onclick="StopTimer();" /><br /> </body>
</html>

源码共享:  戳我

c# ActiveX 控件的开发的更多相关文章

  1. [转]C#开发ActiveX控件,.NET开发OCX控件案例

    引自:百度   http://hi.baidu.com/yanzuoguang/blog/item/fe11974edf52873aaec3ab42.html 讲下什么是ActiveX控件,到底有什么 ...

  2. C#开发ActiveX控件,.NET开发OCX控件案例 【转】

    http://xiaochen.2003.4.blog.163.com/blog/static/480409672012530227678/ 讲下什么是ActiveX控件,到底有什么作用?在网页中又如 ...

  3. 用C#编写ActiveX控件,开发浏览器控件,注册ActiveX 控件

    用C#编写ActiveX控件,开发浏览器控件,注册ActiveX 控件用C#编写ActiveX控件 开发浏览器控件这是本控件开发完成后的一个简单应用.我们可以利用它以本地文件夹为单位来批量更新服务器的 ...

  4. C#ActiveX控件开发学习

    一:C#ActiveX控件开发注意事项   1:C#开发的ActiveX控件只可在装有Framework的系统上才能用. 2:只有IE浏览器支持. 3:初次安装需要导入代码签名证书及其证书链的方式, ...

  5. 使用C#开发ActiveX控件(新)

    前言 ActiveX控件以前也叫做OLE控件,它是微软IE支持的一种软件组件或对象,可以将其插入到Web页面中,实现在浏览器端执行动态程序功能,以增强浏览器端的动态处理能力.通常ActiveX控件都是 ...

  6. 使用C#开发ActiveX控件(新) 转 http://www.cnblogs.com/yilin/p/csharp-activex.html

    前言 ActiveX控件以前也叫做OLE控件,它是微软IE支持的一种软件组件或对象,可以将其插入到Web页面中,实现在浏览器端执行动态程序功能,以增强浏览器端的动态处理能力.通常ActiveX控件都是 ...

  7. C#开发ActiveX控件

    昨天写了篇博客<Winform 程序嵌入WPF程序 并发送消息>,没有说明为什么要嵌入WPF程序,那么今天就来唠叨唠叨其中的一个使用场景,开发ActiveX控件 首先,新建一个类库工程Hu ...

  8. 使用C#开发ActiveX控件

    使用C#开发ActiveX控件(新) 前言 ActiveX控件以前也叫做OLE控件,它是微软IE支持的一种软件组件或对象,可以将其插入到Web页面中,实现在浏览器端执行动态程序功能,以增强浏览器端的动 ...

  9. [转]使用C#开发ActiveX控件全攻略

    前言: 这段时间因为工作的需要,研究了一下ActiveX控件.总结如下: 先说说ActiveX的基本概念. 根据微软权威的软件开发指南MSDN(Microsoft Developer Network) ...

随机推荐

  1. Oracle查看和修改其最大的游标数

    原文 Oracle查看和修改其最大的游标数 以下的文章主要是介绍Oracle查看和修改其最大的游标数,本文主要是通过相关代码的方式来引出Oracle查看和修改其最大的游标数的实际操作步骤,以下就是文章 ...

  2. Php 笔记4-----php 细节知识

    从 php5开始  php.ini  register_globals参数为OFF  ,禁止全局变量. 以前的情况下,  全局变量是默认为On的 , 所以,浏览器的表单中控件,会自动根据name在服务 ...

  3. Why automate?为什么要自动化?

    The need for speed is practically the mantra of the information age. Because technology is now being ...

  4. 五种情况会导致Session 丢失

    1.Session到期自定丢失.2.当修改web.config 系统会重启  SESSION 会丢失.3.Bin目录有变化时候系统会重启 SESSION会丢失 (这里变化指的是,创建新文件.修改文件名 ...

  5. qqq

    http://blog.sina.com.cn/s/blog_6f0774010100wawd.html http://www.2cto.com/kf/201302/189135.html http: ...

  6. Numpy中的矩阵计算

    矩阵初始化 支持matlab语句初始化,支持narray和array初始化. >>> import numpy as np >>> M = np.matrix(&q ...

  7. Sql group by 分组取时间最新的一条数据

    with MiPriceTopOne as (select classid,max(dataTime) dataTime,max(id) as id from MiPrice group by cla ...

  8. dom 动态生产表格

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...

  9. SQL Server UDF用户自定义函数

    UDF的定义 和存储过程很相似,用户自定义函数也是一组有序的T-SQL语句,UDF被预先优化和编译并且尅作为一个单元爱进行调用.UDF和存储过程的主要区别在于返回结果的方式. 使用UDF时可传入参数, ...

  10. 使用 XMPP 构建一个基于 web 的通知工具——转

    Inserting of file(使用 XMPP 构建一个基于 web 的通知工具.docx) failed. Please try again. http://www.ibm.com/develo ...