Как применить масштабирование графики и перевести на TextRenderer - PullRequest
6 голосов
/ 13 января 2012

Я использую масштабирование и преобразование моего графического объекта при рисовании пользовательского элемента управления, чтобы применить масштабирование и прокрутку.Я использую следующее:

            Matrix mx = new Matrix();
            mx.Scale(mZoomFactor, mZoomFactor);
            mx.Translate(-clip.X + mGraphicsOffsetx, -clip.Y + mGraphicsOffsety);

            e.Graphics.Clip = new Region(this.Bounds);
            e.Graphics.Transform = mx;

Затем, когда я рисую мои строки, используя:

Graphics g = ...
g.DrawString(...)

Правильно применяется выкручивание и преобразование к строкам, они уменьшаются и уменьшаютсявкл.

Однако, если я использую следующее для рисования своих строк:

TextRenderer.DrawText(...)

Текст неправильно масштабируется и преобразуется.

Знаете ли вы, как применить этопонятия к TextRenderer?

1 Ответ

6 голосов
/ 06 февраля 2012

Комментарии выше точны - TextRenderer.DrawText, будучи GDI, имеет ограниченную поддержку преобразования координат, учитывая его зависимость от разрешения. Как вы заметили, перевод координат поддерживается, а масштабирование - нет (равно как и вращение координат).

Решение, которое мы использовали (и единственный ресурс, который мне удалось найти в Интернете), состоит в том, чтобы вручную масштабировать объекты Font и Rectangle, чтобы отразить масштабирование, примененное Matrix.Scale(float, float) в сочетании с Graphics.Transform

    private Font GetScaledFont(Graphics g, Font f, float scale)
    {
        return new Font(f.FontFamily,
                        f.SizeInPoints * scale,
                        f.Style,
                        GraphicsUnit.Point,
                        f.GdiCharSet,
                        f.GdiVerticalFont);
    }

    private Rectangle GetScaledRect(Graphics g, Rectangle r, float scale)
    {
        return new Rectangle((int)Math.Ceiling(r.X * scale),
                            (int)Math.Ceiling(r.Y * scale),
                            (int)Math.Ceiling(r.Width * scale),
                            (int)Math.Ceiling(r.Height * scale));
    }

Вот полная форма теста:

public partial class Form1 : Form
{
    private PictureBox box = new PictureBox();

    public Form1()
    {
        InitializeComponent();
        this.Load += new EventHandler(Form1_Load);
    }

    public void Form1_Load(object sender, EventArgs e)
    {
        box.Dock = DockStyle.Fill;
        box.BackColor = Color.White;

        box.Paint += new PaintEventHandler(DrawTest);
        this.Controls.Add(box);
    }

    public void DrawTest(object sender, PaintEventArgs e)
    {
        Graphics g = e.Graphics;

        string text = "Test Text";
        float scale = 1.5F;
        float translate = 200F;

        var flags = TextFormatFlags.PreserveGraphicsClipping | TextFormatFlags.PreserveGraphicsTranslateTransform;

        var mx = new Matrix();
        mx.Scale(scale, scale);
        mx.Translate(translate, translate);

        g.Clip = new Region(Bounds);
        g.Transform = mx;

        Size rendererPSize = Bounds.Size;
        Font f = GetScaledFont(g, new Font("Arial", 12), scale);
        Size rendererRSize = TextRenderer.MeasureText(g, text, f, rendererPSize, flags);

        Rectangle rendererRect = new Rectangle(0, 0, rendererRSize.Width, rendererRSize.Height);
        Rectangle r = GetScaledRect(g, rendererRect, scale);

        TextRenderer.DrawText(g, text, f, realRect, Color.Black, flags);
    }

    private Font GetScaledFont(Graphics g, Font f, float scale)
    {
        return new Font(f.FontFamily,
                        f.SizeInPoints * scale,
                        f.Style,
                        GraphicsUnit.Point,
                        f.GdiCharSet,
                        f.GdiVerticalFont);
    }

    private Rectangle GetScaledRect(Graphics g, Rectangle r, float scale)
    {
        return new Rectangle((int)Math.Ceiling(r.X * scale),
                            (int)Math.Ceiling(r.Y * scale),
                            (int)Math.Ceiling(r.Width * scale),
                            (int)Math.Ceiling(r.Height * scale));
    }
}
...