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

时间:2012-10-10 08:58:35

标签: c# .net winforms drawing

我想我在这里错过了一些微不足道的东西。我直接从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?

2 个答案:

答案 0 :(得分:10)

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

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

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

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

答案 1 :(得分:2)

虽然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;