随笔 - 47  文章 - 2  评论 - 375 

用C#编写ActiveX控件(一)


    前些日子做一个Web项目,必须自己编写一个ActiveX控件。如今的ActiveX控件大多是使用VB/C++来开发的,而我对他们并不熟悉,因此考虑使用熟悉的C#编写ActiveX控件。

    首先,建立一个WinForm控件项目HelloWorld,并拖入一个Label控件,文字设为HelloWorld,如图:

UserControl1.cs内容如下:
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;

namespace HelloWorld
{
    
/// <summary>
    
/// UserControl1 的摘要说明。
    
/// </summary>

    public class Demo : System.Windows.Forms.UserControl
    
{
        
private System.Windows.Forms.Label label1;
        
/// <summary>
        
/// 必需的设计器变量。
        
/// </summary>

        private System.ComponentModel.Container components = null;

        
public Demo()
        
{
            
// 该调用是 Windows.Forms 窗体设计器所必需的。
            InitializeComponent();

            
// TODO: 在 InitComponent 调用后添加任何初始化

        }


        
/// <summary>
        
/// 清理所有正在使用的资源。
        
/// </summary>

        protected override void Dispose( bool disposing )
        
{
            
if( disposing )
            
{
                
if( components != null )
                    components.Dispose();
            }

            
base.Dispose( disposing );
        }


        
组件设计器生成的代码
    }

}


    此时编译项目,可以生成HelloWorld.dll。将此dll拷贝到IIS的虚拟根目录下,然后建立一个helloworld.htm的文件,html代码如下:
<body bgcolor='#223344'>
<object id="helloworld" classid=’http://localhost/HelloWorld.dll#HelloWorld.Demo’ Width="184" Height="96" VIEWASTEXT> </object>
</body>
在IE地址栏中输入以下地址:http://localhost/helloworld.htm,出现界面:

如图,控件已经成功在页面上显示了。OK,我们已经完成了第一步。

    但是问题到这里还没有解决。不相信?你可以试试在另外一台机器上测试,注意需要修改对应的html代码和URL地址。你可以看到这个在原来显示控件的地方是一个红色的叉,或者还会弹出一个对话框,表示这个控件没有任何权限。出现这个结果是微软的默认设置造成的,作者必须在控件所在的控件的 AssemblyInfo.cs/vb 中执行一个安全声明,声明这个控件必须使用赋予的权限,才可以显示出界面。我们在AssemblyInfo.cs中引用System.Security命名空间,并添加一句:
[assembly : AllowPartiallyTrustedCallers()]
现在重新编译,并且替换以前的dll,界面又可以显示出来了。

    需要提醒的是,到现在为止,我们编写的还不是真正的ActiveX控件。这个控件到现在为止,还只是能够实现自身的显示,并且不能实现更多的功能,比如实现与脚本的交互或者操作客户端的注册表或者磁盘。这是由于.Net Framework的安全模型所限制的。如果我们希望这个控件突破.Net Framework安全模型的限制,实现与脚本的交互或者操作客户端的注册表或者磁盘的话,必须要让它成为真正的ActiveX控件。下面,我们把刚才的控件变成真正的ActiveX控件。

    首先使用 工具—〉创建GUID 生成一个GUID,并修改UserControl1.cs文件。首先增加引用System.Runtime.InteropServices命名空间,并在Demo前面加入一条语句:

注意Guid中的字符串,就是你生成的Guid字符串。它是你所生成的ActiveX控件的唯一标识符。然后修改项目属性,如图:

注意面板中的最后一项,我们唯一需要修改的是将其值改为True。

    重新编译。我们使用 工具—〉OLE/COM对象查看器 查看,如图:

可以看到,我们写的HelloWorld.Demo已经被正确识别为COM组件。现在,我们已经可以像使用其它ActiveX控件一样在网页中显示了。在HelloWorld.Demo点击鼠标右键,如图:

