質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

4回答

8276閲覧

画面遷移の際に生じる ちらつきをなくしたいです。

aya5kishi

総合スコア8

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

0クリップ

投稿2022/01/10 01:43

解決したいこと
・下記の画像の通り、メニューバーを作成したのですが画面遷移をする際に、遷移後のFormが開くことによって生じる画面のちらつきをなくしたいです。
イメージ説明
ちらつきをなくしたいのですが、なるべくコードは、基底クラスでメニューバー生成処理を記述して、そのメニューバーを派生クラスで利用する形にしたいです。
自分で試してみたこととして、DoubleBufferedを有効にするためにコンストラクタに、「this.DoubleBuffered = true;」や「SetStyle(ControlStyles.OptimizedDoubleBuffer, true); SetStyle(ControlStyles.AllPaintingInWmPaint, true);」を追加してみたのですが、画面のちらつきはなくなりませんでした。何か良い方法があればご教授いただけると幸いです。

コードは下記の通りとなります。

c#

1using System; 2using System.Collections.Generic; 3using System.ComponentModel; 4using System.Data; 5using System.Drawing; 6using System.Linq; 7using System.Text; 8using System.Threading.Tasks; 9using System.Windows.Forms; 10 11namespace WindowsFormsApp2 12{ 13 // 基底Formクラス 14 public partial class FormBase : Form 15 { 16 private Label menuberLbl; // メニューバー表示に利用するラベル 17 public static int LBL_CNT = 4; // メニューバーで表示するラベルの数 18 private Panel menuPnl; // メニューバー生成時にラベルを張り付けるためのパネル 19 20 public FormBase() 21 { 22 InitializeComponent(); 23 // 全画面表示 24 this.WindowState = FormWindowState.Maximized; 25 26 // メニューバー作成処理 27 // パネル生成処理 28 menuPnl = new Panel(); 29 menuPnl.Location = new Point(90,50); 30 menuPnl.Size = new Size(240, 30); 31 menuPnl.BackColor = Color.FromArgb(255, 255, 255); 32 this.Controls.Add(menuPnl); 33 34 // ラベル生成処理 35 List<Label> lblList = new List<Label>(); 36 for (int i = 0; i < LBL_CNT; i++) 37 { 38 menuberLbl = new Label(); 39 menuberLbl.Name = "lbl" + (i+1); 40 menuberLbl.Font = new Font("MS UI Gothic", float.Parse("9.75"), FontStyle.Bold); 41 menuberLbl.TextAlign = ContentAlignment.MiddleLeft; 42 menuberLbl.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; 43 menuberLbl.AutoSize = false; 44 menuberLbl.Size = new Size(60, 30); 45 menuberLbl.Location = new Point(1+(60 * i), 1); 46 menuberLbl.BackColor = Color.FromArgb(255, 255, 255); 47 menuberLbl.ForeColor = Color.FromArgb(0, 0, 0); 48 menuberLbl.Text = "メニュー" + (i + 1); 49 menuberLbl.Click += new EventHandler(sideLbl_Click); 50 lblList.Add(menuberLbl); 51 } 52 foreach (Label lbl in lblList) 53 { 54 menuPnl.Controls.Add(lbl); 55 menuberLbl.BringToFront(); 56 } 57 58 } 59 60 // 画面遷移 61 private void sideLbl_Click(object sender, EventArgs e) 62 { 63 if (((Label)sender).Name == "lbl1") 64 { 65 Form1 f1 = new Form1(); 66 f1.Show(); 67 this.Visible = false; 68 } 69 else if (((Label)sender).Name == "lbl2") 70 { 71 Form1 f1 = new Form1(); 72 f1.Show(); 73 this.Visible = false; 74 } 75 else if (((Label)sender).Name == "lbl3") 76 { 77 Form1 f1 = new Form1(); 78 f1.Show(); 79 this.Visible = false; 80 } 81 else if (((Label)sender).Name == "lbl4") 82 { 83 Form1 f1 = new Form1(); 84 f1.Show(); 85 this.Visible = false; 86 } 87 } 88 } 89}

c#

1using System; 2using System.Collections.Generic; 3using System.ComponentModel; 4using System.Data; 5using System.Drawing; 6using System.Linq; 7using System.Text; 8using System.Threading.Tasks; 9using System.Windows.Forms; 10 11namespace WindowsFormsApp2 12{ 13 public partial class Form1 : FormBase 14 { 15 public Form1() 16 { 17 InitializeComponent(); 18 } 19 } 20}

お手数をおかけしますがどうぞよろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KOZ6.0

2022/01/10 05:53

このコードだとラベルをクリックするたびに Form1 がどんどん生成されて、画面を閉じても終了できないんですが、その辺はどう考えてますか?
aya5kishi

2022/01/10 12:59

返信が遅くなってしまい申し訳ございません。 重要なご指摘ありがとうございます。 ご指摘の通り、画面を閉じても終了しない点については考慮が欠けていました。 自分でも調べてみて下記のように画面遷移のコードを変更してみました。 下記のコードで考慮が足りない場合は、ご指摘いただけると幸いです。 if (((Label)sender).Name == "lbl1") { Form1 f1 = new Form1(); f1.Owner = this; f1.Show(); this.Hide(); f1.Owner.Show(); f1.Close(); }
KOZ6.0

2022/01/10 13:47

それだと f1 のインスタンスを立ち上げて、一瞬表示した後閉じてるので意味がありません。
aya5kishi

2022/01/10 15:06

Runメソッドの引数を変更するようにコードを修正してみようと思います。
guest

回答4

0

新しいフォームを表示後、古いフォームを即座に非表示にすると、新しいフォームの描画が完了する前に古いフォームの表示が消えるのでチラツキが発生します。

新しいフォームの表示を完了してから、少し遅延を掛けて元のフォームを閉じればマシにはなるでしょう。例えば、下記のような拡張メソッドを作成し、

cs

1public static class FormExtention 2{ 3 private static ApplicationContext _context = new(); 4 5 public static void Transition(this Form formOld, Form formNew) 6 { 7 //古いフォームの位置とサイズを引き継ぐ 8 formNew.Location = formOld.Location; 9 formNew.StartPosition = FormStartPosition.Manual; 10 formNew.Size = formOld.Size; 11 formNew.WindowState = formOld.WindowState; 12 13 // 新フォーム表示後に、時間差で古いフォームを閉じる 14 EventHandler handler = null; 15 handler = async (sender, e) => 16 { 17 formNew.VisibleChanged -= handler; 18 _context.MainForm = formNew; 19 await Task.Delay(20); 20 formOld.Close(); 21 }; 22 formNew.VisibleChanged += handler; 23 24 formNew.Show(); 25 } 26 27 public static void Run(this Form form) 28 { 29 _context.MainForm = form; 30 Application.Run(_context); 31 } 32}

次に、Program.cs の Application.Run(new フォーム名()) を、new フォーム名().Run() に書き換えます。

cs

1internal static class Program 2{ 3 [STAThread] 4 static void Main() 5 { 6 ApplicationConfiguration.Initialize(); 7 new Form1().Run(); 8 } 9}

あとは、Form.Show の代わりに Transition を呼び出します。
(thisを省略すると拡張メソッドと認識してくれません)

cs

1public partial class Form1 : Form 2{ 3 public Form1() 4 { 5 InitializeComponent(); 6 } 7 8 private void button1_Click(object sender, EventArgs e) 9 { 10 this.Transition(new Form2()); 11 } 12}

完全な解決策という訳ではなく、最大化状態から次の画面遷移してサイズを元に戻した時に、前の画面の位置の復元をどうするか、フォームをクローズせずに非表示で維持したい場合はどうするかとか、他にも考慮すべき点はありますので、そのへんは工夫してください。

投稿2022/01/11 05:09

編集2022/01/11 05:11
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ウィンドウ内遷移?は、UserControlでやるのがいいんじゃないでしょうか?
【C#】ウィンドウ内での画面遷移をコントロール切り替えで実装 - いつもの作業の備忘録

【C#】画面遷移1(ユーザーコントロールを使う) - memo

Formの中にFormを入れることもできるようですが、単独でも出したいとかそういうときなんでしょうかね??
【C#】Formの中にFormを表示して良い感じに切り替える | エンジニアが送る穴倉生活のすゝめ

UserControlにするまでもないような簡単な内容なら、TabControlで作っておいてタブを消すような手もあります。
C# - C#での画面遷移の仕方を教えてください|teratail

UserControlを作った場合でも、TabControlは遷移処理に便利に使えます。


あげた例はどれもインスタンスを保持する作りですが、都度newするような作りでもいいでしょう(どちらがいいかは場合によるので何とも言えませんが^^;

投稿2022/01/10 21:43

TN8001

総合スコア9862

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

やりたいことがいまいち不明ですが、ウインドウ(Form) を切り替えるとどうしてもちらつくので、中身を初期化する方向で考えてみては?

FormBase(Form1 のクライアント領域に張り付ける)

C#

1using System; 2using System.Collections.Generic; 3using System.Drawing; 4using System.Windows.Forms; 5 6public partial class FormBase : Form 7{ 8 private Label menuberLbl; // メニューバー表示に利用するラベル 9 public static int LBL_CNT = 4; // メニューバーで表示するラベルの数 10 private Panel menuPnl; // メニューバー生成時にラベルを張り付けるためのパネル 11 12 public FormBase() : this(-1) { } 13 14 public FormBase(int index) { 15 InitializeComponent(); 16 17 //// 全画面表示 18 //this.WindowState = FormWindowState.Maximized; ←やめる 19 20 // パネル生成処理 21 menuPnl = new Panel(); 22 menuPnl.Location = new Point(90, 50); 23 menuPnl.Size = new Size(240, 30); 24 menuPnl.BackColor = Color.FromArgb(255, 255, 255); 25 this.Controls.Add(menuPnl); 26 27 List<Label> lblList = new List<Label>(); 28 for (int i = 0; i < LBL_CNT; i++) { 29 menuberLbl = new Label(); 30 menuberLbl.Name = "lbl" + (i + 1); 31 menuberLbl.Font = new Font("MS UI Gothic", float.Parse("9.75"), FontStyle.Bold); 32 menuberLbl.TextAlign = ContentAlignment.MiddleLeft; 33 menuberLbl.AutoSize = false; 34 menuberLbl.Size = new Size(60, 30); 35 menuberLbl.Location = new Point(1 + (60 * i), 1); 36 // どこをクリックしたかわかるように 37 if (i == index) { 38 menuberLbl.BorderStyle = BorderStyle.None; 39 menuberLbl.BackColor = Color.Black; 40 menuberLbl.ForeColor = Color.White; 41 } else { 42 menuberLbl.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; 43 menuberLbl.BackColor = Color.White; 44 menuberLbl.ForeColor = Color.Black; 45 } 46 menuberLbl.Text = "メニュー" + (i + 1); 47 menuberLbl.Click += new EventHandler(sideLbl_Click); 48 lblList.Add(menuberLbl); 49 } 50 foreach (Label lbl in lblList) { 51 menuPnl.Controls.Add(lbl); 52 menuberLbl.BringToFront(); 53 } 54 55 // Control と同様に扱う 56 TopLevel = false; 57 FormBorderStyle = FormBorderStyle.None; 58 Dock = DockStyle.Fill; 59 } 60 61 private void sideLbl_Click(object sender, EventArgs e) { 62 // 新しいインスタンスを作成 63 string[] labelNames = new string[] { "lbl1", "lbl2", "lbl3", "lbl4" }; 64 int index = Array.IndexOf(labelNames, ((Label)sender).Name); 65 Form f = new FormBase(index) { Visible = true }; 66 Parent.Controls.Add(f); 67 f.BringToFront(); 68 69 // (前の状態が不要なら)自分を破棄する 70 Parent.Controls.Remove(this); 71 Dispose(); 72 } 73} 74

C#

1using System.Windows.Forms; 2 3public partial class Form1 : Form 4{ 5 public Form1() { 6 InitializeComponent(); 7 Controls.Add(new FormBase() { Visible = true}); 8 } 9}

投稿2022/01/10 15:12

KOZ6.0

総合スコア2707

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

aya5kishi

2022/01/10 15:54

ご回答ありがとうございます。 画面のちらつきがなくなりとても助かりました。中身を初期化する方向でコードを書いていこうと思います。 自分の技術レベルが低いこともあり、まだコード内容を理解できていませんが、明日ご教授いただいたコードを参考にして調べていこうと思います。
aya5kishi

2022/01/10 16:08

1点ご教授いただきたいのですが、全画面表示は何故削除したほうが良いのでしょうか? Formアプリケーション開発では、全画面表示をせずに、画面を固定して開発することが多いのでしょうか? 私は実務経験がないため、開発現場ではどうなのかとても気になりました。(開発するアプリや現場にもよるとは思いますが、一般的にはどうなのでしょうか?)
KOZ6.0

2022/01/10 23:04

FormBase は Form1 のコントロールになるので最大化は意味ありません。 やるなら Form1 を最大化させることになりますね。 OnParnetChanged で Parent != null なら最大化させることになるでしょう
guest

0

ベストアンサー

画面がちらつく理由としてはメニューバーが毎回newされているからだと思います。
メニューバーに使うコントロールはすべてstaticで宣言してFormBaseが作られる最初の1回だけnewするようにすると改善するかもしれません。
そのためには、コンストラクタ中のメニューバー作成処理をどうにかしないといけないのですが、簡単な方法としてはbool型のstatic変数を用意して初めてメニューバーが作成されたら変数をtrueにて2回目以降のnewをしないようにすればいいと思います。

C#

1public partial class FormBase : Form 2 { 3 private static Label menuberLbl; // メニューバー表示に利用するラベル 4 public static int LBL_CNT = 4; // メニューバーで表示するラベルの数 5 private static Panel menuPnl; // メニューバー生成時にラベルを張り付けるためのパネル 6 public static bool menu_initialized = false; //メニューバーが初期化されたかどうか 7 8 public FormBase() 9 { 10 if(!menu_initialized){ 11 // メニューバー作成処理 12 13 menu_initialized = true; // メニューバー初期化済み 14 } 15 }

投稿2022/01/10 05:14

編集2022/01/10 05:16
vann_2921

総合スコア190

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

aya5kishi

2022/01/10 13:06

返信が遅くなってしまい申し訳ございません。 ご回答頂きましてありがとうございます。 今からvann_2921さんのご回答をもとに自分でコードを記述してみて、わからない点があるかを確認いたしますので申し訳ないのですが、ベストアンサーボタンは明日には押せるようにいたします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問