Chinaunix首页 | 论坛 | 博客
  • 博客访问: 9471953
  • 博文数量: 1751
  • 博客积分: 12961
  • 博客等级: 上将
  • 技术积分: 20101
  • 用 户 组: 普通用户
  • 注册时间: 2009-01-09 11:25
个人简介

偷得浮生半桶水(半日闲), 好记性不如抄下来(烂笔头). 信息爆炸的时代, 学习是一项持续的工作.

文章分类

全部博文(1751)

文章存档

2024年(27)

2023年(26)

2022年(112)

2021年(217)

2020年(157)

2019年(192)

2018年(81)

2017年(78)

2016年(70)

2015年(52)

2014年(40)

2013年(51)

2012年(85)

2011年(45)

2010年(231)

2009年(287)

分类: LINUX

2009-12-18 10:40:25


ActiveX控件运行在客户端。我们可以获得客户端的一些信息,如IC卡的信息,客户端的验证等等。但是ActiveX控件也有许多缺点:客户端的部署很困难,如客户端不能正确下载,下载了以后不能正确执行,下载的时候需要设置IE的安全级别等等。
更多的时候,我都在使用COM组件来扩展ASP的功能。准确地说,是服务端运行的Activex Dll组件。使用Server.CreateObject(“工程名.类名”)即可完成对组件的调用。这种方式问题很少,只要组件中以PUBLIC对外暴 露方法既可。但是,有时候我们必须使用ACTIVEX 控件(*.OCX)嵌入到网页中执行来获取客户端的信息。这就有了许许多多的一些问题。
这是我们需要解决的N个问题(从简单到难)
1. 如何从服务端获取数据,传递到ActiveX控件中。
1) 初始化时使用参数绑定
2) 运行时得到数据
2. ActiveX控件得到客户端的信息,如何传递到服务端。
3. 安全性
1) 数字签名
2) 使用IOBJSAFE接口
好了,我们开始实例学习。
这个功能演示了如何制作一个简单的控件,并嵌入网页中执行。
工作环境:WINXP+VB6+IE6
我的IE安全设置为安全级别-中。所有的Activex选项设为启用。

打开vb6,新建ActiveX控件工程。
工程名:fOcx,用户控件名:UC1
为了方便,我们使用ActiveX控件接口向导…,菜单->外接程序->外接程序管理器->VB 6 ActiveX控件接口向导。确定即可。

打开ActiveX控件接口向导,下一步,对于可用名称和选定名称我们默认下一步,新建自定义成员,GetInfo类型:属性,下一步,共有方法中 选择我们刚才添加的GetInfo,映射到控件选择TxtInfo,成员选择Text,下一步直到完成。代码窗口中会生成一些我们不需要的,删除,剩下的 代码如下:
Option Explicit
';注意!不要删除或修改下列被注释的行!
';MappingInfo=txtinfo,txtinfo,-1,Text
Public Property Get GetInfo() As String
GetInfo = txtinfo.Text
End Property

Public Property Let GetInfo(ByVal New_GetInfo As String)
txtinfo.Text() = New_GetInfo
PropertyChanged "GetInfo"
End Property

';从存贮器中加载属性值
Private Sub UserControl_ReadProperties(PropBag As PropertyBag)

txtinfo.Text = PropBag.ReadProperty("GetInfo", "Text1")
End Sub

';将属性值写到存储器
Private Sub UserControl_WriteProperties(PropBag As PropertyBag)

Call PropBag.WriteProperty("GetInfo", txtinfo.Text, "Text1")
End Sub

OK,好了,我们编译成fOcx.ocx文件,然后F5直接运行,VB会打开一个测试页。如下:
E:\Program Files\Microsoft Visual Studio\VB98\UC1.html
同时,打开你的IE浏览器,看到了吧,你做的控件出现在了这个测试页中。
你可以打开测试页,可以看到ClsID,比如:890D1028-298B-45CF-9A64-6ED5A5BACBC9

