CreateGraphics和绘图字符串的问题

P a*_*u l 2 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();
        }


    }
}
Run Code Online (Sandbox Code Playgroud)

Han*_*ant 9

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

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

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

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

  • 好吧,你可以自己加倍缓冲.使用Bitmap,Graphics.FromImage()并绘制到该图形上下文中.然后DrawImage()结果.仍然,只需调用Invalidate()让常规的Paint()事件处理程序绘制更好. (3认同)