当用户绘制的控件大小增加时,新区域不会重新绘制

我想我在这里错过了一些微不足道的东西。 我直接从Control派生出简单的控件。 我正在重写OnPaint并绘制矩形( e.Graphics.DrawRectangle )和其中的文本( e.Graphics.DrawString )。 我没有覆盖任何其他成员。

当控件调整为较小的尺寸时,它会很好地自我绘制,但是当它调整到更大的尺寸时,新区域不会被正确重新绘制。 一旦我再次将其调整为较小的尺寸,即使按一个像素,一切都正确重新绘制。

OnPaint被正确调用(适当的PaintEventArgs.ClipRectangle正确设置到新区域),但无论如何都不会绘制新区域(出现工件)。

我错过了什么?

编辑:

码:

 protected override void OnPaint(PaintEventArgs e) { // Adjust control's height based on current width, to fit current text: base.Height = _GetFittingHeight(e.Graphics, base.Width); // Draw frame (if available): if (FrameThickness != 0) { e.Graphics.DrawRectangle(new Pen(FrameColor, FrameThickness), FrameThickness / 2, FrameThickness / 2, base.Width - FrameThickness, base.Height - FrameThickness); } // Draw string: e.Graphics.DrawString(base.Text, base.Font, new SolidBrush(base.ForeColor), new RectangleF(0, 0, base.Width, base.Height)); } private int _GetFittingHeight(Graphics graphics, int width) { return (int)Math.Ceiling(graphics.MeasureString(base.Text, base.Font, width).Height); } 

WTF?

尝试在构造函数中添加:

 public MyControl() { this.ResizeRedraw = true; this.DoubleBuffered = true; } 

并在您的绘画事件中,清除上一张图:

 protected override void OnPaint(PaintEventArgs e) { e.Graphics.Clear(SystemColors.Control); // yada-yada-yada } 

虽然ResizeRedraw可以工作,但它会强制整个控件重新绘制每个resize事件,而不是仅绘制resize显示的区域。 这可能是也可能不是所希望的。

OP所遇到的问题是由于旧矩形没有失效这一事实造成的; 只有被曝光的区域才会被重新粉刷,旧的图形会保持原样。 要更正此问题,请检测矩形的大小是垂直增加还是水平增加,并使矩形的相应边缘无效。

您将如何具体实现这一点取决于您的实施。 你需要有一些东西来擦除旧的矩形边缘,你必须调用Invalidate传递包含旧矩形边缘的区域。 根据你正在做的事情,让它正常工作可能有点复杂,如果性能差异可以忽略不计,那么使用ResizeRedraw可能会更简单。

例如,在绘制边框时,您可以为此问题执行此操作。

 // member variable; should set to initial size in constructor // (side note: should try to remember to give your controls a default non-zero size) Size mLastSize; int borderSize = 1; // some border size ... // then put something like this in the resize event of your control var diff = Size - mLastSize; var wider = diff.Width > 0; var taller = diff.Height > 0; if (wider) Invalidate(new Rectangle( mLastSize.Width - borderSize, // x; some distance into the old area (here border) 0, // y; whole height since wider borderSize, // width; size of the area (here border) Height // height; all of it since wider )); if (taller) Invalidate(new Rectangle( 0, // x; whole width since taller mLastSize.Height - borderSize, // y; some distance into the old area Width, // width; all of it since taller borderSize // height; size of the area (here border) )); mLastSize = Size;