选择Copy HTML <object> Tag to Clipboard,可以将代码拷入剪贴板。

现在,我们改写helloworld.htm,html代码如下:
<body bgcolor='#223344'>
<object id="helloworld"
   classid
="clsid:9551B223-6188-4387-B293-C7D9D8173E3A" Width="184" Height="96">
</object>
</body>
使用IE查看,我们的控件又可以在网页中显示了。不过,这个时候它已经不再是以前的.net WinForm控件了,而是货真价实的ActiveX控件了。

    不过,编写ActiveX控件的任务还没有完成。我们还没有实现脚本互动或者读写I/O,也没有实现ActiveX控件的自动分发。在下一篇Blog中,我会完成ActiveX控件的编写。

    PS:这是我在博客园上的第一个Post,希望得到大家的支持。

红马天下 版权所有
博客:http://homer.cnblogs.com/
欢迎转载,但转载必须注明作者和出处。

posted on 2005-01-04 23:00 红马天下 阅读(30719) 评论(106)  编辑 收藏 所属分类: Asp.Net

  回复  引用  查看    
2005-01-04 23:11 | 洛特      
支持!接着写下去.建议把你的CSS换一下啊.这个黑黑的看不清.
等这个很久了呢..

  回复  引用    
2005-01-05 00:20 | suyife [未注册用户]
支持作者。
  回复  引用  查看    
2005-01-05 08:13 | jhtchina      
支持作者,我才开始学习.
  回复  引用    
2005-01-05 08:23 | xp [未注册用户]
不过,这个时候它已经不再是以前的.net WinForm控件了,而是货真价实的ActiveX控件了。

======================================
请问一下,客户端还要不要装.net framework啊?
  回复  引用    
2005-01-05 09:44 | floerggyy [未注册用户]
客户端是需要装framework的,第一次看见在.net下写ActiveX组件,呵呵:)找这个很久了一直没有他细研究
  回复  引用  查看    
2005-01-05 09:59 | Lion      
不错
  回复  引用  查看    
2005-01-05 11:18 | 水云间      
太好了,终于找到了一些比较实际的,支持一下。
  回复  引用    
2005-01-05 12:27 | arui [未注册用户]
新鲜 不错 支持 继续 呵呵
  回复  引用  查看    
2005-01-05 12:40 | 风之子      
Good,顶
  回复  引用    
2005-01-05 13:03 | ww [未注册用户]
客户端要装framework的话,这样的控件有什么意义??
  回复  引用    
2005-01-05 16:27 | scong [未注册用户]
简单明了,入门得好例子,继续:)
  回复  引用    
2005-01-05 17:02 | lay [未注册用户]
客户端要装framework,那winform跟它有什么区别啊
  回复  引用  查看    
2005-01-05 21:53 | Jirong Zhou      
http://www.cnblogs.com/jrzhou/archive/2005/01/05/86992.html

顺便请教下如何trackback?我找了半天
  回复  引用    
2005-01-06 09:30 | hello [未注册用户]
好啊,好啊。期待着!!谢了
  回复  引用    
2005-01-06 13:42 | Xpc [未注册用户]
具有一定的研究意义,

没什么实用价值
  回复  引用    
2005-01-06 16:53 | canny [未注册用户]
很有意义啊!!!我们的项目正好可以参考!!
  回复  引用    
2005-01-18 15:05 | ares [未注册用户]
支持,等待发布篇,小弟现在正要学写这个!!!太感谢了
  回复  引用    
2005-01-18 15:50 | ares [未注册用户]
首先使用 工具—〉创建GUID 生成一个GUID,并修改UserControl1.cs文件。首先增加引用System.Runtime.InteropServices命名空间,并在Demo前面加入一条语句:

请问生成GUID时,GUID的类型选什么?
  回复  引用    
2005-01-22 05:41 | xxy [未注册用户]
好,支持!!!!
  回复  引用    
