彩票走势图

在 .NET Compact Framework 2.0 中宿主 ActiveX 控件(五)

翻译|其它|编辑:郝浩|2006-06-23 17:03:00.000|阅读 3636 次

概述:

# 慧都年终大促·界面/图表报表/文档/IDE等千款热门软控件火热促销中 >>

例如,.NET Compact Framework 2.0 版本不支持将接口指针数组封送回调用方(即 ISomeInterface[])。这种类型的参数在 IEnumxxx::Next 方法实现中相当常见,您可以在诸如 IEnumVariantIEnumConnectionPoint 这样的 COM 接口中找到这些方法实现。但如果您想查看对象浏览器,则会看到对于 System.Runtime.Interop.ComTypes.IEnumConnectionPoints 类,Next 方法的定义如下所示。


IEnumConnectionPoints.Next(int celt, IConnectionPoint[] rgelt, IntPtr pceltFetched)

遗憾的是,由于前面提到过的原因,该代码并不起作用(而且,将最后一个参数定义为 IntPtr 也很不方便)。相反,您需要重新定义接口,使该方法如下所示。

void Next (UInt32 cConnections, out IConnectionPoint rgpcn, out UInt32 lpcFetched )

虽然从技术角度讲,该代码不能等同于原始定义,但只要 cConnections 设置为 1,该代码也会很好地运行。显然,将其设置为任何大于 1 的值都会导致缓冲区溢出,使您的应用程序崩溃。

使用该方法,您可以定义自己的接口版本。对本例而言,它名为 IMyEnumConnectionPoint。请注意,对 System.Runtime.InteropServices.ComTypes.IConnectionPointContainer.EnumConnectionPoints() 方法的调用获得原始 IEnumConnectionPoint 接口的实例。那么如何获得 IMyEnumConnectionPoint 接口呢?您只需将 IEnumConnectionPoint 接口的实例转换为 IMyEnumConnectionPoint 接口。因为二者都声明为 ComImport,所以这种类型转换将不会使用 CLR 运行时类型检查,但是它们会导致调用 QueryInterface,这会成功地进行,因为两个接口具有相同的 GUID。

使用 TLBIMP.exe 导入接口定义

要自动提取接口定义,您应该使用 TLBIMP 工具。TLBIMP 包含在 .NET Framework SDK 中。当 COM 库(.dll、.ocx、.tlb)的引用添加到 .NET Compact Framework 项目时,也会自动调用它。当您处理设备项目时,ActiveX 控件通常打包在一个 .cab 文件中。当然,这种控件将针对 ARM CPU 进行编译,不能在桌面计算机上运行;幸运的是,也不必在桌面计算机上运行。类型库是独立于平台的,即使包含在 .dll 文件中时也如此 - 几乎是(在 64 位平台上不是这样)。因此,对 ARM ActiveX DLL 的引用可以像对待桌面计算机控件一样,以相同的方式添加到项目中。当然,不可能对其进行实例化或做任何其他事情,但这是另一码事了。

示例请查看 Macromedia (Adobe) 提供的 Shockwave Flash Player 控件。您可以免费该播放器。安装程序包括一个名为 ActiveX.cab 的 .cab 文件,默认情况下,它复制到 C:\Program Files\Microsoft ActiveSync\Macromedia\Flash Player 6 目录中。如果双击该 .cab 文件,您将看到两个文件。名为 000flash.001 的文件是 ActiveX 本身。解压缩该文件,将其重命名为 Flash.dll,然后将其添加为对您项目的引用。它将在列表中显示为 ShockwaveFlashObjects



如果查看类浏览器,您会看到现在拥有一个新的命名空间、类和接口定义,



解决对 CAB 或类型库的访问

有时,您不能享受到访问控件 CAB 的乐趣。例如,当开发人员意识到 Windows Media Player 10 Mobile 没有可重新分发的包时,宿主 Windows Media Player 控件这一最常见的请求将会遇到第一个麻烦。它仅可用作设备 ROM 的一部分。幸运的是,在 Windows Media Player 中,桌面计算机的类型库与设备的类型库是相同的,区别仅为 Windows Media Player Mobile 上的许多方法返回 E_NOTIMPL。幸运的是,设备版本不提供某些方法的完整实现,这对类型库没有影响;因此,您可以从桌面播放器导入类型库(位于 C:\Windows\System32\wmpcore.dll 中),并将其与设备 Media Player 一起使用。您仍需要仔细阅读 Windows Media Player SDK 文档,了解实际上可以使用的方法和属性。

