TextRenderer. DrawText в битовом массиве по сравнению с OnPaintBackground

У вас есть несколько подходов:

  • Поскольку на него уже ответили комментарии @ user3386109 в комментариях к вопросу, вы можете отсканировать исходный файл и извлечь названия включенных функций. Это требует предварительной обработки файла (с помощью cpp(1)), поскольку фактические имена функций могут быть скрыты в конструкциях макросов, а затем извлекаются имена определений функций (для этого потребуется синтаксический анализатор или нет, в зависимости от ограничений, накладываемых на источник файл, который вы хотите отсканировать). В любом случае, это будет сложная задача, и чем больше вы будете ограничивать формат в исходном файле.
  • Вы можете dlopen(3) объектный файл (участвующая программа или совместно используемая библиотека) и искать идентификаторы функций. Это также будет утомительно, поскольку вынуждает вас использовать двоичный формат (в основном, ELF), который будет использоваться в качестве целевой архитектуры вашей программы. Это зависит от исполняемого формата и не всегда будет возможно.
  • Более простой подход состоит в том, чтобы пометить эти идентификаторы в источнике (например, аннотации в java) макросом TAG, который расширяется до нуля, и отметить места, где будет происходить идентификатор функции. Например:

    #define TAG
    void TAG myFunc(int a, int b, int c)
    

    Затем вы можете найти файл для TAG и извлечь следующий идентификатор.

Язык Java требует, чтобы идентификаторы были включены в исполняемый файл в строковом формате, поэтому вы можете применить самоанализ для получения этой информации, но это не является обязательным требованием в C / C ++. И вся структура иерархии классов также включена в исполняемый файл как статическая структура данных, так что вы можете перемещаться и открывать все иерархии типов Java. Это невозможно в C, поскольку основной целью программирования на C является эффективность. Наличие всей информации о типе, включенной в программу, вынуждает использовать много памяти для описания определений данных, и поэтому она не включена в C / C ++.

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

Другой простой подход к автоматическому выполнению того, о чем вы просите, - определить макрос:

#define FUNCTION_NAME(typ, name) char name##_string[] = #name; typ name

и использовать его как

FUNCTION_NAME(void, myFunc)(int par1, char *par2, int par3)
{
    ...
}

, который расширяется до

char myFunc_string[] = "myFunc";
void myFunc(int par1, char *par2, int par3)
{
    ...
}

, поэтому для каждой функции x у вас будет статическая строка x_string с именем в виде строки и заголовком функции, свободным от объявления того, что вы хотите (даже переменная функция)

Кстати, внутри тела функции определен неявный макрос, который расширяется до строки, содержащей имя функции __func__. Но проблема в том, что его можно использовать только внутри функционального тела.

7
задан Jon Tackabury 11 May 2009 в 18:58
поделиться

5 ответов

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

Используйте Graphics.DrawString ] & Graphics.MeasureString , но не забудьте передать его StringFormat.GenericTypographic, чтобы получить точный размер и расположение.

Причина, по которой TextRenderer был первоначально введен, заключалась в том, что GDI + не поддерживал все сложные скрипты, которые GDI's Uniscribe двигатель сделал. Однако со временем поддержка сложных скриптов GDI + была расширена, и в наши дни не осталось никаких веских причин для использования TextRenderer (он даже не самый быстрый из двух, на самом деле, как раз наоборот).

Действительно ,

9
ответ дан 6 December 2019 в 21:19
поделиться

Если размер вашего растрового изображения не совпадает с размером области отображения, это может быть просто проблема изменения размера, когда .NET масштабирует растровое изображение до размера отображения, и вы получаете смешной текст.

Можете ли вы протестировать растровое изображение, созданное с размером области отображения?

-1
ответ дан 6 December 2019 в 21:19
поделиться

Можете ли вы опубликовать самую маленькую программу, которая страдает от этой проблемы? Я не могу воспроизвести это так - сглаживание выглядит нормально:

    using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;

public class Program
{
    public static void Main()
    {
        Bitmap bmp = new Bitmap(100, 100, PixelFormat.Format32bppArgb);
        using (Font font = new Font("Arial", 10, GraphicsUnit.Point))
        using (Graphics g = Graphics.FromImage(bmp))
        {
            Rectangle clip = Rectangle.FromLTRB(0, 0, 100, 100);
            g.Clear(Color.Red);
            TextFormatFlags tf = TextFormatFlags.Left;
            TextRenderer.DrawText(g, @"C:\Development\Testing\blag", font, clip, Color.White, Color.Transparent, tf);
        }

        Form form = new Form();
        form.BackgroundImage = bmp;
        Application.Run(form);
    }
}
-1
ответ дан 6 December 2019 в 21:19
поделиться

Другое возможное решение: нарисуйте все на экране, растровое изображение с текстом наверху, а затем напишите некоторый код на экран захватить эту часть экрана. Не во всех случаях практично, но вы правы, DrawString создает странный текст, а DrawText на растровом изображении выглядит ужасно.

0
ответ дан 6 December 2019 в 21:19
поделиться

Я полагаю, что проблема в том, что рендеринг текста прозрачного типа не работает, если фон прозрачный. Несколько возможных решений.

Вариант 1. Залейте фон вашего растрового изображения цветом.

Если вы сделаете это (как Тим Робинсон сделал выше в своем примере кода, используя g.Clear(Color.Red)), clear type сделает все правильно. Но ваша растровая карта не будет полностью прозрачной, что может быть неприемлемо. Если вы используете Graphics.MeasureText, вы можете заполнить только прямоугольник вокруг вашего текста, если хотите.

Вариант 2. Set TextRenderingHint = TextRenderingHintAntiAliasGridFit

Это, похоже, отключает четкий шрифт. Текст будет отображаться с качеством ниже, чем у прозрачного шрифта на фоне, но гораздо лучше, чем беспорядок, который создает прозрачный шрифт без фона.

Вариант 3. Залейте прямоугольник текста белым цветом, нарисуйте текст, а затем найдите все пиксели, не относящиеся к тексту, и верните их в прозрачное состояние.

using (Bitmap bmp = new Bitmap(someWidth, someHeight))
{
    using (Graphics g = Graphics.FromImage(bmp))
    {
        // figure out where our text will go
        Point textPoint = new Point(someX, someY);
        Size textSize = g.MeasureString(someText, someFont).ToSize();
        Rectangle textRect = new Rectangle(textPoint, textSize);

        // fill that rect with white
        g.FillRectangle(Brushes.White, textRect);

        // draw the text
        g.DrawString(someText, someFont, Brushes.Black, textPoint);

        // set any pure white pixels back to transparent
        for (int x = textRect.Left; x <= textRect.Left + textRect.Width; x++)
        {
            for (int y = textRect.Top; y <= textRect.Top + textRect.Height; y++)
            {
                Color c = bmp.GetPixel(x, y);
                if (c.A == 255 && c.R == 255 && c.G == 255 && c.B == 255)
                {
                    bmp.SetPixel(x, y, Color.Transparent);
                }
            }
        }
    }
}

Я знаю, это ужасный хак, но, похоже, он работает.

3
ответ дан 6 December 2019 в 21:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: