0

我试图在不安全的上下文中使用位图,并且看到其中不稳定,例如,程序第一次运行但第二次失败。这是代码:

private static void RenderBitmap(Graphics g)
{
  const int width = 150, height = 150;
  using (Bitmap bmp = new Bitmap(width, height, 
    System.Drawing.Imaging.PixelFormat.Format24bppRgb))
  {
    Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
    System.Drawing.Imaging.BitmapData bmpData =
      bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, 
        bmp.PixelFormat);
    NativeMethods.RenderText(Graphics.FromImage(bmp).GetHdc(), bmpData.Scan0,
      "This works only first time round", "Segoe", 10, 
      new RGBA(255, 0, 0, 255), width, height);
    bmp.UnlockBits(bmpData);
    g.DrawImage(bmp, new Rectangle(width, height, width, -height));
  }
}

看到这不起作用,我有几个问题。RenderText如果本机方法直接操作位图内存,我正在做的事情是否安全且正确?我HDC从位图获取的方式是否正确,还是应该使用g从绘图方法传递的参数?

我得到的错误是:

" System.AccessViolationException 未处理 Message="尝试读取或写入受保护的内存。这通常表明其他内存已损坏。"

4

3 回答 3

3

NativeMethods.RenderRext方法不能安全地处理位图数据,因为它不知道位图的扫描线有多宽,也不知道它是否倒置存储在内存中。这些症状表明该方法正在写入位图之外的内存,覆盖了您在应用程序中需要的其他内容。

BitmapData.Stride属性具有该方法处理数据所需的信息。它包含以字节为单位的扫描线宽度,如果它为负数,则表示位图倒置存储在内存中。简单来说Scan0就是第一条扫描线的地址,Scan0+Stride就是第二条扫描线的地址。

于 2009-04-03T19:14:36.137 回答
1

好吧,在经历了很多痛苦和折磨之后,我找到了一个解决方案:我没有传递一个要填充的内存缓冲区,而是传递了一个设备上下文(HDC)来渲染。到目前为止似乎工作!

感谢所有回答的人。

于 2009-04-03T20:12:12.953 回答
1

也许这是一个愚蠢的问题,但是为什么不使用 .NET 附带的 TextRenderer 类而不是使用 p/invoke 呢?

TextRenderer::DrawText Method (IDeviceContext, String, Font, Point, Color)

http://msdn.microsoft.com/en-us/library/4ftkekek.aspx

-Oisin

于 2009-04-03T19:14:16.587 回答