1

コントロールの再描画には時間がかかり、多くのリソースを浪費するため、サイズ変更中ではなく、サイズ変更後にコントロールを再描画する必要があります。

私のコントロールはControlクラスを継承し、OnResizeイベントをオーバーライドしています。

PS: OnSizeChanged はまったく同じです

4

4 に答える 4

8

この問題の別の見方を示しましょう。

問題は、必ずしも「ユーザーがまだコントロールのサイズを変更している」ということではありません。実際の問題は、再描画にかかる時間よりも頻繁にコントロールのサイズが変更されることです。

問題をスループットの 1 つとして定義すると、解決が容易になります。実際、Bebop は彼の答えで正しい考えを持っていましたが、もっとうまくやれると思います。

public class MyControl : Control
{
    private TimeSpan paintTime = 250;   // Time to paint, default=250ms
    private TimeSpan resizeTime = 100;  // Time to update layout, default=100ms

    protected override void OnPaint(PaintEventArgs pe)
    {
        Stopwatch sw = new Stopwatch();
        sw.Start();
        // Do your painting here, or call base.OnPaint
        sw.Stop();
        paintTime = sw.Elapsed;
    }

    protected override void OnResize(EventArgs e)
    {
        // The "Stop" is not redundant - it will force the timer to "reset"
        // if it is already running.
        resizeTimer.Stop();
        base.OnResize(e);
        resizeTimer.Interval =
            (int)(paintTime.TotalMilliseconds + resizeTime.TotalMilliseconds);
        resizeTimer.Start();
    }

    private void UpdateSize()
    {
        Stopwatch sw = new Stopwatch();
        sw.Start();
        // Resizing code goes here
        sw.Stop();
        resizeTime = sw.Elapsed;
    }

    private void resizeTimer_Tick(object sender, EventArgs e)
    {
        resizeTimer.Stop();
        UpdateSize();
    }
}

ここでの考え方は、コントロールが自身をアクティブにプロファイリングすることです。遅いマシンで実行したり、マシンの動作が単に遅い場合は、再描画速度が遅くなります。最先端のハードウェアで実行している場合は、再描画をまったくスキップする必要がない場合があります。これは実際には、デバイス エミュレータでよく見られる種類の非常に単純な「自動フレーム スキップ」アルゴリズムです。

明確にするために、nobugz が提唱するアプローチに反対するものは何もありません。代わりにこれを選択する唯一の理由は、ロジックが完全に自己完結型であるためです。一方、Resizingプロパティ (またはおそらくより適切な名前のEnableFullPaint) を公開することは、消費者がそれを知って適切に使用することに依存していますサイズ変更の全期間にわたって再描画が行われるため、アプリにバグが「感じられる」可能性があります。ユーザーは、サイズ変更操作中に空白の画面や無意味な画面が表示されることを期待する傾向はありません。

私は両方の方法を使用しましたが、どちらも機能します。どちらが最適かは、要件によって異なります。これを試して、どれだけうまく機能するかを確認し、問題が発生したり、必要なものではない場合は、nobugz の回答を使用することをお勧めします。

于 2010-01-24T19:25:53.393 に答える
2

親コントロール/フォームのサイズ変更が完了した後にのみ、コントロールのサイズを変更することができます。「ResizeEnd」イベントを使用してこれを行うことができます。

例えば:

private void UserControl1_Load(object sender, EventArgs e)
{
    ((Form)this.Parent).ResizeEnd += new EventHandler(UserControl1_ResizeEnd);
}
void UserControl1_ResizeEnd(object sender, EventArgs e)
{
    MessageBox.Show("Resize end");
}
于 2010-01-24T16:39:50.653 に答える
2

MouseDown イベントを取得したときはどうですか? YourControl.SuspendLayout();

次に、MouseUp イベントに移動します: YourControl.ResumeLayout();

于 2010-01-24T16:59:28.317 に答える
0

ResizeEndイベントは最良のアイデアのようですが、別の方法として、サイズ変更イベントで再起動し、タイマーが起動したときに再描画するタイマーを使用することもできます。タイマーの時間がかなり短い場合、たとえば100msである限り、再描画の遅延がひどく気付くことはありません。

しかし、他のイベントはより良いオプションのようです...

于 2010-01-24T17:30:45.153 に答える