.NET開発者のためのブログメディア

C#での画面描画について紹介|画面描画時のちらつき防止対策
- SE
- C#で画面描画をすると、ちらつきが出てしまうのですが。
- PM
- 描画の際のちらつき防止対策やコントロールのレイアウトロジックの中断や再開方法を紹介しましょう。
目次
C#の描画について
今回は、C#の描画について説明します。コントロールのレイアウトロジックを中断、再開方法を紹介します。また、描画時のちらつきとその対策について紹介します。
C#の描画に興味のある方はぜひご覧ください。
レイアウトロジックの停止、再開
C#では、コントロールのレイアウトロジックを中断、再開ができます。
実際のソースコードを見てみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
using System; A using System.Drawing; using System.Windows.Forms; namespace WindowsFormsApp1 { public partial class Form1 : Form { Button button1, button2; public Form1() { button1 = new Button(); button1.Text = “SuspendLayout”; button1.Dock = DockStyle.Top; button1.Click += Button1_Click; button2 = new Button(); button2.Text = “ResumeLayout”; button2.Dock = DockStyle.Bottom; button2.Click += Button2_Click; this.Load += Form1_Load; this.Controls.Add(button1); this.Controls.Add(button2); } private void Form1_Load(object sender, EventArgs e) { button2.Enabled = false; } private void Button1_Click(object sender, EventArgs e) { // コントロールのレイアウトロジックを一時的に中断 this.SuspendLayout(); button1.Enabled = false; button2.Enabled = true; } private void Button2_Click(object sender, EventArgs e) { // コントロールのレイアウトロジック再開 this.ResumeLayout(); button1.Enabled = true; button2.Enabled = false; } } } |
Formをリサイズすると、Formの上端および下端にボタンが配置されます。”SuspendLayout”ボタンをクリックすると、コントロールのレイアウトロジックが一時的に中断され、ボタンの描画が止まります。”ResumeLayout”ボタンをクリックすると、コントロールのレイアウトロジックが再開されます。
このように、C#ではコントロールのレイアウトロジックを中断、再開ができます。
描画がちらつく
Formのリサイズ時などの描画がちらつくことがあります。どのようにちらつくのか、確認してみます。
実際のソースコードを見てみましょう。事前に”C:\test\test.bmp”を格納してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
using System; using System.Drawing; using System.Windows.Forms; namespace WindowsFormsApp1 { public partial class Form1 : Form { Bitmap bitmap; public Form1() { this.Load += Form1_Load; } private void Form1_Load(object sender, EventArgs e) { // 画像の設定 bitmap = new Bitmap(@”C:\test\test.bmp”); this.ClientSize = bitmap.Size; } protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); // FormのClientRectangleプロパティにより、Form領域の四角形を取得し、同じサイズで描画 e.Graphics.DrawImage(bitmap, this.ClientRectangle); } } } |
オーバーライドしたOnPaintメソッドで、Form全体にビットマップを表示します。Formをリサイズすると、正しく描画されないことが分かります。
Fromのリサイズ時にはOnPaintメソッドが呼び出されますが、OnPaintメソッドでは基本的に無効領域に対してのみ描画します。この場合、Formをリサイズすることにより広くなった部分が無効領域ですので、正しく描画できません。
OnResizeメソッドによるForm領域の無効化
上記のサンプルのように、OnPaintメソッドでは基本的に無効領域に対してのみ描画しません。C#ではこの対策として、Form領域を無効化することで、正しい描画が行えます。
実際のソースコードを見てみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
using System; using System.Drawing; using System.Windows.Forms; namespace WindowsFormsApp1 { public partial class Form1 : Form { Bitmap bitmap; public Form1() { this.Load += Form1_Load; } private void Form1_Load(object sender, EventArgs e) { bitmap = new Bitmap(@”C:\test\test.bmp”); this.ClientSize = bitmap.Size; } protected override void OnResize(EventArgs e) { base.OnResize(e); // 指定した領域(Form)を無効にする this.Invalidate(); } protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); // FormのClientRectangleプロパティにより、Form領域の四角形を取得し、同じサイズで描画 e.Graphics.DrawImage(bitmap, this.ClientRectangle); } } } |
ウィンドウのリサイズ時に呼び出されるOnResizeメソッドをオーバーライドします。OnResizeメソッドにて、Invalidateメソッドを呼び出すことで、Form領域全体が無効となります。その結果、描画時のちらつきが発生しないことが分かります。
コントロール・スタイルの設定
C#でのちらつき対策の別の方法として、コントロール・スタイルの設定があります。
実際のソースコードを見てみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
using System; using System.Drawing; using System.Windows.Forms; namespace WindowsFormsApp1 { public partial class Form1 : Form { Bitmap bitmap; public Form1() { this.Load += Form1_Load; } private void Form1_Load(object sender, EventArgs e) { bitmap = new Bitmap(@”C:\test\test.bmp”); this.ClientSize = bitmap.Size; // OnResizeメソッドを記述せずとも同じ効果がある this.SetStyle(ControlStyles.ResizeRedraw, true); } protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); e.Graphics.DrawImage(bitmap, this.ClientRectangle); } } } |
この場合、OnResizeメソッドを記述せずとも、Formのスタイル「ControlStyles.ResizeRedraw」を設定すれば同じ効果があります。このように、C#でのちらつき対策の別の方法として、スタイルの設定があります。
ダブルバッファリングを用いた描画
複雑な描画や、ウィンドウを大きなサイズにリサイズした場合などには描画がちらつく場合があります。その場合、C#ではダブルバッファリングを使用するのが一般的です。
ダブルバッファリングとは、画面に表示する前に、あらかじめ用意したメモリ上のイメージバッファに描画し、すべての描画が完了したら画面描画する方法です。すべての描画が完了したら画面に描画するため、結果として画面のちらつきが発生しません。
実際のソースコードを見てみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
using System; using System.Drawing; using System.Windows.Forms; namespace WindowsFormsApp1 { public partial class Form1 : Form { Bitmap bitmap; public Form1() { this.Load += Form1_Load; } private void Form1_Load(object sender, EventArgs e) { bitmap = new Bitmap(@”C:\test\test.bmp”); this.ClientSize = bitmap.Size; this.SetStyle(ControlStyles.ResizeRedraw, true); // ダブルバッファリング this.SetStyle(ControlStyles.DoubleBuffer, true); this.SetStyle(ControlStyles.UserPaint, true); this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); } protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); e.Graphics.DrawImage(bitmap, this.ClientRectangle); } } } |
画面をリサイズしてもちらつきは発生しません。このように、C#ではダブルバッファリングを利用することで、画面のちらつきを防止できます。
- SE
- 描画のちらつき対策にはいろいろあるのですね。
- PM
- ご紹介したソースコードを参考に、ご自身でソースコードを書いて理解を深めてください。
まとめ
いかがでしたでしょうか。C#でのコントロールのレイアウトロジックを中断、再開方法を紹介しました。また、描画時のちらつきとその対策について紹介しました。
ぜひご自身でソースコードを書いて、理解を深めてください。