C#でOLEサーバーを実装する方法

私が質問したいのは、

(1)Clipboardクラスを使ってクリップボードとやり取りする場合、 “Embed Source”と “MetaFilePict”ストリームに何を入れるべきですか?

(2)COMインタフェースIDataObjectを使ってクリップボードとやり取りする場合、 “Embed Source”と “MetaFilePict”のハンドルをどうすればいいですか?

(3)C#でOLEを実装するためのより良い方法(クライアントかサーバーのどちらかが私を助けてくれるでしょう)はありますか?

もっと詳しく

私はC#でOLEサーバーの実装を探しています(x86上で動作する外部Windows APIやその他のメソッドは、それらが1つのC#プロジェクトに含まれるのであれば、すべて問題ありません)。 MFCを含まないOLEの例は見付かりません。だから私は最初に少し試してみました。

私の最初のステップはそれらのデータをクリップボードに入れるために他のOLEサーバーが何をするのか見ることです。私は2つの方法でクリップボードと対話することを試みました:後で説明されるように私に3つのストリームを与えるNET Clipboardクラスと私にポインタを与えるOleGetClipboardによって返されたIDataObjectインターフェース。

私はOriginが3つのデータエントリーを入れることを発見しました:Object Descriptor、Embed SourceとMetaFilePict。彼らはストリームのようです。 3つのStreamからすべてのバイトを読み取り、それらを新しいDataObjectに戻して、そのDataObjectをクリップボードに再度配置すれば、元のオブジェクトをWordなどに貼り付けることができます。つまり、3つのStreamの内容は十分です。貼り付けるOLEコンテナ用。

私がさらに見つけたのは、Object Descriptorがデータクラスといくつかの名前のguidを持つOBJECTDESCRIPTOR構造体を含み、オブジェクトをインスタンス化してそれをIOLEObjectに変換することができるということです。しかし、他の2つのストリーム、Embed SourceとMetaFilePictに何が含まれるべきかわかりません。私の理解したところでは、埋め込みソースはそれを作成した後にIOLEObjectに(おそらくInitFromDataによって)渡されるデータを含むべきですが、私はそうすることに成功しませんでした。そしてMetaFilePictを言い換えると、このエントリがないと、他の2つは適切に動作できないようです(Object DescriptorとEmbed Sourceのみが存在する場合、Wordで貼り付けると何もできません)。しかし、繰り返しますが、その内容はわかりません。それはASCII文字列(私の場合は “CPYA 4.2878 724#”)で始まり、WMFファイルのようには見えません。

System.Runtime.InteropServices.ComTypesまたはMicrosoft.VisualStudio.OLE.Interop名前空間のいずれかでCOMオブジェクトIDataObjectを使用すると、そこからHMETAFILEPICTを取得できますが、ハンドルの使用方法がわかりません。 PlayMetaFileは動作しません。

編集

MFCでは、この例ではOleCreateFromDataを使用してクリップボードから取得したIDataObjectから直接オブジェクトを作成します。これはC#でも機能するはずです。しかし、これはクライアントの実装にすぎません。私はどうやってサーバーを実装するかを見つけようとします。

ベストアンサー
私の質問がなぜ下方投票されたのかわかりません。実際、私はインターネット上で同じような質問をする多くのスレッドを見つけることができますが、それらのどれも完全な答えで終わることはありません。これは残念です。

最後に、MFCのサンプルコードを見て、自分で答えを見つけます。 OLEは、特にMFCなしで​​は、新しい人にとっては習得が困難です。何を詳細にすべきかをあなたに言うことができる人は誰もいません。

まず、両方の方法が同じように機能するはずです。 “Object Descriptor”の場合、HGlobalは単なるメモリブロックで、OBJECTDESCRIPTOR構造体を含んでいます。 “Embed Source”の場合、IStorageは通常ILockBytesを使って作成されます。ILockBytesにはメモリブロックがあります。問題はそれにどんな種類のデータがあるのか​​ということです。実際にはブロック上にはOLE複合ファイルと呼ばれるフォーマットがあります。これには2つの情報が含まれています:guidとIOLEObjectの初期化に使用されるデータです。実際にはIOLEObjectを作成するために使用されるものであるため、guidは非常に重要です。 “Object Descriptor”のGUIDは、[特殊貼り付け]ダイアログを表示するためだけに使用されています。 GUIDはWriteClassStg API関数を使用してIStorageに追加できます。 IStorageに含まれるデータの他の部分は通常 “Contents”と呼ばれる単一のストリームです(少なくともこれは私が持っているMFCの例の実装です)。

結論として、ペーストを準備するために私がしなければならないことは以下のとおりです。

> IOLEObject、IDataObject、IPersistStorage、およびIViewObjectを実装するOLEObjectクラスを用意します(IViewObjectについてはよくわかりません)。
> IDataObjectを実装するDataObjectクラスを用意します(1のオブジェクトと同じことを行いますが、IDataObjectインターフェースのみ)。
> 2つのオブジェクトのIDataObjectの実装では、少なくとも “Object Descriptor”、 “Embed Source”、および “MetaFilePict”のデータが必要です。 MetaFileはConvert an image into WMF with .NET?で提供されている方法で作成できます。
>クラスがCOMからアクセスでき、正しく登録されていることを確認してください。 https://limbioliong.wordpress.com/2011/08/30/creating-a-com-server-using-c/
>コピーを実行するときは、StgCreateDocfileでIStorageを構築し、WriteClassStgを使用してOLEObjectのGUIDを設定し、その中にOLEObjectに必要なその他のデータを書き込みます。
> DataObjectクラスを構築し、それを「埋め込みソース」としてIStorageに提供します。
> OleSetClipboardを使用してDataObjectをクリップボードに設定します。

MFCがOLEObjectが作成されるのを許可するIClassFactoryを登録するようです。 C#でこれを実現する方法がわかりません。

OLEの詳細を探す他の人が簡単に見つけられるように、終了後にここにコードを追加します。

(やや)実用的な例:https://github.com/acaly/SharpOle

転載記事の出典を記入してください: C#でOLEサーバーを実装する方法 - コードログ