コントロールの再描画には時間がかかり、多くのリソースを浪費するため、サイズ変更中ではなく、サイズ変更後にコントロールを再描画する必要があります。
私のコントロールはControlクラスを継承し、OnResizeイベントをオーバーライドしています。
PS: OnSizeChanged はまったく同じです
この問題の別の見方を示しましょう。
問題は、必ずしも「ユーザーがまだコントロールのサイズを変更している」ということではありません。実際の問題は、再描画にかかる時間よりも頻繁にコントロールのサイズが変更されることです。
問題をスループットの 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 の回答を使用することをお勧めします。
親コントロール/フォームのサイズ変更が完了した後にのみ、コントロールのサイズを変更することができます。「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");
}
MouseDown イベントを取得したときはどうですか? YourControl.SuspendLayout();
次に、MouseUp イベントに移動します: YourControl.ResumeLayout();
ResizeEndイベントは最良のアイデアのようですが、別の方法として、サイズ変更イベントで再起動し、タイマーが起動したときに再描画するタイマーを使用することもできます。タイマーの時間がかなり短い場合、たとえば100msである限り、再描画の遅延がひどく気付くことはありません。
しかし、他のイベントはより良いオプションのようです...