2005-01-27 09:00 | jizhe@msn.com [未注册用户]
老大,颜色改一下吧,累眼!

我想用这个做个在线安装程序,好像msn or yahoo的在线安装!怎么样?
  回复  引用    
2005-01-27 11:31 | lin [未注册用户]
你好:D 文章很好啊
不过有一个地方我不明白阿
工具—〉创建GUID 生成一个GUID
还有ole对象察看器,我都找不到阿
是vs2003 IDE 里的吗?
请告诉我哪能打开阿 ,谢谢!
  回复  引用  查看    
2005-01-28 11:35 | 红马天下      
To lin:

是的,vs2003 IDE附带的工具。
  回复  引用    
2005-03-17 09:23 | 小斌 [未注册用户]
你好:ActiveX控件,如何一次安裝後以後的運行都不要提示用戶

“這個畫面上某個ActiveX控制項與其他部分相互作用時可能會不安全。要允許相互作用?”

然後兩個按鈕 「是」 「否」

因為我要寫的程序如果老是這樣的話每次用戶刷新都要提示非常的煩。就像webpos的發票打印一樣,如果每一次交易都提示一次界面特別的不友好。能不能討論一下我的MSN: hunter_32252@hotmail.com QQ:
33890361
好,支持。

  回复  引用    
2005-04-21 15:42 | szx [未注册用户]
超级不错的文章,长见识了,学到东西了
  回复  引用    
2005-05-11 11:23 | jenie [未注册用户]
不得不说一句, 挺好,谢谢了, 不过不知道有没有关于vc++这样好的实例!·!!
  回复  引用    
2005-05-18 16:02 | cc [未注册用户]
如果在客户端要装framework,那这个控件的适用范围太小了,能不能不装阿
  回复  引用    
2005-06-14 10:51 | 学习的人 [未注册用户]
很值得学习,不错
  回复  引用  查看    
2005-06-21 09:30 | Jason.NET      
作者有没有测试需不需要装Framework也可以跑啊?
如果要装Framework,那说到底还不是ActiveX,只是一个ActiveX的代理而以.最终的实现还是其于Framework.

如果客户端不需要装Framework,那可真是如获至宝啊
  回复  引用    
2005-07-04 17:52 | 古月 [未注册用户]
你好:D 文章很好啊
不过有一个地方我不明白阿
工具—〉创建GUID 生成一个GUID
还有ole对象察看器,我都找不到阿
是vs2003 IDE 里的吗?
请告诉我哪能打开阿 ,谢谢!


我也找了半天了,都找不到

  回复  引用    
2005-07-04 17:57 | 古月 [未注册用户]
首先,建立一个WinForm控件项目HelloWorld,并拖入一个Label控件,文字设为HelloWorld,如图:
 那个图怎么是那样子的???
  回复  引用    
2005-07-14 22:36 | PingYJ [未注册用户]
老大,佩服啊,能不能推荐这方面的书籍啊。
  回复  引用    
2005-07-22 20:01 | 艾解清 [未注册用户]
佩服,请问楼主从开始学C#至今都看了那些方面的书籍啊
  回复  引用    
2005-08-08 01:05 | 笨蛋 [未注册用户]
我做不出来!每次都是象一个windows窗体的东西,每个人都在拍,大家加油!
  回复  引用    
2005-08-08 01:07 | 笨蛋 [未注册用户]
我用的os是xp,studio2003,对照代码七遍了,哎大家都这么厉害,只有我一个人做不出来???????????
  回复  引用    
2005-08-08 01:11 | 笨蛋 [未注册用户]
完全绝对地有问题,大家不要误会,我是说我自己肯定有问题,太奔了
  回复  引用    
2005-08-08 01:13 | 笨蛋 [未注册用户]
//这样对吗,有什么问题????

using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;