因为VB编译的时候已经完成注册.所以无法模拟客户端没有安装该控件时出现的提示.
我们继续
使用regsvr32 F:\csdn_vb\com+_activeX\sample1\fOcx.ocx –u卸载
或者
打开注册表,在HKEY_CLASSES_ROOT\CLSID下面找到
890D1028-298B-45CF-9A64-6ED5A5BACBC9项,删除之,当然这种方式还有项存在而没有删除干净.

此时浏览,由于IE中ActiveX设置为启动,所以,控件会显示出来。
下载后的ocx到哪里去了???
打开该目录(可能有所不同)E:\WINDOWS.0\Downloaded Program Files,看到了吧,fOcx.UC1文件在这个目录下.
原理:客户端下载该控件后,自动注册,然后放在上述这个目录下.这时我们可以打开注册表看看CLSID,呵呵,还是以前的那个.
我们可以右键看看fOcx.UC1的属性,看看相关内容,这里显示了该OCX所依赖的所有文件.所以,你的OCX尽量减少使用高级控件或者第三方的控件,否则,下载就有些问题了.

如果IE中关于ActiveX的选项设为禁用,那么浏览器就会出现对话框”当前安全设置禁止运行该页中的ActiveX控件.因此可能无法正确显示该页”,这个就需要其他的方式来处理了。
一般用户默认的都是禁用ActiveX选项,所以让用户自己设置不太合适。

=======================================================================

ASP与ACTIVEX控件交互实战
ASP与ACTIVEX控件交互实战(二)
我们来看看如何从服务端获取数据,传递到ActiveX控件中。
1) 初始化时使用参数绑定
2) 运行时得到数据
打开vb6,新建ActiveX控件工程。
工程名:fOcx,用户控件名:UC2
为了方便,我们使用ActiveX控件接口向导…,菜单->外接程序->外接程序管理器->VB 6 ActiveX控件接口向导。确定即可。
打开ActiveX控件接口向导,下一步,对于可用名称和选定名称我们默认下一步,新建自定义成员,GetInfo类型:属性,下一步,共有方法中选择我 们刚才添加的GetInfo,映射到控件选择TxtInfo,成员选择Text,下一步直到完成。代码窗口中会生成一些我们不需要的,删除,

';注意!不要删除或修改下列被注释的行!
';MappingInfo=txtinfo,txtinfo,-1,Text
Public Property Get GetInfo() As String
GetInfo = txtinfo.Text
End Property
Public Property Let GetInfo(ByVal New_GetInfo As String)
txtinfo.Text() = New_GetInfo
PropertyChanged "GetInfo"
End Property

Private Sub Command1_Click()
Label2.Caption = GetInfo()
End Sub

';从存贮器中加载属性值
Private Sub UserControl_ReadProperties(PropBag As PropertyBag)

txtinfo.Text = PropBag.ReadProperty("GetInfo", "Text1")
End Sub

';将属性值写到存储器
Private Sub UserControl_WriteProperties(PropBag As PropertyBag)

Call PropBag.WriteProperty("GetInfo", txtinfo.Text, "Text1")
End Sub

编译成OCX控件.运行生成的测试页.Text中默认的是Text1
如何将服务器端的数据传递给OCX呢?

使用Microsoft ActiveX Control Pad这个工具,可以很容易找到.
直接用这个工具把测试页打开.
菜单->Edit->Edit Activex Control,呵呵,打开了一个可视化的界面.
看到了吧,有一个属性框,我们可以进行设置,设置完成以后的代码如下:


New Page


CLASSID="CLSID:890D1028-298B-45CF-9A64-6ED5A5BACBC9"
CODEBASE="">






增加了ID,ID就是我们用来访问的标志.还有我们的属性GetInfo,我们也设定初始值了
好了,运行.
Text中就出现了我们设定的值”这是ocx得到的客户端读卡器的信息”

我们把上边的页面改成asp的,看代码:


龙卷风测试页


<%
dim sValue
sValue="这是ocx得到的客户端读卡器的信息"
%>
CLASSID="CLSID:56DFCA88-F5B8-4879-853B-97FE504423FD"
CODEBASE="">






OK,运行即可

我们看看第二种情况
运行时得到数据



龙卷风测试页

<%
dim sValue
sValue="这是ocx得到的客户端读卡器的信息"
%>



