【发布时间】:2010-01-14 22:00:54
【问题描述】:
下面的控件在一个矩形中绘制一个字符串。在鼠标移动时,字符串矩形上有一个命中测试,字符串通过 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();
}
}
}
【问题讨论】:
-
你为什么还要使用 CreateGraphics?在 Pain 事件中完成所有绘画,这就是它的用途。
-
如何只绘制字符串而不绘制控件的其余部分?
-
我会首先在 DrawString 方法中调试 PaintEventArgs 的 ClipRectangle 的位置和 ClientRectangle,看看是否一切都匹配...
-
只需在控件上调用 Invalidate,将要刷新的矩形作为参数。 msdn.microsoft.com/en-us/library/8dtk06x2.aspx
-
-- 然后在 Paint 事件中我是否测试每个绘图元素并且仅在剪辑区域中绘制?