ControlクラスのRefresh、Update、Invalidateメソッドは主にコントロールを再描画するために使用されますが、これらの違いはヘルプを読んだだけでは非常に分かりにくいです。
ヘルプによると、これらのメソッドは次のように説明されています。
これらのメソッドが具体的に何を行っているのかを調べるには、「Reflector for .NET」のような逆アセンブラを使う方法があります。実際に行ってみると、次のようなことが分かります。
つまり、Invalidateメソッドはアプリケーションキューが空になった時にコントロールを再描画し、Updateメソッドはアプリケーションキューが空でなくても再描画すべき領域があるならばすぐに再描画し、Refreshはアプリケーションキューが空でなくてもコントロール(及び、設定によってはその子コントロール)をすぐに再描画するということになります。
実際のコードで動作の違いを確認してみましょう。以下のサンプル(Windowsフォームアプリケーション)では、Windowsフォーム(Form1)にボタンを2つ(Button1, 2)とピクチャボックスを4つ(PictureBox1~4)が配置されています。ピクチャボックスのPaintイベントではcounterフィールドの値を描画しています。そしてButton1のClickイベントハンドラ(Button1_Click)では1秒おきにcounterフィールドの値を増やして、その直後にPictureBox2はRefreshメソッド、PictureBox3はUpdateメソッド、PictureBox4はInvalidateメソッドを呼び出しています(PictureBox1は何もしません)。これをButton1_Clickから抜けることなく10回繰り返します。
このコードをビルド(.NET Framework 2.0、C#)して作成した実行ファイル「ControlInvalidateTest.exe」を置いておきますので、実際にお確かめください。
Public Class Form1 'カウンターの値 Private counter As Integer = 0 'PictureBoxのPaintイベントハンドラ Private Sub PictureBox_Paint(sender As Object, e As PaintEventArgs) _ Handles PictureBox1.Paint, _ PictureBox2.Paint, _ PictureBox3.Paint, _ PictureBox4.Paint 'カウンターを描画する e.Graphics.DrawString(counter.ToString(), Me.Font, Brushes.Black, 0, 0) End Sub 'Button1のClickイベントハンドラ Private Sub Button1_Click(sender As Object, e As EventArgs) _ Handles Button1.Click For i As Integer = 0 To 9 'カウンターを増やす Me.counter += 1 'PictureBox1では、何もしない 'PictureBox2では、Refreshを呼び出す PictureBox2.Refresh() 'PictureBox3では、Updateを呼び出す PictureBox3.Update() 'PictureBox4では、Invalidateを呼び出す PictureBox4.Invalidate() '1秒間停止する System.Threading.Thread.Sleep(1000) Next End Sub 'Button2のClickイベントハンドラ Private Sub Button2_Click(sender As Object, e As EventArgs) _ Handles Button2.Click 'カウンターをリセットする Me.counter = 0 'PictureBoxを再描画する PictureBox1.Invalidate() PictureBox2.Invalidate() PictureBox3.Invalidate() PictureBox4.Invalidate() End Sub End Class
using System; using System.Drawing; using System.Windows.Forms; namespace ControlInvalidateTest { public partial class Form1 : Form { public Form1() { InitializeComponent(); //イベントにイベントハンドラをアタッチする Button1.Click += new EventHandler(Button1_Click); Button2.Click += new EventHandler(Button2_Click); PictureBox1.Paint += new PaintEventHandler(PictureBox_Paint); PictureBox2.Paint += new PaintEventHandler(PictureBox_Paint); PictureBox3.Paint += new PaintEventHandler(PictureBox_Paint); PictureBox4.Paint += new PaintEventHandler(PictureBox_Paint); } //カウンターの値 private int counter = 0; //PictureBoxのPaintイベントハンドラ private void PictureBox_Paint(object sender, PaintEventArgs e) { //カウンターを描画する e.Graphics.DrawString( counter.ToString(), this.Font, Brushes.Black, 0, 0); } //Button1のClickイベントハンドラ private void Button1_Click(object sender, EventArgs e) { for (int i = 0; i < 10; i++) { //カウンターを増やす this.counter++; //PictureBox1では、何もしない //PictureBox2では、Refreshを呼び出す PictureBox2.Refresh(); //PictureBox3では、Updateを呼び出す PictureBox3.Update(); //PictureBox4では、Invalidateを呼び出す PictureBox4.Invalidate(); //1秒間停止する System.Threading.Thread.Sleep(1000); } } //Button2のClickイベントハンドラ private void Button2_Click(object sender, EventArgs e) { //カウンターをリセットする this.counter = 0; //PictureBoxを再描画する PictureBox1.Invalidate(); PictureBox2.Invalidate(); PictureBox3.Invalidate(); PictureBox4.Invalidate(); } } }
普通に実行させると、カウンターが1秒おきにインクリメントされて表示されるのは、Refreshメソッドを使ったPictureBox2だけです。Invalidateメソッドを使ったPictureBox4は、10秒後にカウンターの表示が更新されます。何もしなかったPictureBox1とUpdateメソッドを使ったPictureBox3は10秒経っても「0」のままです。しかし、フォームの上に別のウィンドウを重ねて隠してからどけたり、フォームを最小化してから元に戻したりすると、「10」と表示されます。
何もしなかった時とUpdateメソッドを使った時は同じに見えますが、Updateメソッドを使った時はフォームを別のウィンドウで隠してどけるというようなことを行うと、10秒経過する前でも更新されて表示されます。
注意:環境によっては、フォームを別のウィンドウで隠してからどけるといった方法では再描画されません。Windows Vista以降では、テーマをクラシックにしていなければ、この方法で再描画はできないようです。さらに、それ以外の動作も、様々な要因で変化する可能性があります。
実際のこれらのメソッドの使い分けとしては、コントロールを再描画したいがすぐである必要がないときはInvalidateメソッドを使い、今すぐ再描画する必要があるときはRefreshメソッドを使うということになるでしょう。
補足:.NET Frameworkの標準コントロールで言うと、例えばPictureBoxコントロールではImageプロパティを変更すると内部でInvalidateメソッドが呼び出されています。