0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

VB.NET / C# の Windows Forms でフォーム切り替え時に起こる「ちらつき」の解決方法

Posted at

VB.NET / C# の Windows Forms でフォーム切り替え時に起こる「ちらつき」の解決方法:point_up:

はじめまして。
理学療法士からシステムエンジニアに転職した25歳のパパ、ましろと申します。
現場では Laravel と VB.NET(WinForms) を中心に開発しています。

今回は、実務で遭遇した フォーム切り替え時の“ちらつき問題” の対処法を共有します。

Double BufferedをTrueにしても、コンポーネントのBackColorのTransparentを諦めても
解決しなかった方は、ぜひ今回のソースを参考にしていただけたらと思います。

では結論から。

'VB.NET
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
     Dim newForm As New 画面2
     newForm.Opacity = 0
     newForm.Show()
     Application.DoEvents()
     newForm.Opacity = 1
     Me.Visible = False
 End Sub
//C#
Private void Button1_Click(object sender, EventArgs e)
 {
     var newForm = new 画面2();
     newForm.Opacity = 0;
     newForm.Show();
     Application.DoEvents();
     newForm.Opacity = 1;
     this.Visible = False;
 }

この記述方法で「ちらつき」を解決することができます。

<以下説明>
スタートアップウィンドウを画面1として、
画面1のコンポーネントであるボタン1をクリックすると画面2に遷移するというシステムを
想定しています。
その画面2に遷移する際の「ちらつき」を解決していきます。

今回紹介するソースは
画面2のデザインにピクチャーボックスやボタンなどが多く配置され、backcolorがtransparent(背景透かし)であるなど、処理が重たくなっている状態にも対応できます。

では、各ステートメントごとに解説していきます。

'VB.NET
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
//C#
Private void Button1_Click(object sender,  EventArgs e)

これはボタン1がクリックされた時に実行されるイベントハンドラの定義です。
(※ このように、メソッド名・引数・戻り値の形をまとめて “メソッドシグネチャ”
と呼びます。)

'VB.NET
 Dim newForm As New 画面2
//C#
var newForm = new 画面2();

これはローカル変数を用意して新しいフォームである"画面2"を代入しています。
ここでは変数に代入しているだけなので何も起きません。
(※ オブジェクトを作成しているNewをコンストラクタと呼びます)
コンストラクタではない表示方法も後述します。

'VB.NET
newForm.Opacity = 0
//C#
newForm.Opacity = 0;

さて、ここからが本題である「ちらつき」解決のミソになります。
Opacityとは不透明度の意味で初期値が1になります。
今回は イコール0とすることで不透明ではない。つまり、透明の状態にしています。
newFormを透明。つまりボタン1をクリックしたときに表示される”画面2”を
透明にしています。

'VB.NET
newForm.Show()
//C#
newForm.Show();

これはnewFormを表示する。つまり画面2を表示させるメソッドです。
(※ Show()はモードレスで表示、ShowDialog()はモーダルで表示します。)
これをOpacity = 0 のコードの下に記述することで画面2を透明にして表示する
という処理ができます。

'VB.NET
Application.DoEvents()
//C#
Application.DoEvents();

WindowsFormの切り替えでちらつく原因は、ビルドした際にビジュアルスタジオ上の
デザインで配置した各コンポーネントをフォームに配置している最中にも関わらず画面を
表示するからです。いわゆる画面の描画中に表示している状態、、
上記のコードではその処理を指しています。

(※ Double Bufferedがデザイン上で初期値がFalseになっているのでTrueにすると「ちらつき」が解消するという情報はたくさん出てきますが、WindowsFormの描画がGDIというのもありDouble Bufferedはそこまで強力ではないうえ、デザインからはフォームにしか適応できず
ピクチャーボックス等のコンポーネントにはソースにDouble Bufferedのコントロールを
直接組み込まないといけないので、かなり面倒 ... )

'VB.NET
newForm.Opacity = 1
//C#
newForm.Opacity = 1;

Opacityプロパティに1を代入することで不透明にしています。
不透明にすることでユーザーが見えるようになります。

一度ここまでをまとめると
ボタン1をクリックすると、画面2を透明にして表示する→各コンポーネント
を画面2に配置し終わるのを待つ→配置し終わったら画面2の透明を解除する。

このロジックを組み込むことでピクチャーボックス等のtransparentが多くても、
画面切り替えの際に「ちらつく」ことなくスムーズに切り替えられます。

'VB.NET
Me.visible = False
//C#
this.visible = False;

ここはHide()でもClose()でも問題ないのですが、Opacity = 1より下に記述してください。
理由は、画面2の透明を解除する前に画面1を閉じてしまうと
何も表示されない時間が生まれるからです。
(一瞬ではありますが。。それゆえ「ちらつき」ます。)

先述したコンストラクタではない表示法も提示しておきます。

'VB.NET
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
     画面2.Opacity = 0
     画面2.Show()
     Application.DoEvents()
     画面2.Opacity = 1
     Me.Visible = False
 End Sub
//C#
Private void Button1_Click(object sender, EventArgs e)
 {
     画面2.Opacity = 0;
     画面2.Show();
     Application.DoEvents();
     画面2.Opacity = 1;
     this.Visible = False;
 }

先程のローカル変数の部分をインスタンスに変えただけです。

以上がVB.NET / C# の Windows Forms でフォーム切り替え時に起こる
「ちらつき」の解決方法 でした。

補足)
今回、クリックイベント時に実行されるように記述していますが
画面2読み込み時に本ロジックを実行すればよいのでは?
という考えもあるかと思います。
ソースとしては

'VB.NET
Private Sub 画面2_load(sender As Object, e As EventArgs) Handles Me.Load
Me.Opacity = 0
Me.show()
End Sub
------------------------------------------------------------------------
Private Sub 画面2_shown(sender As Object, e As EventArgs) Handles Me.shown
Application.DoEvents()
Me.Opacity = 1
End Sub
//C#
Private void 画面2.Load(object sender, EventArgs e)
{
this.Opacity = 0;
this.show();
}
--------------------------------------------------------------
Private void 画面2.Shown(object sender, EventArgs e)
{
Application.DoEvents();
this.Opacity = 1;
}

このようになると思います。
これは間違った記述方法ですが、そのまま進めます。
上記のコードは実行すると「ちらつき」ます。
それはLoadイベントでは暗黙的にshowメソッドも実行されるからです。
つまりshowした後に透明になるという、本題に反する動きをしてしまいます。

暗黙的にshowメソッドが実行されるため、上記Loadイベントハンドラ内の
Me.show()およびthis.show();はゾンビコードになります。

今回の方法はクリックイベント時に実行するのが確実です。

フォーム切り替え時のちらつきでお困りの方はぜひ試してみてください。

ステートメントごとに解説しているので、
フォーム切り替え時の「ちらつき」でお困りの方以外にも参考になると思います。
最後までご覧いただき、ありがとうございました。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?