用VB调用C#写的NET控件.docx

上传人:b****3 文档编号:2914104 上传时间:2022-11-16 格式:DOCX 页数:17 大小:166.57KB
下载 相关 举报
用VB调用C#写的NET控件.docx_第1页
第1页 / 共17页
用VB调用C#写的NET控件.docx_第2页
第2页 / 共17页
用VB调用C#写的NET控件.docx_第3页
第3页 / 共17页
用VB调用C#写的NET控件.docx_第4页
第4页 / 共17页
用VB调用C#写的NET控件.docx_第5页
第5页 / 共17页
点击查看更多>>
下载资源
资源描述

用VB调用C#写的NET控件.docx

《用VB调用C#写的NET控件.docx》由会员分享,可在线阅读,更多相关《用VB调用C#写的NET控件.docx(17页珍藏版)》请在冰豆网上搜索。

用VB调用C#写的NET控件.docx

用VB调用C#写的NET控件

 虽然IT开发技术日新月异,不过业界仍然运行着大量的VB系统,这些系统凝聚了不少客户的投资,应当要一定程度的保护和利用。

因此也就产生了一种需求,也就是使用旧的开发技术仍然可以使用新技术的产出。

本文就讨论如何在VB6.0开发中使用上WinForm.NET控件。

[袁永福版权所有]

 

二.软件原理:

  运行VBIDE,打开或创建一个EXE工程,打开窗体设计器,如下图所示:

 

  为了能在窗体上添加控件,需要往窗体左边的工具箱上添加项目,需要点击菜单项目“Project-Components”,此时会弹出如下图所示的对话框:

 

   点击“Browse”按钮,弹出文件选择对话框,这个对话框中优先选择OCX文件,而C#编译结果绝不可能是OCX文件的,此时即使选择一个.NET程序集DLL文件,无论如何必然会报错“ThisfilenotregisterableasanActiveXComponent”。

[袁永福版权所有]

  因此也就是说,使用C#开发的WinForm.NET控件是不可能直接通过传统的模式放置在VB窗体上。

  不过VB仍然可以通过COM方式调用.NET程序集中的对COM公开的类型。

此时就可以想出一种曲线实现方式,那就是VB创建C#组件,该组件是一个WinForm.NET控件,然后调用Win32APISetParent函数,将WinForm.NET控件硬塞入VB窗体中。

这样在用户界面上,用户能看到和使用WinForm.NET控件;在后台,VB代码能访问.NET组件提供的公开的属性、方法和事件,实现了VB全方位的调用WinForm.NET控件。

 

三.C#开发

C#控件开发

  根据上述的软件原理,笔者开发一个WinForm.NET控件并成功的应用于VB6.0的开发中,现对软件进行说明。

  这个WinForm.NET控件名为MyWinFormControl,派生自System.Windows.Forms.UserControl类型,它包含在一个名为DCWinFormControlLib的C#项目中,项目输出类型为类库,目标框架为.NET2.0,添加了对System.Windows.Forms.dll的引用。

界面设计:

MyWinFormControl控件的用户界面设计如下:

 

  在界面上放置一个名为“btnAction”的按钮,一个名为“myTextBox”的文本框。

定义公开属性和方法:

  打开该控件的C#代码文件,可以看到声明该类型的C#代码如下:

[System.Runtime.InteropServices.ComVisible(true)]

[System.Runtime.InteropServices.Guid("60550064-C97F-4306-A8B2-6908F50780E3")]

[System.Runtime.InteropServices.ComSourceInterfaces(typeof(IComMyEvent))]

publicpartialclassMyWinFormControl:

UserControl

{

}

  这段代码中,第一行代码的ComVisible标记类型为COM公开的;第二行代码Guid标记了类型在COM中的唯一编号;第三行代码的ComSourceInterfaces指明该类型实现了名为IComMyEvent的事件接口。

[袁永福版权所有]

  VB中无法直接绑定编译阶段未知的控件事件,同时也无法直接感应C#中的事件,为此需要编写一个接口通知VB存在若干事件,使得VB能绑定事件。

