翻譯|其它|編輯:郝浩|2006-06-23 17:03:00.000|閱讀 3645 次
概述:
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
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 會導致包括 IConnectionPoint、IConnectionPointContainer 以及其他一些接口。
使用 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="http://schemas.microsoft.com/VisualStudio/2004/03/SmartDevices/XMTA.xsd"> <Class Name="System.Windows.Forms.AxHost"> <DesignTimeVisible>false</DesignTimeVisible> </Class> </Classes>
總有一些內容可以改進。我們這些 OpenNETCF.org 的員工正計劃將來添加或增強一些 AxHost 類功能。
下面列出一些不具備的功能:
? |
鍵盤支持 |
? |
無窗口激活 |
? |
類似按鈕和類似標簽的控件 |
? |
激活和停用 |
如果您覺得此代碼有用,請隨時將您的意見和問題報告發送至 alexf@opennetcf.org。
您已經了解了通過使用 .NET Compact Framework 2.0 創建 ActiveX 控件的托管宿主這一過程。本文介紹了有關控件宿主的一些內容,并針對特別有用的 ActiveX 宿主對象,說明了一些問題和解決方案,并向您介紹了如何使用它以在您自己的應用程序中宿主控件。
此處說明的托管控件宿主框架由 提供。
本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@fc6vip.cn