关于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. js的预解析和代码执行相关规则

    JavaScript解析过程分为两个阶段,一个是编译阶段,另外一个就是执行阶段. 1.编译阶段:又称为预解析阶段,在这个阶段JavaScript解释器将完成把JavaScript脚本代码转换到字节码. ...

  2. hdu 4927 java求组合数(大数)

    import java.util.Scanner; import java.math.BigInteger; public class Main { private static int [] a = ...

  3. 【转】linux下cpio命令使用

    转自:http://www.51testing.com/html/32/498132-816949.html 功能说明:备份文件. 补充说明:cpio是用来建立,还原备份档的工具程序,它可以加入,解开 ...

  4. 【转】linux打包压缩命令

    转自:http://www.cnblogs.com/end/archive/2011/04/20/2022614.html tar命令 [root@linux ~]# tar [-cxtzjvfpPN ...

  5. Java之--Java基础知识

    一.软件基础知识 1.软件:一系列按特定顺序组织的计算机数据和指令的集合. 1)系统软件:DOS.windows.linux. 2)应用软件:QQ.扫雷等. 2.软件开发就是制作软件. 3.人与计算机 ...

  6. VC++中内存对齐

    我们经常看到求 sizeof(A) 的值的问题,其中A是一个结构体,类,或者联合体. 为了优化CPU访问和优化内存,减少内存碎片,编译器对内存对齐制定了一些规则.但是,不同的编译器可能有不同的实现,本 ...

  7. new 动态分配数组空间 .xml

    pre{ line-height:1; color:#3c3c3c; background-color:#d2c39b; font-size:16px;}.sysFunc{color:#627cf6; ...

  8. 从date中获取相应信息

    创建测试用表: CREATE OR REPLACE VIEW v AS SELECT TO_DATE('2015-5-5 13:14:15', 'YYYY-MM-DD HH24:MI:SS') AS ...

  9. 【LeetCode】83 - Remove Duplicates from Sorted List

    Given a sorted linked list, delete all duplicates such that each element appear only once. For examp ...

  10. C/C++——C++变量的作用域与生命周期,C语言中变量的作用域和生命周期

    全局变量 作用域:全局作用域(全局变量只需在一个源文件中定义,就可以作用于所有的源文件.) 生命周期:程序运行期一直存在 引用方法:其他文件中要使用必须用extern 关键字声明要引用的全局变量. 内 ...