因此在此定义了IComMyEvent接口,声明了C#控件中的事件,IComMyEvent接口定义如下

usingSystem.Runtime.InteropServices;

[Guid("096EF9A6-24CB-4091-A18F-34DA38C9A6F1")]

[ComVisible(true)]

[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]

publicinterfaceIComMyEvent

{

///

///按钮按下事件

///

[DispId(12340)]

voidComButtonClick();

///

///文本内容修改事件t

///

[DispId(12350)]

voidComTextChanged();

}

 

///

///无参数无返回值委托类型

///

publicdelegatevoidVoidEventHandler();

而后在控件的C#代码中添加以下代码:

#region实现IComMyEvent中的成员

///

///按钮按下事件

///

publiceventVoidEventHandlerComButtonClick=null;

///

///文本内容修改事件

///

publiceventVoidEventHandlerComTextChanged=null;

#endregion

  这样C#中定义的事件在VB中就能绑定了,以下代码就是触发这些事件的:

privatevoidbtnAction_Click(objectsender,EventArgse)

{

if(ComButtonClick!

=null)

{

//触发ComButtonClick事件

ComButtonClick();

}

}

privatevoidmyTextBox_TextChanged(objectsender,EventArgse)

{

if(ComTextChanged!

=null)

{

//触发ComTextChanged事件

ComTextChanged();

}

}

  对控件实现了COM公开的事件后,就可以编写COM公开的属性和方法,其代码如下:

///

///公开的属性

///

publicstringUserText

{

get

{

returnmyTextBox.Text;

}

set

{

myTextBox.Text=value;

}

}

///

///公开的方法

///

publicdoubleCalcute(doublep)

{

returnMath.Sin(p);

}

  这个用户控件虽然能在VB代码中创建和访问,但还不能直接拖放到VB窗体上,此时还需要使用代码将C#控件添加到VB窗体上:

///

///将控件添加到指定句柄的窗体中

///

///指定的窗体句柄对象

///操作是否成功

publicboolAppendToContainerControl(intcontainerHandle)

{

CrossPlatformControlHostManagerman=newCrossPlatformControlHostManager();

man.ContainerHandle=newIntPtr(containerHandle);

man.ControlHandle=this.Handle;

man.Dock=this.Dock;

returnman.UpdateLayout();

}

  在这个函数中,参数为VB窗体中某个控件的句柄,该控件用于承载C#控件。

这段代码使用了笔者编写的一个CrossPlatformControlHostManager类型,该类型专业用于执行跨应用程序的控件承载,实现“乾坤大挪移”,该类型首先定义了几个属性:

[袁永福版权所有]

privateIntPtr_ControlHandle=IntPtr.Zero;

///

///操作的控件句柄对象

///

publicIntPtrControlHandle

{

get{return_ControlHandle;}

set{_ControlHandle=value;}

}

privateIntPtr_ContainerHandle=IntPtr.Zero;

///

///容器元素对象

///

publicIntPtrContainerHandle

{

get{return_ContainerHandle;}

set{_ContainerHandle=value;}

}

privateDockStyle_Dock=DockStyle.Fill;

///

///停靠样式

///

publicDockStyleDock

{

get{return_Dock;}

set{_Dock=value;}

}

 

此外还定义了一个方法,其代码如下:

///

///更新排版

///

///操作是否成功

publicboolUpdateLayout()

{

WindowInformationinfo=newWindowInformation(this.ControlHandle);

WindowInformationcontainer=newWindowInformation(this.ContainerHandle);

if(info.CheckHandle()==false

||container.CheckHandle()==false)

{

returnfalse;

}

if(info.ParentHandle!

=container.Handle)

{

if(info.SetParent(container.Handle)==false)

{

returnfalse;

}

}

RectangleclientRect=container.ClientBounds;

Rectanglebounds=info.Bounds;

RectangledescBounds=bounds;

switch(this.Dock)

{

caseDockStyle.Fill:

descBounds=clientRect;

break;

caseDockStyle.Bottom:

descBounds=newRectangle(

0,

clientRect.Height-bounds.Height,

clientRect.Width,

bound

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 医药卫生 > 基础医学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1