6

私はここで些細なことを見逃していると思います。から直接単純な制御を導き出しましたControlOnPaint長方形(e.Graphics.DrawRectangle)とその中のテキスト()をオーバーライドしてペイントしていますe.Graphics.DrawString。他のメンバーをオーバーライドしませんでした。

コントロールを小さいサイズにサイズ変更するとうまくペイントされますが、大きいサイズにサイズ変更すると、新しい領域が適切に再ペイントされません。もう一度小さいサイズにサイズ変更するとすぐに、たとえ1ピクセルでも、すべてが正しく再描画されます。

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?

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 に答える