如果您拥有一个类型库不可用的控件,则检查是否存在一个具有相同或相似接口的相同控件的桌面计算机版本。

遗憾的是,有时上述方法并不起作用。例如,如果您试图使用桌面计算机的 Web 浏览器控件 (SHDOCVW.DLL) 的类型库来宿主 Pocket PC Web 浏览器控件,您可能会失望;因为它们并不相同。所幸,有一种避开这种情况的方法。如果查看 Windows Mobile SDK,您将看到一个名为 webvw.idl 的文件,它包含 Web 浏览器控件的所有接口定义 - 这是个好消息。但坏消息是,它的大小为 50 KB,包含大约 1500 行代码。该控件对于手动转换为 C# 是不可行的。不过还是好消息更多一些:有一个从该文件创建类型库的省事的方法。

从 webvw.idl 文件创建一个类型库

 打开一个 Visual Studio 命令提示符。(如果运行的是 64 位平台,则确保它是 32 位命令提示符。)

浏览到 SDK Include 目录(默认情况下,它位于 C:\Program Files\Microsoft Visual Studio 8\SmartDevices\SDK\PocketPC2003\Include 中)。

运行以下命令:

midl /D UNDER_CE webwv.idl

MIDL 编译器编译 .idl 文件并生成另一个文件 webvw.tlb。您可能已经猜到,该文件可以导入到 Visual Studio 项目中。

这个巧妙的方法有一个局限。.idl 文件必须包含一个 library 部分,其中定义了一个 coclass。有时您可能没有该部分。在这种情况下,需要生成一个 library,如下示例代码所示。

