6

我想我在这里遗漏了一些微不足道的东西。我直接从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);
}

怎么回事?

4

2 回答 2

11

尝试在您的构造函数中添加它:

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

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

protected override void OnPaint(PaintEventArgs e) {
  e.Graphics.Clear(SystemColors.Control);
  // yada-yada-yada
}
于 2012-10-10T11:29:27.670 回答
3

虽然ResizeRedraw会起作用,但它会强制整个控件为每个调整大小事件重新绘制,而不是只绘制由调整大小显示的区域。这可能是可取的,也可能不是可取的。

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;
于 2016-09-09T20:29:28.733 回答