我想问的问题是:
(1)如果我通过剪贴板类与剪贴板交互,那么在“嵌入源”和"MetaFilePict“流中应该是什么?
(2)如果通过COM接口IDataObject与剪贴板交互,应该如何处理“嵌入源”和"MetaFilePict“中的句柄?
(3)是否有更好的方法在C#中实现OLE (客户机或服务器将帮助我)?
详细信息:
我正在C#中寻找OLE服务器的实现(extern和其他在x86上工作的方法对我来说都是可以的,只要它们可以在一个C#项目中)。我找不到不涉及MFC的OLE示例。所以我先试了一下。
我的第一步是看看其他OLE服务器做什么,以便将它们的数据放入剪贴板。我尝试了两种方法来与剪贴板进行交互: NET剪贴板类,它给我提供了后面描述的三个流,以及OleGetClipboard返回的OleGetClipboard接口,它为我提供了指针。
我发现原点放置了三个数据条目:对象描述符、嵌入源和MetaFilePict。他们似乎是溪流。如果我从这三个流中读取所有字节,将它们放回一个新的DataObject中,并再次将DataObject放到剪贴板上,我就能够将原始对象粘贴到例如Word中,这意味着这三个流的内容足够一个OLE容器粘贴。
我进一步发现,对象描述符包含带有数据类guid和一些名称的OBJECTDESCRIPTOR结构,并且能够实例化该对象并将其转换为IOLEObject。但是我不知道另外两个流,即Embed和MetaFilePict应该是什么。据我所知,Embed应该包含在创建IOLEObject (可能是通过InitFromData)之后传递给它的数据,但我没有成功。再加上MetaFilePict,似乎没有这个条目,其他两个就不能正常工作了(如果只有对象描述符和嵌入源存在,Word中的粘贴就什么都没有了)。但我还是不知道里面是什么。它似乎以一个ASCII字符串开始(在我的例子中它是"CPYA 4.2878 724#"),并且看起来不像WMF文件。
如果我使用COM对象IDataObject (无论是在System.Runtime.InteropServices.ComTypes还是Microsoft.VisualStudio.OLE.Interop名称空间中),我可以从它获得HMETAFILEPICT,但是我不知道如何使用句柄。PlayMetaFile对此不起作用。
编辑
在MFC中,示例使用OleCreateFromData直接从剪贴板获取的IDataObject创建对象。这也应该适用于C#。但这只是客户端的实现。我将尝试了解如何实现服务器。
发布于 2016-12-03 07:52:59
我不知道为什么我的问题被否决了。实际上,我可以在互联网上找到很多问类似问题的帖子,但没有一条得到完整的答案。这太可惜了。
最后,通过MFC示例代码,我自己找到了答案。对于一个新人来说,OLE真的很难学习,尤其是没有MFC的时候。没有人能详细地告诉你该怎么做。
首先,这两种方法都应该以相同的方式工作。对于“对象描述符”,HGlobal只是一个内存块,它只包含OBJECTDESCRIPTOR结构。对于“嵌入源”,IStorage通常是用ILockBytes创建的,它只有一个内存块。问题是它上有什么样的数据。实际上,块上有一种名为OLE复合文件的格式。它包含两部分信息:用于初始化IOLEObject的guid和数据。guid非常重要,因为它实际上是用来创建IOLEObject的。“对象描述符”中的GUID仅用于显示特殊粘贴对话框。GUID可以通过IStorage API函数添加到WriteClassStg中。IStorage中包含的数据的其他部分通常是一个名为“Content”的流(至少这是MFC示例的实现)。
最后,我要做的是准备粘贴:
似乎MFC注册了一个允许创建IClassFactory的OLEObject。我不知道如何在C#中实现这一点。
在完成之后,我将在这里添加一些代码,以便其他寻找OLE细节的人能够轻松找到它。
一个(勉强)工作的例子:https://github.com/acaly/SharpOle
https://stackoverflow.com/questions/40901712
复制相似问题