【问题标题】:Convert DIB to DDB?将DIB转换为DDB?
【发布时间】:2012-08-23 03:54:15
【问题描述】:

我正在开发一个剪贴板管理器(可以在这里看到:http://flamefusion.net/software/shapeshifter)。

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

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

我知道其中存在潜在的内存泄漏,这只是作为测试。测试失败。粘贴到剪贴板中的图像在粘贴时无法被 Paint 读取。

所以经过大量的研究和失败的尝试,我得到了一个新的理论。我使用的位图是从MemoryStream 创建的,它是通过先前调用Bitmap.Save(Stream, ImageFormat) 方法创建的。这让我相信System.Drawing.BitmapGetHBitmap 不是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。我知道在执行此操作时会导致 alpha 损失,但仍然需要它。

编辑 2 使用Clipboard.SetImage 是不可接受的。这在我的场景中不起作用。我需要使用 API。

【问题讨论】:

  • GetHBitmap() 应该可以在剪贴板中正常工作。您确定原始位图有效吗?你能在屏幕上显示原始位图(从内存流创建)吗?
  • 您不想转换为 DDB。你想Bitmap.Save(Stream, ImageFormat.Bmp),然后用CF_DIB把它放到剪贴板中。
  • 无法在 Paint 中显示。你能用实际证明它有效的代码来回答吗?

标签: c# pinvoke gdi+ clipboard gdi


【解决方案1】:

CF_BITMAP 可能是与您的位图一起使用的错误格式。 CF_BITMAP 剪贴板格式指定设备位图,但如今几乎所有位图都是 DIB - 设备独立位图。设备位图与系统/硬件设备调色板相关(想想 EGA 图形),并且必须匹配当前显示模式的像素格式。 DIB 带有自己的颜色信息,其像素格式与显示模式无关。

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

使用 CF_DIB 而不是 CF_BITMAP 重试。

【讨论】:

  • 我知道这一点,但它必须是 CF_BITMAP。我已经处理过 DIB,而且我也很清楚它们可以自动转换。我仍然需要它来使用 CF_BITMAP。
  • 你在做什么来确保bitmap.GetHBitmap()返回的位图句柄是设备位图?我很确定 .net Bitmap 类默认构造 DIB。
  • 啊哈,那么 GetHBitmap 可以两者兼得?我不知道。如果需要,如何转换,如何检查它是否确实是设备位图?
  • 距离我上次使用 Windows DDB 已经 20 年了。我有点生疏了。 ;>
【解决方案2】:

我认为你过于复杂了。根本不需要 p/invoke —— 框架已经为你处理好了。您可以单线执行此操作:

Clipboard.SetImage(bmp);

【讨论】:

  • 我需要使用 PInvoke,因为 .NET 中的剪贴板非常有问题,正如许多其他帖子已经详细介绍的那样。
  • 嗯,我觉得这有点难以置信。
  • 我也是。无需太多谷歌搜索即可找出人们解决问题所需的所有技巧。
  • 我很好奇,您能否指出其中的一些错误。我从来没有遇到过问题。我想知道为什么不。
  • @MathiasLykkegaardLorenzen - 实际上,我也无法重现您的 Copy From Word -> GetData 问题(运行 VS2010/CLR4)。剪贴板操作期间发生 OutOfMemory 异常可能发生(.NET 与否)。
猜你喜欢
  • 1970-01-01
  • 2012-06-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多