我正在开发一个剪贴板管理器(可以在这里看到:http://flamefusion.net/software/shapeshifter)。
但是,我目前遇到了位图(bmp)的问题,该位图不能正确地插入剪贴板。我的第一个方法是使用SetClipboardData,如下所示。
var hBitmap = bmp.GetHBitmap();
SetClipboardData(CF_BITMAP, hBitmap);我知道其中潜在的内存泄漏,这完全是作为一种测试。测试失败了。放入剪贴板中的图像在粘贴到剪贴板上时无法被油漆读取。
所以经过大量的研究和失败的尝试,我得到了一个新的理论。我使用的位图是从一个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很好地指出的那样,我的问题似乎是,我试图保存的图像实际上是一个DIB。现在问题已经改变了。我需要弄清楚如何从DIB转换成DDB。我知道在做这件事的同时,阿尔法损失,但它仍然是必要的。
编辑2使用Clipboard.SetImage是不可接受的。这在我的情况下行不通。我需要使用API。
发布于 2012-08-28 16:40:45
CF_BITMAP可能是与位图一起使用的错误格式。CF_BITMAP剪贴板格式指定了一个设备位图,但是现在几乎所有的位图都是DIBs --设备独立的位图。设备位图相对于系统/硬件设备调色板(考虑EGA图形),并且必须与当前显示模式的像素格式相匹配。DIBs携带自己的颜色信息,它们的像素格式与显示模式无关。
Docs说,如果应用程序在从剪贴板读取CF_BITMAP时请求CF_DIB,剪贴板管理器将将CF_DIB转换为CF_DIB,但这假定原始图像实际上是当前显示模式像素格式下的设备位图。如果不是,转换将产生垃圾,因为输入是垃圾。
再次尝试使用CF_DIB而不是CF_BITMAP。
发布于 2012-08-28 19:21:01
我觉得你搞得太复杂了。实际上根本不需要使用p/invoke --框架已经为您处理好了。你可以用一条线来完成这个任务:
Clipboard.SetImage(bmp);https://stackoverflow.com/questions/12162676
复制相似问题