OCX的正确使用姿势是在网页上使用,那么如果第三方只提供了OCX,我们在WPF程序中该如何调用呢?本文就来探讨该问题。
一、从OCX生成dll
按照《WPF 引用 OCX 控件 – CSDN 博客》的方法来:
1、先注册 OCX 控件;(有的把 OCX 控件封装到 EXE 文件中,安装即可);
2、打开 vs,新建一个 winform 程序,在工具箱中添加 COM 组件(把刚才注册的 OCX 控件)引用进来,这时就会看到当前 winform 程序 Debug 目录下会多出 2 个 DLL;
3、打开 vs,新建一个 WPF 程序,把上面的 2 个 DLL 引用上就可以了。
比如,我有一个 “TZ_SignMainDevOcx.ocx” 组件,经过以上方法,可得到以下两个文件:”AxInterop.TZ_SignMainDevOcxLib.dll” 和 “Interop.TZ_SignMainDevOcxLib.dll”。
二、添加到WPF项目中
我们要引用的是”AxInterop.TZ_SignMainDevOcxLib.dll”,”Interop.TZ_SignMainDevOcxLib.dll”是它的依赖项:
换言之,我们需要的方法都在带 “AxInterop” 前缀的dll中,而带 “Interop” 前缀的则是其依赖项。从图中还可以看出,实际要使用的类是在原OCX中的类前加上了 “Ax” 前缀。
三、MVVM方式调用
1、Xaml 添加一个隐藏的占位:
<ContentControl Grid.Row="1" Content="{Binding OcxContent}" Visibility="Collapsed"/>
2、ViewModel 中(使用AxTZ_SignMainDevOcx类):
// 绑定的对象 private object _ocxContent; public object OcxContent { get => _ocxContent; set => SetProperty(ref _ocxContent, value); } // 。。。 // 在主线程中实例化 com 组件 var axtz = new AxTZ_SignMainDevOcx(); // WPF 承载 windows 组件 System.Windows.Forms.Integration.WindowsFormsHost host = new System.Windows.Forms.Integration.WindowsFormsHost(); host.Child = axtz; // 除了实例化 com 组件,还要将该对象进行初始化 ((System.ComponentModel.ISupportInitialize)axtz).BeginInit(); OcxContent = new StackPanel { Children = { host} }; ((System.ComponentModel.ISupportInitialize)axtz).EndInit(); // 调用 int ret = axtz.TZ_QrCodePrinter(0, "USB001", 0, 0, 5, info.barCode);
关键一点就是,除了要实例化相关对象,还要对其进行初始化。所以,如果是在Winform中使用,只要在 BeginInit 和 EndInit 之间,将实例化出的控件对象添加到界面中即可。
这里展示的是WPF的情况:
(1)要在主线程实例化相关对象,参见《当前线程不在单线程单元中, 因此无法实例化 ActiveX 控件的解决方案》
(2)WPF 承载 windows 组件必须用 WindowsFormsHost(需引用WindowsFormslntegration),参见《WPF 中实例化 Com 组件,调用组件的方法时报 System.Windows.Forms.AxHost+InvalidActiveXStateException 的异常》
(3)添加控件的方法我采用了MVVM的方式:Xaml中内容控件 ContentControl 的内容绑定了一个对象,然后新建一个StackPanel(或其它合适的容器)赋值给它,并将com组件的宿主(host)放在其中(赋值给Children),以此来完成初始化。
3、最后,就可以像调用普通方法一样调用了。
原创文章,转载请注明: 转载自 独立观察员(dlgcy.com)
本文链接地址: [在WPF的MVVM模式中使用OCX组件](https://dlgcy.com/wpf-mvvm-ocx/)
关注微信公众号 独立观察员博客(DLGCY_BLOG) 第一时间获取最新文章
发表评论