C#下OCX控件的完美使用
在上一篇C#下COM组件调用篇中,我当时没有把OCX的使用方法说清楚,主要原因是我那时有一个核心问题没有解决好,后来在CodeProject中看到一篇文章,一下解开了心中多年的疑惑,豁然开朗。在这里分享一下最新的研究成果。
OCX使用的关键问题点
其实OCX使用中,有两个关键点需要解决:
- 1、如何获取到AxInterop文件
- 2、Visual Studio 设计Form时,可以在工具箱位置找到OCX控件,且使用我们自己的Axinterop。
只要大家亲身使用过OCX控件就会有体会,以前我都是直接在工具箱里面点击添加项,然后选COM页签,找到我想要的控件,最后选中确认。此时VS会进行一连串的TlbImp和AxImp操作,然后给你自动生成一大堆的Interop和AxInterop,简直是自动的不要不要的。但是以前文章中说过的COM Interop 拖家带口问题和ADODB问题,会造成你的项目引用非常混乱,2008系统会各种报错。
加之U8的COM组件和OCX控件引用关键错终复杂,搞得我最后一听说要画控件在Form上就恶心。我也在网络上找了很多资料,不管是国内的还是国外的论坛,基本回答都是手工使用AxImp加上rcw参数,解决引用问题。然后都不说怎么在VS的工具箱里增加控件。后来我测试发现,rcw参数也解决不了ADODB错误。我也就没有在深入研究下去。有兴趣的可以看看我之前的文章,rcw参数和TlbImp的reference参数差不多。
OCX止吐关键技术
AxInterop引用关系解决
第一个问题,AxInterop引用错误问题,还是建议使用IL工具进行编译修改。如果不会或者不明白看我之前的COM使用技巧第二章。换言之,我们必须先得到一个已经解决了引用关系的Axinterop。
VS工具箱引用解决
VS工具箱引用问题,其实并不难,这里仅仅需要使用到AxImp工具的一个参数,直接给大家看一下命令行
C:\ax>aximp /source "c:\u8soft\ufcomsql\vsflex8u.ocx"
生成的源: C:\ax\AxVSFlex8U.cs
生成的程序集: C:\ax\VSFlex8U.dll
生成的程序集: C:\ax\AxVSFlex8U.dll
简单说,我们这里利用aximp的一个叫做srource的参数,搞出来一个C#版本的源码文件,引入项目,并通过修改这个文件的代码就可以让控件显示在工具箱里面了。
这里有一点,需格外强调一下,我们虽然这里使用了aximp,但是他生成的其他文件我们都不用,比如后面两个DLL文件,或者说,就唯独使用那个cs源码文件。下面看看这个刚刚生成出来的CS文件,热乎的时候是什么样子,记住此时他是不正确的,需要进行下一步修改才可以。
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行时版本:4.0.30319.42000
//
// 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------
[assembly: System.Reflection.AssemblyVersion("1.0.0.0")]
[assembly: System.Windows.Forms.AxHost.TypeLibraryTimeStamp("09/30/2011 10:57:06")]
namespace AxVSFlex8U {
[System.Windows.Forms.AxHost.ClsidAttribute("{3705b4e2-8fcb-4a21-8cce-5d6a98c32456}")]
[System.ComponentModel.DesignTimeVisibleAttribute(true)]
[System.ComponentModel.DefaultEvent("SelChange")]
[System.ComponentModel.DefaultProperty("Text")]
public class AxVSFlexGrid : System.Windows.Forms.AxHost {
private VSFlex8U.IVSFlexGrid ocx;
private AxVSFlexGridEventMulticaster eventMulticaster;
private System.Windows.Forms.AxHost.ConnectionPointCookie cookie;
private msdatasrc.DataSource axDataSource;
public AxVSFlexGrid() :
base("3705b4e2-8fcb-4a21-8cce-5d6a98c32456") {
this.SetAboutBoxDelegate(new AboutBoxDelegate(About));
}
\'后面代码一律省略,毛用没有,没必要看!!!
代码修改1
注意看这个文件的几个地方,第一个就是版本号,在上文的11行
[assembly: System.Reflection.AssemblyVersion("1.0.0.0")]
这行代码必须删除,放在这里就是报错用的。
代码修改2
namespace AxVSFlex8U {
命名空间必须修改成你的项目中的命名空间
代码修改3
\'必须增加ToolboxItem参数
[System.ComponentModel.ToolboxItem(true)]
public class AxVSFlexGrid : System.Windows.Forms.AxHost {
这个非常非常重要,就因为有了这个才真正让VS识别出来是控件类。
代码修改4
最后添加 MSACAL.dll 和 Stdole.dll 两个引用,一般情况下VS会提示你的。
最后我们看一下完美解决后的文件
\'删除垃圾代码
[assembly: System.Windows.Forms.AxHost.TypeLibraryTimeStamp("09/30/2011 10:57:06")]
namespace WindowsFormsApp1 \'命名空间修改
{
[System.Windows.Forms.AxHost.ClsidAttribute("{3705b4e2-8fcb-4a21-8cce-5d6a98c32456}")]
[System.ComponentModel.DesignTimeVisibleAttribute(true)]
[System.ComponentModel.DefaultEvent("SelChange")]
[System.ComponentModel.DefaultProperty("Text")]
[System.ComponentModel.ToolboxItem(true)] \'属性增加
public class AxVSFlexGrid : System.Windows.Forms.AxHost {
然后试着编译一下程序,用X86编译你的项目,64的编译后不能拖拽控件,去设计一下窗体,看看工具箱里面是不是出现了一个叫做AxVSFlexGrid的控件了,然后拖拽控件进入Form,版权提示后,就有一个美丽的控件嵌入Form中了。是不是很神奇!
劳动成果的复用
到此OCX问题完美解决了。如果你想让劳动成果最大化复用,并为后期的项目使用,完全可以把这个项目编译成类库,然后供给其他项目引用。我测试后发现是好用的,关键点在于需要到工具箱里面增加引用,如图
然后就可以正常拖拽控件进入Form了,使用过程非常简单,记住你的项目必须X86。
也就是说如果你愿意,可以把所有常用的控件都封装到一个DLL中,然后引用后直接使用,这操作简直666,比VB6引用控件方便太多了。
大家有任何问题,可以在博客中留言,我会在平时进行回复。
请发表评论