CLASSID="CLSID:56DFCA88-F5B8-4879-853B-97FE504423FD"
CODEBASE="">





=====================================================================

ASP与ACTIVEX控件交互实战
ASP与ACTIVEX控件交互实战(三)
ActiveX控件得到客户端的信息,如何传递到服务端???
一种方法就是得到值后,使用Get,Post方式提交,这可能也是最常用的.
有没有更好一些的方法呢?
能不能在控件中直接向服务器发出请求而得到数据呢?

打开vb6,新建ActiveX控件工程。
工程名:fOcx,用户控件名:UC3
添加1个按钮,2个文本框
代码如下:
Option Explicit
Private Sub Command1_Click()
';注意字符串和数字的写法有些区别
';使用AsyncRead通过HTTP发送你的请求
UserControl.AsyncRead "=" & Text1.Text & "", vbAsyncTypeByteArray
UserControl.AsyncRead "=" & Text1.Text, vbAsyncTypeByteArray
End Sub

';AsyncReadComplete 事件用来从asp页面接受和分析。
';当容器刚完成一个异步读取请求时 , 发生该事件?
';AsyncProp 中的数值指定了已完成的某个异步数据读取请求,
';它与前一个 AsyncRead 方法调用中的数据匹配。
';AsyncReadComplete 事件过程中应包含错误处理代码,因为错误状态会终止下载。
';如果发生了这种情况,当访问 AsyncProperty 对象的 Value 属性时将会发生错误。
Private Sub UserControl_AsyncReadComplete(AsyncProp As AsyncProperty)
On Error GoTo errhandle
Text2.Text = ByteArrayToString(AsyncProp.Value)
errhandle:
Err.Raise 601, "异步读取发生了错误", Err.Description
End Sub
';将字节数组转换成字符串
Public Function ByteArrayToString(bytArray() As Byte) As String
Dim sAns As String
sAns = StrConv(bytArray, vbUnicode)
ByteArrayToString = sAns
End Function

我们来看看这个文件
<%
dim str
str=request("s1")
if str="name" then
response.write ("龙卷风")
elseif str="age" then
response.write ("26")
else
response.write ("没有可用信息返回")
end if
%>
很简单,使用request接受参数,response返回。

这个例子可以进一步处理,将服务器名以属性的方式传递给控件。
比如:
然后在程序中得到,就可以使用了,如:
UserControl.AsyncRead "=" & Text1.Text & "", vbAsyncTypeByteArray

=======================================================================

ASP与ACTIVEX控件交互实战
基于ActiveX 控件开发动态Web页

  Web页面的开发主要分为三类:静态Web页面、半动态Web页面以及Client端动态页面。本文重点论述基于ActiveX Control(控件)动态实时页面的开发。
  ActiveX控件用于Web的过程是将控件嵌入主页中,用户通过浏览器访问该主页时,将主页中的控件下载,并在用户机器上注册,以后就可在用户的浏 览器上运行。控件下载一次后就驻留在用户本地机器上,下次再访问相同的主页时,可不再下载该控件,而是直接运行用户本地的控件。这里控件容器就是浏览器, 用户不需要通过浏览器调用控件的属性或方法。因此,开发面向Web的ActiveX控件比开发桌面的控件还要简单些,所复杂的是如何将该控件很好地嵌入主 页,使用户能正常浏览。下面介绍这个问题。
