3

私はクリップボードマネージャーを開発しています(これはここで見ることができます:http://flamefusion.net/software/shapeshifter)。

ただし、現在bmp、クリップボードに正しく挿入されないビットマップ()で問題が発生しています。私の最初のアプローチは、を使用して次のとおりでしたSetClipboardData

var hBitmap = bmp.GetHBitmap();
SetClipboardData(CF_BITMAP, hBitmap);

これでメモリリークが発生する可能性があることを認識しており、これはテストとしてのみ作成されました。テストは失敗しました。クリップボードに挿入された画像は、貼り付け時にペイントで読み取ることができませんでした。

それで、たくさんの研究と失敗した試みの後で、私は新しい理論を得ました。私が使用しているビットマップは、メソッドMemoryStreamへの以前の呼び出しによって作成された、から作成されていますBitmap.Save(Stream, ImageFormat)System.Drawing.Bitmapこれにより、 'sは関数が期待するGetHBitmap種類ではないと私は信じるようにHBITMAPなります。SetClipboardData

そこで、次のことを試してみましたが、なんらかの成功を収めました。

var memDC = CreateCompatibleDC(IntPtr.Zero);
var memBitmap = CreateCompatibleBitmap(memDC, bmp.Width, bmp.Height);
SetClipboardData(CF_BITMAP, memBitmap);

これで、画像は正しいサイズで挿入されますが、黒い画像として挿入されます。そして、これは非常に明白です。なぜならbmp、幅と高さ以外に「互換性のある」ビットマップを作成するために実際に使用されるものは何もないからです。

元のビットマップをこの「互換性のある」ビットマップにコピーするには、なんらかの方法でBitBltを使用する必要があると思いますが、どこから始めればよいかわかりません。

GDIウィザードの誰かが知っていますか?ここでは明らかに魔法が必要です。

編集 1dthorpeがうまく指摘しているように、私の問題は、保存しようとしている画像が実際にはDIBであるということのようです。今、質問が変わりました。DIBからDDBに変換する方法を理解する必要があります。とりわけこれを行っている間、私はアルファ損失に気づいていますが、それでもそれは必要です。

編集2 を使用することはできませんClipboard.SetImage。これは私のシナリオでは機能しません。APIを使用する必要があります。

4

2 に答える 2

2

CF_BITMAP は、ビットマップで使用するのにおそらく間違った形式です。CF_BITMAP クリップボード形式はデバイス ビットマップを指定しますが、今日のほとんどすべてのビットマップは DIB (デバイスに依存しないビットマップ) です。デバイス ビットマップは、システム/ハードウェア デバイス パレット (EGA グラフィックスと考えてください) に相対的であり、現在の表示モードのピクセル形式と一致する必要があります。DIB は独自の色情報を持ち、そのピクセル形式は表示モードに依存しません。

ドキュメントによると、アプリケーションがクリップボードから読み取るときに CF_DIB を要求すると、クリップボード マネージャーは CF_BITMAP を CF_DIB に変換しますが、これは元の画像が実際には現在の表示モードのピクセル形式のデバイス ビットマップであることを前提としています。そうでない場合、入力がガベージであるため、変換によってガベージが生成されます。

CF_BITMAP の代わりに CF_DIB を使用して再試行してください。

于 2012-08-28T16:40:45.483 に答える
2

あなたはこれを過度に複雑にしていると思います。p/invoke はまったく必要ありません。フレームワークが既にこれを処理しています。これをワンライナーで行うことができます:

Clipboard.SetImage(bmp);
于 2012-08-28T19:21:01.173 に答える