2016-12-01 67 views
2

我要问的问题是:如何实现OLE服务器在C#

(1)如果我通过剪贴板类剪贴板互动,应该是“嵌入源”和“METAFILEPICT”流呢? (2)如果我通过COM接口IDataObject与剪贴板交互,我应该如何处理“Embed Source”和“MetaFilePict”中的句柄? (3)是否有更好的方法在C#中实现OLE(客户端或服务器将帮助我)?

更多细节:

我寻求OLE服务器在C#(EXTERN的Windows API和其他方法的实现,在x86工作对我来说都可以,只要他们可以在一个C#项目)。我无法找到任何不涉及MFC的OLE示例。所以我先试了一下。

我的第一步是看看其他OLE服务器为了将他们的数据放到剪贴板中所做的事情。我已经尝试了2种方法与剪贴板交互:NET Clipboard类,它给了我三个Streams(后面将介绍),以及OleGetClipboard返回的IDataObject接口,它给了我指针。

我发现Origin提供了三个数据条目:对象描述符,嵌入源和MetaFilePict。他们似乎是流。如果我从三个Stream中读取所有字节,将它们放回到一个新的DataObject并将DataObject重新放到剪贴板中,我可以将原始对象粘贴到Word中,这意味着三个Streams的内容足够用于粘贴一个OLE容器。

我发现更进一步的是对象描述符包含带有数据类和一些名称的GUID的OBJECTDESCRIPTOR结构,并且我能够实例化对象并将其转换为IOLEObject。但我不知道其他两个流中应该是什么,Embed Source和MetaFilePict。根据我的理解,Embed Source应该包含在创建它之后传递给IOLEObject(可能由InitFromData)的数据,但我没有成功。并且重新编写MetaFilePict,看起来如果没有这个条目,其他两个就不能正常工作(如果只有对象描述符和嵌入源存在,在Word中粘贴最终不会有任何结果)。但是,我不知道它里面有什么。它似乎开始于一个ASCII字符串(在我的情况下它是“CPYA 4.2878 724#”),看起来不像WMF文件。

如果我使用COM对象IDataObject(在System.Runtime.InteropServices.ComTypes或Microsoft.VisualStudio.OLE.Interop命名空间中),我可以从它获取HMETAFILEPICT,但我不知道如何使用该句柄。 PlayMetaFile不起作用。

EDIT

在MFC,该示例使用OleCreateFromData直接创建对象从IDataObject的从剪贴板得到。这也应该在C#中工作。但这只是客户端的实现。我将尝试了解如何实现服务器。

回答

3

我不知道为什么我的问题被拒绝投票。实际上,我可以在互联网上找到许多线索,要求提供类似的问题,但没有一个以完整答案结束。这是一个耻辱。

最后我通过查看MFC示例代码后自己找到答案。对于一个新人来说,OLE真的很难学,特别是没有MFC。根本没有人可以告诉你详细做什么。

首先,这两种方法应该以相同的方式工作。对于“对象描述符”,HGlobal只是一个内存块,它只包含OBJECTDESCRIPTOR结构。对于“Embed Source”,IStorage通常是用ILockBytes创建的,它只有一个内存块。问题是它上面有什么样的数据。实际上块是一种叫做OLE复合文件的格式。它包含两部分信息:一个guid和用于初始化IOLEObject的数据。 guid非常重要,因为它实际上是用来创建IOLEObject的。 “对象描述符”中的GUID仅用于显示特殊粘贴对话框。可以使用WriteClassStg API函数将GUID添加到IStorage中。包含在IStorage中的其他部分数据通常是一个名为“内容”的单一流(至少这是我实例的MFC示例)。

总之,我有什么做的糊状准备是:

  1. 有一个实现的IOleObject,IDataObject的,IPersistStorage和IViewObject(不太清楚有关IViewObject)一个OLEOBJECT类。
  2. 有一个实现IDataObject的DataObject类(与1中的对象相同,但只有IDataObject接口)。
  3. 在2个对象的IDataObject实现中,至少有类型为“Object Descriptor”,“Embed Source”和“MetaFilePict”的数据。 MetaFile可以通过Convert an image into WMF with .NET?中提供的方法创建。
  4. 确保COM可以访问这些类并正确注册。 https://limbioliong.wordpress.com/2011/08/30/creating-a-com-server-using-c/
  5. 执行复制时,通过StgCreateDocfile构造一个IStorage,用WriteClassStg设置OLEObject的GUID,并在其中写入OLEObject所需的其他数据。
  6. 构建DataObject类并将其作为“嵌入源”提供给IStorage。
  7. 使用OleSetClipboard将DataObject设置为剪贴板。

看来,MFC注册一个IClassFactory,允许创建OLEObject。我不知道如何在C#中实现这一点。

我会在完成后添加一些代码,以便查找OLE详细信息的其他人可以轻松找到它。

A(勉强)工作示例:https://github.com/acaly/SharpOle

+1

一直在寻找了几个小时找到如何做到这一点的好例子。真的很好的小演示应用程序。谢谢。 – Matt

+0

吴振伟不担心降价,有的用户只有在对这个话题不感兴趣时​​才会轻易退缩,同样的用户在没有调研的情况下也可以轻松提出真正不好的问题。希望这个社区更加友好和正确。 – JHG