namespace helloworld
{
/// <summary>
/// UserControl1 的摘要说明。
/// </summary>
public class Demo : System.Windows.Forms.UserControl
{
private System.Windows.Forms.Label label1;
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.Container components = null;

public Demo()
{
// 该调用是 Windows.Forms 窗体设计器所必需的。
InitializeComponent();

// TODO: 在 InitComponent 调用后添加任何初始化

}

/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if( components != null )
components.Dispose();
}
base.Dispose( disposing );
}

#region 组件设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要使用代码编辑器
/// 修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.label1 = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// label1
//
this.label1.Location = new System.Drawing.Point(32, 32);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(56, 16);
this.label1.TabIndex = 0;
this.label1.Text = "hello world";
//
// UserControl1
//
this.Controls.Add(this.label1);
this.Name = "UserControl1";
this.Load += new System.EventHandler(this.UserControl1_Load);
this.ResumeLayout(false);

}
#endregion

private void UserControl1_Load(object sender, System.EventArgs e)
{

}
}
}

  回复  引用  查看    
2005-08-20 15:26 | sheepchang      
做了N次都不是楼主那样的!
http://www.cnblogs.com/images/cnblogs_com/sheepchang/32749/r_error.JPG
  回复  引用    
2005-09-01 22:24 | sucesss [未注册用户]
功力不够,偶也是一片空白.
  回复  引用    
2005-09-06 12:57 | georgegodman [未注册用户]
这个根本就不能算是ActiveX,客户端必须要装.NET FrameWork的,没什么实用价值,不可能要求网页的第个浏览都装了那么大一的一个包
  回复  引用    
2005-09-28 15:13 | wwrre [未注册用户]
sdsfasfa
  回复  引用    
2005-09-30 21:36 | C# [未注册用户]
不错
  回复  引用    
2005-10-19 13:03 | 花纯春 [未注册用户]
写得太好了,
虽然有人提出,客户要装.net framework可是,在以后发布的OS中的自带有的,随着时间的推移,这不是问题,
期盼作者,能尽快写出下篇。
  回复  引用    
2005-10-19 13:04 | 花纯春 [未注册用户]
支持,请写出下篇,谢谢。

好文章
  回复  引用    
2005-10-19 16:15 | weekzero(星期零) [未注册用户]
问题求助:按照您的这个思路制作了一个摄象头拍照的activeX,调用的时候使用
<object id="WindowsControlDv" classid="clsid:7E614D4F-BFFD-4410-8ACC-E8C00288CABA"></object>
的方式,本地可以,但是别的机器访问我的机器不可以.
使用
<object id="WindowsControlDv" classid="http:WindowsControlDv.dll#WindowsControlDv.UserControl1" VIEWASTEXT>
</object>
方式,别的机器到是可以访问到了,但是摄象头不可以使用了

我的第一种方式的问题可能出在什么地方呢?

这是什么原因呢?谢谢您的答复
  回复  引用    
2005-10-19 17:05 | weekzero(星期零) [未注册用户]
使用<object id="WindowsControlDv" classid="clsid:7E614D4F-BFFD-4410-8ACC-E8C00288CABA"></object>
方式后,别的机器不可以访问到,是不是要在访问者的机器上做个什么注册什么的?

  回复  引用  查看    
2005-10-28 17:07 | 吹雪      
我按lz的第一步来放一个Label的时候也遇到如下情况
# re: 用C#编写ActiveX控件(一)
做了N次都不是楼主那样的!
http://www.cnblogs.com/images/cnblogs_com/sheepchang/32749/r_error.JPG
sheepchang 评论于 2005-08-20 15:26

不知道是什么原因造成的,难道是.net Framework版本问题?
  回复  引用  查看    
2005-11-02 16:01 | freeman      
吹雪:
问题主要处在 classid=’http://localhost/HelloWorld.dll#HelloWorld.Demo’ 你需要在#号后面更改成你的项目名称和类名
  回复  引用    
