2

我有一个使用 Aero 玻璃效果的应用程序,因此除了红色、绿色和蓝色值之外,每个像素都有一个 alpha 值。我有一个具有纯白色背景(alpha = 255)的自定义绘制控件。我想使用 GDI 文本函数在控件上绘制纯文本。但是,这些函数将 alpha 值设置为任意值,导致文本半透明地显示我的应用程序下方的任何窗口。

在调用渲染文本之后,我想遍历控件中的所有像素并将它们的 alpha 值设置回 255。最好的方法是什么?

BitBlt我对,GetPixelSetPixel函数没有任何运气。他们似乎没有注意到 alpha 值。

以下是我考虑并拒绝的其他解决方案:

  • 绘制到位图,然后将位图复制到设备:使用这种方法,文本呈现不会利用监视器的特性(例如,ClearText)。如果您知道一种让 GDI 将文本呈现到位图的方法,就像它呈现到屏幕上一样,那也可以解决我的问题。
  • 使用 GDI+ 进行文本渲染:这个应用程序最初使用 GDI+ 进行文本渲染(在我开始从事 Aero 支持工作之前)。由于在尝试使用 GDI+ 准确测量字符串时遇到困难,我转而使用 GDI。我宁愿不换回来。
  • 设置 Aero 区域以避免有问题的控件:我的应用程序的窗口实际上是在不同进程中运行的不同应用程序的子窗口。我无法直接控制顶级窗口中的 Aero 设置。

该应用程序是使用 Windows 窗体用 C# 编写的,尽管我不喜欢使用 Interop 调用 Win32 API 函数。

4

2 回答 2

1

下面是我最终想出的解决方案。这有点丑陋,可能会被简化,但它确实有效。这个想法是基于原始的Graphics 对象(即屏幕)创建一个BufferedGraphics 对象。在 BufferedGraphics 对象中,TextRenderer.DrawText() 将呈现文本,就像它在屏幕上绘制时一样。然后我创建一个常规图形对象,将 Buffered Graphics 对象复制到常规图形对象,最后将常规图形对象绘制到屏幕上。

Rectangle inner = new Rectangle(Point.Empty, ContentRectangle.Size);
using (BufferedGraphics bg = BufferedGraphicsManager.Current.Allocate(e.Graphics, inner)) {
    using (Bitmap bmp = new Bitmap(inner.Width, inner.Height, bg.Graphics)) {
        using (Graphics bmpg = Graphics.FromImage(bmp)) {
            bg.Graphics.Clear(BackColor);
            do_my_drawing(bg.Graphics);
            bg.Graphics.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy;
            e.Graphics.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy;
            bmpg.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy;

            bg.Render(bmpg);
            e.Graphics.DrawImageUnscaledAndClipped(bmp, ContentRectangle);
        }
    }
}

设置所有 CompositingMode 属性可能不是必需的,但是一旦我开始工作,我就不会费心测试所有排列来找出需要哪些排列(如果有的话)。

于 2010-04-28T16:58:06.933 回答
0

您可能想尝试在单独的位图上使用 GDI+,将其复制到屏幕上。优点是使用 GDI+ 绘制的文本的 alpha将显示位图的颜色(您将其涂成白色),而不是使位图透明。

但实际上,GDI+ 有很多错误或者只是不准确的文本测量功能。但也许您可以为此使用GDI 函数。最后,您的 GDI+ 文本渲染应该看起来与您现在拥有的 GDI 文本渲染完全一样,因此值得一试。

于 2010-04-22T14:38:44.583 回答