本文主要介绍如何在网页中配置ActiveX控件。一般来说开发好的ActiveX在网页中让用户访问可以有以下两种方式:
1. 直接将ActiveX打包为exe文件,并在exe文件中加入注册命令,让用户下载安装包自行安装。在安装过程中控件会自动注册,当打开含有控件ID的网页时,控件可以正常显示。
2. 在服务端作一些设置,让用户在第一次打开网页的时候下载控件并注册(这些过程是静默进行的),之后控件可以正常显示
从原理上来说上述两种情况并没有任何区别。在发出Qt ActiveX开发的博文之后,有几位网友提出了一些反馈,希望我能就第二种情况给出一些建议。本文主要对这种情况作一些介绍,有部分内容尚未完全完善,如果读者有更好的方式,欢迎指正。
将ActiveX控件引入到网页中,需要添加一个CODEBASE属性,让客户端浏览器知道从什么地址下载到控件,具体代码如下:
<object
ID="simpleqtactivex"
CLASSID="CLSID:F26FF23A-168E-43DB-A2C5-67242036D9AA"
CODEBASE="http://172.16.40.26:8080/mainwindow.cab"
width="1140"
height="910"
>
[Object not available! Did you forget to build and register the server?]
</object>
具体的CODEBASE是服务器中指向ActiveX压缩包的地址,这里提到了ActiveX压缩包,它是一个使用微软提供的 cabarc.exe 工具打好的安装包,使用cabarc.exe在打包的过程中,我们需要编辑一个inf文件,这个文件对压缩包中的文件进行了一些说明,指明了这些文件在用户下载之后下载到硬盘中的位置,以及文件的版本信息等内容,具体对于inf文件的介绍可以参考Packing ActiveX Controls 中对inf的介绍。下面给出一个参考inf文件:
[version]
signature="$CHICAGO$"
AdvancedINF=2.0
[Add.Code]
mainwindow.dll=mainwindow.dll
QtCore4.dll=QtCore4.dll
QtGui4.dll=QtGui4.dll
[mainwindow.dll]
file-win32-x86=thiscab
DestDir=11
clsid={F26FF23A-168E-43DB-A2C5-67242036D9AA}
FileVersion=1,0,0,0
RegisterServer=yes
[QtCore4.dll]
file-win32-x86=thiscab
DestDir=11
FileVersion=4,8,6,0
[QtGui4.dll]
file-win32-x86=thiscab
DestDir=11
FileVersion=4,8,6,0
可以简单介绍一下里面的信息:DestDir是指用户下载这些文件到硬盘的位置,这里面的11指的是Windows\System32类似这样的系统目录,thiscab表示该文件就位于该打包文件之内。AddCode 段会将所有该ActiveX文件依赖的dll列举出来。
当写好inf之后,我们就可以使用工具打包了,具体的命令如下:
当压缩完成之后,CODEBASE的地址需要指向这个安装包,也就是说用户可以输入CODEBASE中的链接地址下载到这个文件。
当配置完成之后就可以在客户端使用浏览器进行访问测试了,在实测过程中,IE可能会要求该控件的认证,这是因为ActiveX这种技术安全性的原因,微软会对开发者进行证书认证,正常情况下开发者需要去微软注册自己的证书,在ActiveX中添加这种证书,这样客户端在访问的过程中,IE浏览器给出提示,并告诉用户这一开发者开发的控件有着合规的证书,要求用户允许,在获得允许之后,控件便安装注册。
如果没有这一证书,可以让用户设置网站时信任站点,在IE设置中添加,如下图所示:
之后浏览器应该可以访问了。
在Qt的ActiveX文档示例中给出了一种方案,使用IObjectSafety进行设置,以期望绕开安全验证,我测试之后发现并没有预期的效果,但是有网友反馈是可行的,这里给出链接(在Qt Assitant中可以找到),读者可以自行测试 http://doc.qt.io/qt-4.8/qt-activeqt-opengl-example.html
另外几个关于ActiveX控件的问题:
(1)当ActiveX控件需要调用资源的时候我们应该如何处理?
最简单的想法应该是使用相对路径来访问资源,但是这并不可行,ActiveX中的相对位置在运行软件过程中并不能获取到资源的位置,处理方法是 获取到ActiveX控件在磁盘中的位置,可以通过ActiveX控件的位置得到资源的位置,代码可以参考下面(2)中的代码。
(2) 当ActiveX控件作国际化,里面需要访问翻译文件(.ts)文件的时候应该如何处理?
解决方案是:将正常的翻译文件载入方式放在ActiveX控件初始化的位置(一般来说可以放在构造函数中)即可,代码类似于下面这样:
CHAR ch[MAX_PATH];
CHAR longPath[MAX_PATH];
::GetModuleFileNameA(::GetModuleHandleA("MainWindow.dll"),ch,MAX_PATH); // 使用Windows API 获取到ActiveX控件在磁盘上的绝对路径
::GetLongPathNameA(ch,longPath,MAX_PATH);
_currentDir=QString::fromLocal8Bit(osgDB::getFilePath(longPath).c_str());
bool sus=_translator->load(_currentDir + QString("/MainWindow_zh.qm")); //通过ActiveX控件的位置得到相对位置的ts翻译文件编译的qm文件位置
QCoreApplication::installTranslator(_translator);