c# ActiveX 控件的开发

关于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  接口定义

1
2
3
4
5
6
7
8
9
10
11
    [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)

  自定义ActiveX控件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
[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>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<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>

  

源码共享:  戳我

 

posted @   老张一笑  阅读(1874)  评论(4编辑  收藏  举报
编辑推荐:
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
阅读排行:
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· 2 本地部署DeepSeek模型构建本地知识库+联网搜索详细步骤
点击右上角即可分享
微信分享提示