New area not repaints when user-drawn control size is increased

谁都会走 提交于 2019-12-23 09:58:37

问题


I think I'm missing something trivial here. I derived simple control directly from Control. I'm overriding OnPaint and painting the rectangle (e.Graphics.DrawRectangle)and a text inside it (e.Graphics.DrawString). I did not override any other members.

It paints itself well when the control is resized to the smaller size, but when it gets resized to the larger size, new area is not repainted properly. As soon as I resize it to the smaller size again, even if by one pixel, everything repaints correctly.

OnPaint gets called properly (with appropriate PaintEventArgs.ClipRectangle set correctly to new area), but the new area is not painted (artifacts appear) anyway.

What am I missing?

EDIT:

Code:

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);
}


回答1:


Try adding this in your constructor:

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

and in your paint event, clear the previous drawing:

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



回答2:


While ResizeRedraw will work, it forces the entire control to repaint for every resize event, rather than only painting the area that was revealed by the resize. This may or may not be desirable.

The problem the OP was having is caused by the fact that the old rectangle does not get invalidated; only the revealed area gets repainted, and old graphics stay where they were. To correct this, detect whether the size of your rectangle has increased vertically or horizontally, and invalidate the appropriate edge of the rectangle.

How you would specifically go about this would depend on your implementation. You would need to have something that erases the old rectangle edge and you would have to call Invalidate passing an area containing the old rectangle edge. It may be somewhat complicated to get it to work properly, depending what you're doing, and using ResizeRedraw after all may be much simpler if the performance difference is negligible.

Just for example, here is something you can do for this problem when drawing a border.

// 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;


来源:https://stackoverflow.com/questions/12815605/new-area-not-repaints-when-user-drawn-control-size-is-increased

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!