CreateGraphics和绘图字符串的问题

时间:2010-01-14 22:00:54

标签: c# winforms

下面的控件在矩形中绘制一个字符串。在鼠标移动时,对字符串矩形进行了命中测试,并通过CreateGraphics重新绘制字符串。令人恼火的问题是文本的绘制方式与Paint处理程序中的相同;它似乎被大约1个像素所取代,效果就像一个粗体字体。如何创建与Paint处理程序中的图形对象完全相同的图形对象,以便以相同的方式绘制文本?通常,您会在Paint事件中使所有内容无效并重绘,但我可能有数百个其他绘图项,并且只想绘制字符串。我是否应该尝试在Paint事件之外进行任何绘图,或者这是一个错误?

示例控件:

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

namespace Test.TestModes
{
    public partial class ExampleControl: UserControl
    {
        private const string testString = "0123456789";
        private RectangleF stringRect = new RectangleF(10, 10, 100, 20);

        public ExampleControl()
        {
            InitializeComponent();
        }

        private void ExampleControl_Paint(object sender, PaintEventArgs e)
        {
            Font font = new Font("Arial", 12, FontStyle.Regular);

            e.Graphics.DrawString(testString, font, Brushes.Black, stringRect);

            font.Dispose();
        }

        private void DrawString(bool hit)
        {
            Font font = new Font("Arial", 12, FontStyle.Regular);

            using(Graphics g = CreateGraphics())
            {
                g.SetClip(ClientRectangle);
                if(hit)
                    g.DrawString(testString, font, Brushes.Red, stringRect);
                else
                    g.DrawString(testString, font, Brushes.Black, stringRect);
            }

            font.Dispose();
        }

        private void ExampleControl_MouseMove(object sender, MouseEventArgs e)
        {
            if(stringRect.Contains(e.Location))
                DrawString(true);
            else
                DrawString(false);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Invalidate();
        }


    }
}

1 个答案:

答案 0 :(得分:8)

CreateGraphics()调用间接地让你陷入困境。问题是文本的抗锯齿。正常的绘画循环在绘制顶部之前擦除背景。在您的情况下,您的绘图文本不会发生在现有文本之上。副作用是每次绘制时用于创建锯齿的像素变得更暗。最终的结果是大胆的外观和明显的锯齿状文字轮廓。

修复很容易:在绘制之前先用干净的石板开始:

    using (Graphics g = CreateGraphics()) {
        g.Clear(this.BackColor);                <=== added
        g.SetClip(ClientRectangle);
        // etc..
    }

你现在也会在绘图中遇到一个被称为“闪烁”的问题。它可能还不是那么明显,但是当你做更多的绘画时它会。通过双缓冲抑制闪烁。 Windows窗体支持的功能,但仅限于使用标准绘图技术。换句话说:没有CreateGraphics()。