C# 是否将DIB转换为DDB?

C# 是否将DIB转换为DDB?,c#,pinvoke,gdi+,clipboard,gdi,C#,Pinvoke,Gdi+,Clipboard,Gdi,我正在开发一个剪贴板管理器(可以在这里看到:) 但是,我目前遇到位图(bmp)问题,该位图无法正确插入剪贴板。我的第一种方法是使用SetClipboardData var hBitmap = bmp.GetHBitmap(); SetClipboardData(CF_BITMAP, hBitmap); 我知道这里面有潜在的内存泄漏,这只是一个测试。测试失败了。粘贴到剪贴板中的图像时,Paint无法读取该图像 所以经过大量的研究和失败的尝试,我得到了一个新的理论。我使用的位图是从MemorySt

我正在开发一个剪贴板管理器(可以在这里看到:)

但是,我目前遇到位图(
bmp
)问题,该位图无法正确插入剪贴板。我的第一种方法是使用
SetClipboardData

var hBitmap = bmp.GetHBitmap();
SetClipboardData(CF_BITMAP, hBitmap);
我知道这里面有潜在的内存泄漏,这只是一个测试。测试失败了。粘贴到剪贴板中的图像时,Paint无法读取该图像

所以经过大量的研究和失败的尝试,我得到了一个新的理论。我使用的位图是从
MemoryStream
创建的,它是通过先前调用
bitmap.Save(Stream,ImageFormat)
方法创建的。这使我相信
System.Drawing.Bitmap
GetHBitmap
不是
SetClipboardData
函数所期望的那种
HBITMAP

所以我尝试了以下方法,取得了一定的成功

var memDC = CreateCompatibleDC(IntPtr.Zero);
var memBitmap = CreateCompatibleBitmap(memDC, bmp.Width, bmp.Height);
SetClipboardData(CF_BITMAP, memBitmap);
现在插入的图像尺寸正确,但为黑色图像。这是很明显的,因为除了宽度和高度之外,实际上没有任何来自
bmp
的东西被用于创建“兼容”位图

我假设我必须以某种方式使用BitBlt将我的原始位图复制到这个现在“兼容”的位图,但我不知道从哪里开始

你们这些GDI奇才知道吗?这里显然需要魔法

编辑1 正如dthorpe很好地指出的那样,我的问题似乎是我试图保存的图像实际上是DIB。现在问题变了。我需要弄清楚如何从DIB转换成DDB。我意识到阿尔法损失,而这样做的其他事情,但它仍然是必要的

编辑2
不能使用剪贴板.SetImage。这在我的场景中不起作用。我需要使用API。

CF\u位图可能是与位图一起使用的错误格式。CF_位图剪贴板格式指定了一个设备位图,但现在几乎所有位图都是DIBs-独立于设备的位图。设备位图与系统/硬件设备调色板(如EGA图形)相关,并且必须与当前显示模式的像素格式相匹配。DIB具有自己的颜色信息,其像素格式独立于显示模式

文档称,如果应用程序在从剪贴板读取时请求CF_DIB,剪贴板管理器将把CF_位图转换为CF_DIB,但这假定原始图像实际上是当前显示模式像素格式的设备位图。如果不是,转换将产生垃圾,因为输入是垃圾


请再次尝试使用CF_DIB而不是CF_位图。

我认为您将此问题复杂化了。实际上根本不需要p/invoke——框架已经为您处理了。您可以将其作为一行程序执行:

Clipboard.SetImage(bmp);

GetHBitmap()应该可以很好地处理剪贴板。您确定原始位图有效吗?您能在屏幕上显示原始位图(从内存流创建)吗?您不想转换为DDB。您希望
Bitmap.Save(Stream,ImageFormat.Bmp)
,然后使用
CF_DIB
将其放入剪贴板。这无法在绘图中显示。你能用你的代码来回答这个问题吗?我知道这一点,但它必须是CF_位图。我已经处理DIB,我也很清楚它们可以自动转换。我仍然需要它来处理CF_位图。您如何确保BITMAP.GetHBitmap()返回的位图句柄是设备位图?我很确定.net位图类在默认情况下构造DIB.Aha,所以GetHBitmap可以两者都是?我不知道。如果需要,我如何转换,以及如何检查它是否确实是设备位图?请参阅此处的最后一段:我上次使用Windows DDB已经20年了。我有点生疏了我需要使用PInvoke,因为.NET中的剪贴板有很多漏洞,正如许多其他帖子已经详细说明的那样。我觉得这有点难以置信。我也是。不需要太多的谷歌搜索就能找出人们需要绕过的所有黑客。我很好奇,你能给我指出一些漏洞吗。我从来没有遇到过问题。我想知道为什么不。@MathiasLykkegaardLorenzen-实际上,我也无法从Word->GetData问题(运行VS2010/CLR4)复制您的副本。剪贴板操作期间可能发生OutOfMemory异常(.NET或not)。