2005-11-17 15:17 | Dyliang [未注册用户]
我找这个找了好久了,我早就想用C#来写控件了,但不知道从何着手,真是太谢谢楼主了,今天晚上一定要好好学学用.
  回复  引用    
2005-12-01 10:29 | xiao_p [未注册用户]
晕了,还需要安装framework,还这么多人追捧,支持原创的精神,不过好像不值得大家这样吧…………


  回复  引用    
2005-12-03 10:48 | 阿良 [未注册用户]
楼主,你那个 OLE/COM Objects Viewer 在哪里启动的?
  回复  引用    
2005-12-22 17:02 | 飞翔鸟 [未注册用户]
用C#来实现手写签名是不是必须要写成ActiveX控件
  回复  引用    
2006-02-27 14:22 | 12343456567aa [未注册用户]
很好的帖子。不过在vs2005开发环境下还需要做一点调整.应该把设置属性[ComVisible(true)]才能够注册
  回复  引用    
2006-03-20 17:39 | ayaya [未注册用户]
啥都不說了!謝謝!
  回复  引用    
2006-03-23 11:29 | re [未注册用户]
ActiveX 现在已经过时了。
  回复  引用    
2006-03-31 17:54 | iwa [未注册用户]
非常感谢,
就象前面朋友提到的,在vs2005开发环境下还需要做一点调整.应该把设置属性[ComVisible(true)]才能够注册

  回复  引用    
2006-04-03 22:12 | olivia [未注册用户]
@iwa
那么在vs2005种应该怎么设置呢?你们大家说的属性[ComVisible(true)]是什么的属性?在哪里可以找到哈?在vs2005中还有什么不一样呢?
  回复  引用    
2006-04-06 17:53 | gxpotato [未注册用户]
@olivia
VS2005的话,在AssemblyInfo.cs文件里面有这个选项,默认是false的。


@楼主
请问,我用的是VS2005,在做到最后一步的时候也就是生成COM的时候,在测试页面出现一个大大的叉。我确认我的“为 COM Interop 注册”已经打勾了。但是,还是不行。前面的都成功了。

引用System.Runtime.InteropServices命名空间这个在VS2005里面是默认的,生成GUID在VS2005里面也是自动生成的。我实在想不通还有什么东西需要特别注意的。望高手指教。
  回复  引用    
2006-07-07 12:57 | Ripple [未注册用户]
done!
thank you !
  回复  引用    
2006-07-10 21:17 | Eric Tsai [未注册用户]
您好,我現在也有需要寫一個能抓web cam影像的ActiveX Control。我現在用DirectShow可以抓得到,但是放到網頁上卻沒辦法執行。不知道您的source code能否借我參考,感謝。erictsai53[at]gmail.com
  回复  引用    
2006-07-12 20:24 | WANGERPANG [未注册用户]
ASP.NET上的例子有吗?也是用C#
  回复  引用    
2006-07-19 14:31 | felix1 [未注册用户]
.net开发的ActiveX控件放在页面上后,该页面为什么会引起项目的死掉?
  回复  引用    
2006-07-20 11:50 | lizhi [未注册用户]
请问有没有C#写的html解析啊?

比如说:数据库里面有 : <input id="txtName" type="text" value="新增流程分类" /> 这一个 text 类型的数据!


现在,我需要写一段解析代码, 它可以解析到<> , input , id , 还有 value 里面的值等. 并在网页中显示出来!

大哥们,救救急啊!

万分感谢啊~~~请发往邮箱: lizhi198304@163.com
  回复  引用    
2006-09-18 12:19 | newcomer[匿名] [未注册用户]
如何生成HelloWorld.dll ?
我是Copy Paste 的 Code. 不行 啊

  回复  引用    
2006-11-06 13:12 | bluewater [未注册用户]
強人啊。頂。。。。。
  回复  引用    
2006-11-15 15:09 | hujunhua [未注册用户]
有一问题请教 就是我更新了demo 然后生成dll
覆盖以前的DLL 但是界面上仍然显示是以前的

