Как исправить альфа-значение после вызова текстовых функций GDI?

У меня есть приложение, которое использует эффект стекла Aero, поэтому каждый пиксель имеет альфа-значение в дополнение к красным, зеленым и синим значениям. У меня есть один пользовательский элемент управления рисования, который имеет сплошной белый фон (альфа = 255). Я хотел бы нарисовать сплошной текст на элементе управления, используя текстовые функции GDI. Однако эти функции устанавливают произвольное значение альфа-значения, в результате чего текст полупрозрачно отображает любое окно под моим приложением.

После вызова рендеринга текста я хотел бы просмотреть все пиксели в элементе управления и установить их альфа-значение обратно на 255. Какой лучший способ сделать это?

Мне не повезло с BitBlt, GetPixel, а также SetPixel функции. Кажется, они не обращают внимания на альфа-значение.

Вот другие решения, которые я рассмотрел и отклонил:

  • Нарисуйте растровое изображение, затем скопируйте растровое изображение на устройство. При таком подходе при визуализации текста не используются характеристики монитора (например, ClearText). Если вы знаете, как заставить GDI отображать текст в растровом формате точно так же, как на экране, это также решило бы мою проблему.
  • Использовать GDI+ для рендеринга текста. Это приложение изначально использовало GDI+ для рендеринга текста (до того, как я начал работать над поддержкой Aero). Я переключился на GDI из-за трудностей, с которыми я столкнулся, пытаясь точно измерить строки с помощью GDI+. Я бы предпочел не переключаться обратно.
  • Установите область Aero, чтобы избежать рассматриваемого элемента управления: окно моего приложения на самом деле является дочерним окном другого приложения, работающего в другом процессе. У меня нет прямого контроля над настройками Aero в окне верхнего уровня.

Приложение написано на C# с использованием Windows Forms, хотя я не использую Interop для вызова функций Win32 API.

2 ответа

Решение

Ниже приведено решение, которое я в итоге придумала. Это некрасиво и, вероятно, может быть упрощено, но это работает. Идея состоит в том, чтобы создать объект BufferedGraphics на основе исходного объекта Graphics (т. Е. Экрана). В объекте 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, вероятно, не является необходимой, но как только я начал работать, я не стал проверять все перестановки, чтобы выяснить, какие из них необходимы, если таковые имеются.

Возможно, вы захотите попробовать использовать GDI+ на отдельном растровом изображении, скопировав его на экран. Преимущество состоит в том, что альфа текста, нарисованного с помощью GDI+, покажет цвет растрового изображения (который вы бы нарисовали белым) вместо того, чтобы сделать растровое изображение прозрачным.

Но действительно, в GDI+ очень глючная или просто неточная функция измерения текста. Но, возможно, вы можете использовать функции GDI для этого. В конце концов, ваш рендеринг текста GDI+ должен выглядеть точно так же, как и рендеринг текста GDI, который у вас есть сейчас, поэтому стоит попробовать.

Другие вопросы по тегам