在调用GDI文本函数后如何修复alpha值?

时间:2010-04-22 14:10:54

标签: c# .net winforms gdi aero

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

在调用渲染文本后,我想浏览控件中的所有像素并将其alpha值设置回255.这是最好的方法吗?

我对BitBltGetPixelSetPixel函数没有任何好运。他们似乎没有注意到阿尔法价值。

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

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

该应用程序是使用Windows窗体用C#编写的,尽管我上面没有使用Interop来调用Win32 API函数。

2 个答案:

答案 0 :(得分: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属性可能不是必需的,但是一旦我开始工作,我就不会费心测试所有的排列,以确定需要哪些(如果有的话)。

答案 1 :(得分:0)

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

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