缓存 临时文件夹都清理了还是 但是我从新启动电脑后就出新了新的

怎么回事啊?
  回复  引用    
2007-01-18 20:13 | Namebus [未注册用户]
http://www.openssl.com.cn/thread-101-1-1.html

这个论坛有提供免费的国际认证代码签名证书,可以很方便的用于ActiveX的数字签名,这样发布代码就变为可信了。
  回复  引用    
2007-01-23 16:58 | 土豆 [未注册用户]
学习中极力支持!!
在IE地址栏中输入http://localhost/helloworld.htm后界面出现了,但创建了一个GRID,并修改了页面属性,但在OLE/COM对象查看器里面没有被识别为COM组件,做了N遍也还是那样

到底是怎么回事呢??
谢谢
  回复  引用    
2007-02-26 14:31 | 张杰 [未注册用户]
我的控件中为操作位图而使用了指针,因而在编译时需要选择“允许使用不安全代码”。发现这样编译出来的控件无法显示出来。后来做了一个测试,找了一个原来可以正确显示的控件,不做任何代码的修改,只是把项目属性中的“允许使用不安全代码”选择上,再编译后的控件,就不能显示了。因此判断是这个编译设置起的作用。不知道 楼主 对这个问题是否有处理办法。
  回复  引用    
2007-04-03 15:23 | 阿胜 [未注册用户]
我的GUID是65C0C1A5-8726-4cad-B4C7-A8C9B3860F73.但是却不显示出来!!怎么回事??
  回复  引用    
2007-04-04 17:14 | 不知该怎么弄 [未注册用户]
看了你的文章,收益很多,可还是有两个问题不知该怎么解决,真的希望得到你的帮助:

1、生成好的ActiveX该如何用Cab文件来发布,用户访问我的页面后可以自动下载注册。如果我的ActiveX更新后,用户再访问的话,如何替换已有的。

2、我在ActiveX里写了对客户端的磁盘进行I/o操作,可是我在另外的机器上访问的时候会出现错误,调用别的方法就没有错误,是不是还有那个安全设置没有设定啊??

谢谢。
  回复  引用    
2007-06-09 14:14 | 刘良良 [未注册用户]
你能把你的代码给我看看吗,求你了。我对它很感兴趣的。你能给我发一份 吗?我的油箱是:xinxiaoxinxiao@163.com 拜托
  回复  引用    
2007-06-09 14:20 | 刘良良 [未注册用户]
我永远都支持你。你就是我的偶像
  回复  引用  查看    
2007-06-13 20:48 | ma.cnblogs.com      
基本我认为不包含可为 COM Interop 注册是不可能成功的,因为我试了N遍后,还是 不包含可为 COM Interop 注册的任何类型。
  回复  引用    
2007-06-21 18:10 | tuonibao [未注册用户]
请问 版主和各位朋友
你们的activex控件怎么和数据库交互。
  回复  引用    
2007-06-21 18:25 | tuonibao [未注册用户]
请问 红马天下
activex可以访问数据库吗,我做了几都提示不行的。你们有什么办法,请指教。
感激!

  回复  引用    
2007-06-22 10:19 | tuonibao [未注册用户]
阳阳
能不能明确说一下,activex能和数据库交互吗?如果能希望指条路,在下不胜感激。qq:361552912 e-mail : yyb9385@126.com
  回复  引用    
2007-06-22 10:21 | tuonibao [未注册用户]
谢谢你介绍那篇文章给我,文章挺好,我正在研究,但是项目紧,所以我想先知道个结果,谢谢!
  回复  引用    
2007-06-22 12:19 | jld [未注册用户]
不错顶顶顶顶
  回复  引用    
2007-06-22 15:39 | tuonibao [未注册用户]
我用c#做了一个activex控件
现在在客户端也可以安装了
看客户端的注册表里也有相关信息
但是安装后仍然显示为一个叉
请问这是为什么?