在Web页中加入ActiveX 控件
  在HTML页面中使用ActiveX控件包含三个基本操作:将控件放入HTML中;将该控件下载给用户;在用户机器上安装该控件。如果只是针对IE用 户,在HTML中插入ActiveX控件就比较简单;如果同时兼顾IE和Netscape用户,则要做更多工作。大家知道,HTML文件由文本和各种标志 (tags)组成,ActiveX 控件对于IE在HTML中的标志是<OBJECT>,该标记有几个重要的参数特性,它们是:
  1.ID:为控件提供一个标识名称,为HTML代码提供一种访问该控件的方式。
  2.CLASSID:是该控件唯一的UUID,告诉IE装入哪个对象。如果使用已经开发好的控件,它的CLASSID可以通过调用Win95或NT下 的应用Regedit来查找。从开始菜单中运行该程序,展开HKEY_CLASSES_ROOT项,可以看到按字母顺序排列的注册表,找到需要使用的控件 名,例如WClnt,展开时可看到一个CLSID文件夹,里面就是该控件的CLASSID。
  如果是自己用VC开发控件,该UUID可以在ActiveX控件项目中的ODL(对象描述库)文件中找到;通过查看控件的类信息注释来定位特定控件的UUID,例如,要找到CMyControl控件的UUID,则需要找到以下代码:
  // Class information for CMyControl
  [uuid (051C4748-1262-11D2-87C1-00A024D948FB),
  licensed,
  helpstring(“CmyControl Control”), control ]
  uuid后面括号中的内容就是该控件的UUID。
  3.CODEBASE:如果在用户机器上没有控件的当前版本,该参数告诉用户浏览器在哪里可找到要下载的控件和最新版本号.当控件作了修改后,可以更改版本号强制用户重新下载。
  4.PARAM:该标记用于设置控件的初始属性值,它有两个特性:Name和Value,即属性名称和属性值。
  此外还有一些标记,如:Width表示该控件所占的宽度,Height表示高度等,总体来说,这样一个插入控件的HTML代码和插入Java Applet的HTML代码非常相似。
  下面是一个嵌有ActiveX控件的HTML代码示例:
 
ID=“CMyControl”
CLASSID=“clsid:051C4748-1262-11D2-87C1-00A024D948FB ”
CODEBASE=“#version=1,0,0,1”
WIDTH=400
HEIGHT=200
ALIGN=center
HSPACE=0
VSPACE=0

  如果希望控件还能在Netscape中运行,除了Netscape需加装插件外,HTML也要加一些附加标记,下面的例子中EMBED段就是为 Netscape加上的。如果使用MFC开发OCX控件,则少数用户第一次访问时除了下载OCX文件外,还要下载相应的MFC DLL,下载量变大,这时可将相关文件在服务器端打包成可以在客户端自解压安装的CAB文件。经过修改后的HTML代码段如下:
<ALIGN=“CENTER” CLASSID=“clsid:
7BCA18C6-2178-11D2-87C1-00A024D948FB”
WIDTH=“1200” HEIGHT=“900” ID=“marquee”
CODEBASE=“
WClnt.cab#version=1,0,0,1”>
<EMBED ALIGN=“CENTER”CLASSID=“clsid:7BCA18C6- 2178-11D2-87C1-00A024D948FB”
WIDTH=“1200” HEIGHT=“900” ID=“marqueequot;”
CODEBASE=“
WClnt.OCX#version=1,0,0,1”
TYPE=“application/oleobject” >
实时动态页面的实现方案
  对实时动态页面的要求多产生于一些要求自动更新实时数据的应用中,如电网监控、股市监测等。具体要求是:用户只需选取希望浏览的图表,但无需介入操作,该图表就能根据实时数据不断更新,用户总能观察到最新情况。
  要实现上述功能,结构上有两种方案:一种是设置一个中介服务器,该服务器作为控件和后台系统信息交流的中介;另一种是不设中介服务器,但在提供实时数 据的后台服务器上留出供控件通信用的数据接口,控件可以直接从后台服务器上定时获得当前实时数据。按数据提供方式分也有两种:一种是由客户端定时向服务器 发出请求,指明需要的实时数据,服务器收到请求后将满足请求的动态数据发送至相应客户;另一种是客户端只请求一次,服务器端便定时将满足请求的实时数据传 到客户端,直到客户更换要显示的图表或停止刷新。上述各方案都有其优点和局限,在应用中可考虑实际情况采用相应方案。
  工作流程为:用户先从Web服务器上下载包含ActiveX 控件的网页,控件随即在客户机上注册运行,并通过Winsock同中介服务器或直接同提供实时信息的网,如股票信息网相连接,定时取得动态实时数据,并刷 新显示。在这个体系中,客户有两条线路获得信息,一条是和Web Server的连接,从这条线上用户访问主页;另一条就是控件和后台信息网的连接,从这条线路上用户可以访问实时数据。后一条线路用Winsock建立, 传输速度远大于前一条线路,且控制灵活、效率高,不和主页下载争资源。通过这条线路,用户甚至可以传送远程控制信息实现遥控操作。
