C#での画面描画について紹介|画面描画時のちらつき防止対策

- システム
エンジニア - C#で画面描画をすると、ちらつきが出てしまうのですが。
- プロジェクト
マネージャー - 描画の際のちらつき防止対策やコントロールのレイアウトロジックの中断や再開方法を紹介しましょう。
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 |
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#ではダブルバッファリングを利用することで、画面のちらつきを防止できます。
- システム
エンジニア - 描画のちらつき対策にはいろいろあるのですね。
- プロジェクト
マネージャー - ご紹介したソースコードを参考に、ご自身でソースコードを書いて理解を深めてください。
まとめ
いかがでしたでしょうか。C#でのコントロールのレイアウトロジックを中断、再開方法を紹介しました。また、描画時のちらつきとその対策について紹介しました。
ぜひご自身でソースコードを書いて、理解を深めてください。
FEnet.NETナビ・.NETコラムは株式会社オープンアップシステムが運営しています。
株式会社オープンアップシステムはこんな会社です
秋葉原オフィスには株式会社オープンアップシステムをはじめグループのIT企業が集結!
数多くのエンジニアが集まります。

-
スマホアプリから業務系システムまで
スマホアプリから業務系システムまで開発案件多数。システムエンジニア・プログラマーとしての多彩なキャリアパスがあります。
-
充実した研修制度
毎年、IT技術のトレンドや社員の要望に合わせて、カリキュラムを刷新し展開しています。社内講師の丁寧なサポートを受けながら、自分のペースで学ぶことができます。
-
資格取得を応援
スキルアップしたい社員を応援するために資格取得一時金制度を設けています。受験料(実費)と合わせて資格レベルに合わせた最大10万円の一時金も支給しています。
-
東証プライム上場企業グループ
オープンアップシステムは東証プライム上場「株式会社オープンアップグループ」のグループ企業です。
安定した経営基盤とグループ間のスムーズな連携でコロナ禍でも安定した雇用を実現させています。
株式会社オープンアップシステムに興味を持った方へ
株式会社オープンアップシステムでは、開発系エンジニア・プログラマを募集しています。
年収をアップしたい!スキルアップしたい!大手の上流案件にチャレンジしたい!
まずは話だけでも聞いてみたい場合もOK。お気軽にご登録ください。


C#新着案件New Job
システム開発/東京都新宿区/【WEB面談可/C#経験者/20代前半の方活躍中/経験1年以上の方活躍中】/在宅勤務
月給29万~34万円東京都新宿区(新宿駅)システム開発/東京都新宿区/【WEB面談可/C#経験者/20代後半~40代の方活躍中/経験年数不問】/在宅勤務
月給41万~50万円東京都新宿区(新宿駅)デバック、テスト項目の作成/神奈川県横浜市/【WEB面談可/C#経験者/20代前半の方活躍中/経験1年以上の方活躍中】/在宅勤務
月給29万~34万円神奈川県横浜市(桜木町駅)デバック、テスト項目の作成/神奈川県横浜市/【WEB面談可/C#経験者/20代後半~40代の方活躍中/経験年数不問】/在宅勤務
月給41万~50万円神奈川県横浜市(桜木町駅)基幹システム開発導入/東京都新宿区/【WEB面談可/C#経験者/20代前半の方活躍中/経験1年以上の方活躍中】/在宅勤務
月給29万~34万円東京都新宿区(西新宿駅)基幹システム開発導入/東京都新宿区/【WEB面談可/C#経験者/20代後半~40代の方活躍中/経験年数不問】/在宅勤務
月給41万~50万円東京都新宿区(西新宿駅)