import "OAIdl.Idl";
import "objidl.idl"; // Import any other .idl files you need [
    uuid(77777777-7777-7777-7777-777777777777),
    helpstring("Test library"),
    lcid(0x0000),
    version(1.0)
]
library TestLib
{
    [
        uuid(33333333-3333-3333-3333-333333333333),
        helpstring("Test class")
    ]
    coclass Test
    {
        [default] interface IEnumConnectionPoints;
          interface IConnectionPoint; // List any other interfaces that you are interested in };
}

生成一个如代码示例所示的文件。根据需要添加 import 指令和接口参数。如果包括了一个接口,并且其方法引用另一个接口,则该接口将自动包含在其中。在前面的示例中,添加 IEnumConnectionPoints 会导致包括 IConnectionPointIConnectionPointContainer 以及其他一些接口。

使用 AxImp.exe 生成一个完整的控件类定义

能够最终获益当然好 - 按照 Visual Studio 在桌面计算机窗体项目中处理的方式处理 ActiveX 控件。您只需向工具栏添加一个控件,方法是浏览到该控件或从注册组件列表中选择它。虽然 Visual Studio 设计器主动阻止任何将 ActiveX 控件添加到设备项目的企图,但您可以避免该限制。与前面描述的方法(将 TLBIMP 工具用作添加对类型库引用的命令行功能)类似,当将一个 ActiveX 控件放在窗体上时,可以使用 AXIMP 工具(也是 .NET Framework SDK 的一部分),该工具创建与 Visual Studio IDE 所创建的库相同的一组库。正如 TLBIMP 工具具有比集成开发环境 (IDE)(在导入类型库方面)更丰富的功能集一样,AXIMP 工具能够完成更多的任务。对于您的项目而言,最重要的是能够以其源格式产生 Interop 代码。如果运行以下命令行 AxImp.exe C:\WINDOWS\system32\wmp.dll /source,将产生三个文件:
    • AxWMPLib.cs
    •AxWMPLib.dll
    •WMPLib.dll

还有一个 .pdb 文件,但它现在已经不重要了。AxWmpLib.cs 是 Interop 库 AxWMPLib.dll 的源代码。仔细看一下,您会发现它定义了一个从 System.Windows.Forms.AxHost 派生的类 AxWindowsMediaPlayer。这 1663 行代码告诉明示了手动编写该代码是多么地令人不快。

您为什么想要源代码呢?如果您在 ILDAsm 工具中查看 AxWMPLib.dll,就会发现,它是针对 MSCORLIB 和 System.Windows.Forms 的桌面计算机版本编译的。显然,您不能使用 AXIMP 生成的 AxWMPLib.dll 版本。但是,您可以针对 .NET Compact Framework 库编译源代码文件,获得可以在设备上使用的程序集。

试图编译 Interop 库的源代码时,您会发现由于 MSCORLIB 和 System.Windows.Forms 的设备版本而导致产生了相当多的错误。幸运的是,您可以忽略所有这些缺失的引用,并用生成方法存根 (stub) 替换它们。您可以在本文的的 AxImpSupport.cs 模块中找到这些 stub。

使用 AXIMP 工具生成包装的好处是:快速、简单,并且可以创建一个具有完全事件和设计器支持的控件类。当然,其他两个方法也可以产生带有完全设计器支持的代码,但它们会需要大量的工作。

一些开发人员更喜欢将这样的类编译到一个单独的库中。因为不需要编写任何额外的代码,即使不熟悉 C# 的开发人员也可以构建此控件库。控件库构建完成后,您可以轻松地将其用于 Visual Basic .NET 项目中,如本文的所示。

设计器支持

因为 AxHost 类是从 Control 类派生的,所以 Visual Studio 设计器直接获得 AxHost 类,并将其显示为可以插入到您的项目窗体中。对于从 AxHost 类派生的类也如此。所有宿主的控件在设计器中均可自动使用,

此外,由于生成的 ActiveX 控件类通过 .NET Compact Framework 属性和事件公开了调度属性和事件接口,因此它们在设计器中也可用。您可以通过控件清单进一步自定义设计器中的控件外观,但这不属于本文的讨论范围。


Control 类派生 AxHost 类的一个意外结果是 AxHost 类也在设计器工具箱中显示。因为对开发人员而言,它作为一个独立的控件是没用的,所以您需要用以下内容向项目添加一个控件清单文件来阻止它。

<?xml version="1.0" encoding="utf-16"?>
<Classes xmlns="//schemas.microsoft.com/VisualStudio/2004/03/SmartDevices/XMTA.xsd">
    <Class Name="System.Windows.Forms.AxHost">
    <DesignTimeVisible>false</DesignTimeVisible>
    </Class>
</Classes>

需要改进的内容

总有一些内容可以改进。我们这些 OpenNETCF.org 的员工正计划将来添加或增强一些 AxHost 类功能。

下面列出一些不具备的功能:

键盘支持
尚未通过使用键盘的设备对该代码进行测试。我很肯定快捷键、焦点和按键处理存在一些问题。

无窗口激活
目前不支持该类型的激活。幸运的是,大部分支持无窗口激活的控件也支持窗口激活。

类似按钮和类似标签的控件
AxHost 类的当前版本很有可能不能正确地处理 OLEMISC 标志。利用诸如 Shockwave player 和 WMP 之类的控件,它实际上不是必需的,但我希望某些控件真正需要它。

激活和停用
大部分控件开发人员都对具有一个简单的生命周期感兴趣:创建,激活,显示,停用,销毁。一些控件可能还有更复杂的要求,如多个激活或停用。

如果您觉得此代码有用,请随时将您的意见和问题报告发送至 alexf@opennetcf.org

小结

您已经了解了通过使用 .NET Compact Framework 2.0 创建 ActiveX 控件的托管宿主这一过程。本文介绍了有关控件宿主的一些内容,并针对特别有用的 ActiveX 宿主对象,说明了一些问题和解决方案,并向您介绍了如何使用它以在您自己的应用程序中宿主控件。

此处说明的托管控件宿主框架由 提供。


标签:

本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@pclwef.cn


为你推荐

  • 推荐视频
  • 推荐活动
  • 推荐产品
  • 推荐文章
  • 慧都慧问
扫码咨询


添加微信 立即咨询

电话咨询

客服热线
023-68661681

TOP