利用MFC开发ActiveX控件
  利用VC5.0开发的这种控件,功能可扩展性强,理论上独立的VC5.0程序具有的功能,该控件都能实现,例如控件直接绘制浏览器,可以使用 OpenGL等图库,图形图像功能强大。实时数据刷新频率理论上可达毫秒级,用户通过鼠标可以实现各类交互操作,如旋转、缩放,图2就是一幅GL图形,并 有一个缩放工具条进行缩放操作。如果是在计算机上观看,可以看到这几个三维图在不断旋转。
  应该说,较好的开发工具可直接用API编程或使用ATL模板库,利用MFC开发ActiveX控件不是一个好的选择,因为控件运行需要MFC DLL的支持。假如客户机器上没有这些类库(这种情况很少,但确实存在),第一次下载就要花费些工夫。不过对于熟悉MFC的开发员来说,这些问题相对 MFC提供的便利来说都是可以忽略的。
  由于VC5.0对ActiveX控件的开发提供了许多便利,所以开发一个ActiveX控件并不像许多人想象中的那么困难复杂,通过VC 5.0的AppWizard,实现控件的主类从ColeControl类派生出来,该类则是CWnd的一个子类,所以你可以像对窗口类编程一样对这个主类 编程。为了实现上面提及的功能,首先必要重载它的OnDraw函数加入需要绘制的对象,加入Winsock类(CSocket或 CAsyncSocket),以实现与后端数据服务器的通信。如果需要用OpenGL绘制丰富多彩的立体图,则要初始化GL环境。其他的工作就在于用户如 何控制程序的调度,使得各功能都能正常工作且与其他部分正常通信。此外,后端服务器程序也要增加对应于该控件的接口。
  这样的一个程序编译通过后,就成为一个可用于Web的控件,后缀名是OCX。按照前面叙述的方法将该OCX置入主页,基本的工作就算完成。
  综上所述,利用VC5.0开发ActiveX控件用于Web浏览,主要有以下几个特点:
  1.采用Winsock的通信机制,速度快、控制灵活、效率高;
  2.控件采用VC5.0编制,功能可扩展性很强;
  4.控件第一次下载虽然稍费时间,但下载后即在用户机上注册,以后可直接调用,速度效率均好;
  5.ActiveX技术是微软发展的重中之重,且已成为当前软件发展的潮流所向,发展空间广阔;
  6.系统采用VC开发,可以利用已有的采用C语言编制的系统,开发工作量大大减少。


  我们来看看如何从服务端获取数据,传递到ActiveX控件中。
  1) 初始化时使用参数绑定
  2) 运行时得到数据
  打开vb6,新建ActiveX控件工程。
  工程名:fOcx,用户控件名:UC2
  为了方便,我们使用ActiveX控件接口向导…,菜单->外接程序->外接程序管理器->VB 6 ActiveX控件接口向导。确定即可。
   打开ActiveX控件接口向导,下一步,对于可用名称和选定名称我们默认下一步,新建自定义成员,GetInfo类型:属性,下一步,共有方法中选择 我们刚才添加的GetInfo,映射到控件选择TxtInfo,成员选择Text,下一步直到完成。代码窗口中会生成一些我们不需要的,删除,
  '注意!不要删除或修改下列被注释的行!
  'MappingInfo=txtinfo,txtinfo,-1,Text
  Public Property Get GetInfo() As String
   GetInfo = txtinfo.Text
  End Property
  Public Property Let GetInfo(ByVal New_GetInfo As String)
   txtinfo.Text() = New_GetInfo
   PropertyChanged "GetInfo"
  End Property
  Private Sub Command1_Click()
  Label2.Caption = GetInfo()
  End Sub
  '从存贮器中加载属性值
  Private Sub UserControl_ReadProperties(PropBag As PropertyBag)
   txtinfo.Text = PropBag.ReadProperty("GetInfo", "Text1")
  End Sub
  '将属性值写到存储器
  Private Sub UserControl_WriteProperties(PropBag As PropertyBag)
   Call PropBag.WriteProperty("GetInfo", txtinfo.Text, "Text1")
  End Sub
  编译成OCX控件.运行生成的测试页.Text中默认的是Text1
  如何将服务器端的数据传递给OCX呢?
  使用Microsoft ActiveX Control Pad这个工具,可以很容易找到.
  直接用这个工具把测试页打开.
  菜单->Edit->Edit Activex Control,呵呵,打开了一个可视化的界面.
  看到了吧,有一个属性框,我们可以进行设置,设置完成以后的代码如下:
  
  
  New Page
  
  
    CLASSID="CLSID:890D1028-298B-45CF-9A64-6ED5A5BACBC9"
  CODEBASE="">
  
  
  
  

  
  
  增加了ID,ID就是我们用来访问的标志.还有我们的属性GetInfo,我们也设定初始值了
  好了,运行.
  Text中就出现了我们设定的值”这是ocx得到的客户端读卡器的信息”
  我们把上边的页面改成asp的,看代码:
  
  
  龙卷风测试页
  
  
  <%
  dim sValue
  sValue="这是ocx得到的客户端读卡器的信息"
  %>
    CLASSID="CLSID:56DFCA88-F5B8-4879-853B-97FE504423FD"
  CODEBASE="">
  
  
  
  

  
  
  OK,运行即可
  我们看看第二种情况
  运行时得到数据
  
  
  龙卷风测试页
  <%
  dim sValue
  sValue="这是ocx得到的客户端读卡器的信息"
  %>
  
  
  
    CLASSID="CLSID:56DFCA88-F5B8-4879-853B-97FE504423FD"
  CODEBASE="">
  
  
  

  
  
  
  运行后,点击按钮即可看到效果.

问题提出:
  ActiveX控件得到客户端的信息,如何传递到服务端???
  一种方法就是得到值后,使用Get,Post方式提交,这可能也是最常用的.
  有没有更好一些的方法呢?
  能不能在控件中直接向服务器发出请求而得到数据呢?
  打开vb6,新建ActiveX控件工程。
  工程名:fOcx,用户控件名:UC3
  添加1个按钮,2个文本框
  代码如下:
  Option Explicit
  Private Sub Command1_Click()
  '注意字符串和数字的写法有些区别
  '使用AsyncRead通过HTTP发送你的请求
  UserControl.AsyncRead "" & Text1.Text & "", vbAsyncTypeByteArray
  UserControl.AsyncRead "" & Text1.Text, vbAsyncTypeByteArray
  End Sub
  'AsyncReadComplete 事件用来从asp页面接受和分析。
  '当容器刚完成一个异步读取请求时 , 发生该事件?
  'AsyncProp 中的数值指定了已完成的某个异步数据读取请求,
  '它与前一个 AsyncRead 方法调用中的数据匹配。
  'AsyncReadComplete 事件过程中应包含错误处理代码,因为错误状态会终止下载。
  '如果发生了这种情况,当访问 AsyncProperty 对象的 Value 属性时将会发生错误。
  Private Sub UserControl_AsyncReadComplete(AsyncProp As AsyncProperty)
  On Error GoTo errhandle
  Text2.Text = ByteArrayToString(AsyncProp.Value)
  errhandle:
  Err.Raise 601, "异步读取发生了错误", Err.Description
  End Sub
  '将字节数组转换成字符串
  Public Function ByteArrayToString(bytArray() As Byte) As String
   Dim sAns As String
   sAns = StrConv(bytArray, vbUnicode)
   ByteArrayToString = sAns
  End Function
  我们来看看这个文件
  <%
  dim str
  str=request("s1")
  if str="name" then
  response.write ("龙卷风")
  elseif str="age" then
  response.write ("26")
  else
  response.write ("没有可用信息返回")
  end if
  %>
  很简单,使用request接受参数,response返回。
  这个例子可以进一步处理,将服务器名以属性的方式传递给控件。
  比如:
  然后在程序中得到,就可以使用了,如:
  UserControl.AsyncRead "" & Text1.Text & "", vbAsyncTypeByteArray
  然后在程序中得到就可以灵活处理了。


阅读(3803) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~