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

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

新規登録して質問してみよう
ただいま回答率
85.49%
VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

Q&A

解決済

1回答

10689閲覧

SuspendLayoutがうまくいかない。

hanbee.com

総合スコア52

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

0グッド

0クリップ

投稿2021/05/08 09:13

編集2021/05/08 09:16

お世話になっております。

SuspendLayout、ResumeLayoutについて質問させていただきます。
動作を模擬したサンプルを作成しました。

フォームのサイズチェンジの割合に合わせて、子コントロールのサイズを追従させるメソッドFormScalingを使って、Form1_Loadイベントの最後でフォームを最大化し、動的に作成したbutton1は初期値のサイズ(100,100)ではなく、(312,211)になります。

次にReloadイベントで、button1を消して、フォームのサイズを初期値の(500,500)にします。
そしてもう一度Form1_Loadイベントを呼び出して再び(312,211)のサイズのbutton1を生成するという動作です。

この動作で、ReloadイベントはSuspendLayout、ResumeLayoutで囲っているのに、一瞬フォームが初期値の(500,500)に戻って最大化するのが見えてしまっています。
またここで模擬している実際のアプリでは動作が遅いタブレットPCを使っているのですが、複数のコントロールがフォームが縮小するのにも追従して、最大化するのにも追従している過程が見えてしまっています。
この動作に時間がかかっているため、見栄えが悪くなっています。

ここを見せないためにSuspendLayout、ResumeLayoutを使っているつもりでしたが、
無理なのでしょうか。SuspendLayout、ResumeLayoutをコメントアウトしても動作は変わりません。

ご存じの方教えていただけないでしょうか。宜しくお願いします。

以下がFormScalingのメソッドです。

vb.net

1Module resolution 2 Private originalSize_bin As Size ' -- コントロール・スケーリング用オリジナルサイズ 3 Public Sub FormScaling(sender As Object) 4 originalSize_bin = sender.ClientSize 5 ' --- フォーム上のコントロールのサイズと位置を調整 6 If Not (sender.WindowState = FormWindowState.Minimized) Then 7 ' --- サイズファクターの決定 8 Dim sfWidth As Single = (sender.ClientSize.Width / sender.originalSize.Width) 9 Dim sfHeight As Single = (sender.ClientSize.Height / sender.originalSize.Height) 10 Dim sizeFactor As New SizeF(sfWidth, sfHeight) 11 ' --- 各コントロールのスケーリング 12 For Each ctrl As Control In sender.Controls 13 If (TypeOf ctrl Is ListBox) Then 14 DirectCast(ctrl, ListBox).IntegralHeight = False 15 End If 16 If (TypeOf ctrl Is ComboBox) Then 17 DirectCast(ctrl, ComboBox).IntegralHeight = False 18 End If 19 ' --- フォントのスケーリング 20 Dim fntScale As Single = (ctrl.Font.Size * sizeFactor.Height) 21 ctrl.Font _ 22 = New Font(ctrl.Font.FontFamily, fntScale, ctrl.Font.Style, ctrl.Font.Unit) 23 ' --- コントロールのスケーリング 24 ctrl.Scale(sizeFactor) 25 Next 26 ' --- オリジナルサイズに保存 27 sender.originalSize = originalSize_bin 28 End If 29 End Sub 30End Module

以下がForm1クラスのソースコードです。

Public Class Form1 Public moni_height As Integer Public moni_width As Integer ' --- 変数宣言 Public originalSize As Size ' -- コントロール・スケーリング用オリジナルサイズ Public Sub New() '現在フォームが存在しているディスプレイの高さと幅を取得 Dim h As Integer = System.Windows.Forms.Screen.GetBounds(Me).Height Dim w As Integer = System.Windows.Forms.Screen.GetBounds(Me).Width moni_height = h moni_width = w ' この呼び出しはデザイナーで必要です。 InitializeComponent() ' InitializeComponent() 呼び出しの後で初期化を追加します。 End Sub Private Sub Form1_SizeChanged(sender As Object, e As EventArgs) _ Handles MyBase.SizeChanged FormScaling(Me) End Sub 'フォームのLoadイベントハンドラ Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load 'Buttonクラスのインスタンスを作成する Me.Button1 = New System.Windows.Forms.Button() 'Buttonコントロールのプロパティを設定する Me.Button1.Name = "Button1" 'サイズと位置を設定する Me.Button1.Location = New Point(0, 0) Me.Button1.Size = New System.Drawing.Size(100, 100) 'Clickイベントハンドラを追加する AddHandler Me.Button1.Click, AddressOf reload 'フォームに追加する Me.Controls.Add(Me.Button1) '最大化する(後で縮小できるようにFormWindowState.Maximizedとはしない) Me.Top = 0 Me.Left = 0 Me.Height = moni_height - 10 Me.Width = moni_width - 10 Me.Button1.Text = Button1.Size.ToString End Sub Private Sub Reload(sender As Object, e As EventArgs) Button1.Dispose() Me.SuspendLayout() 'フォームのサイズをデザイナーの初期値にする Me.Size = New Size(500, 500) Call Form1_Load(sender, e) Me.ResumeLayout() End Sub End Class

実行して以下のようになる
イメージ説明

以上、長文失礼しました。

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

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

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

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

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

guest

回答1

0

ベストアンサー

Me.SuspendLayoutを行うとフォームのレイアウトロジックが一時停止します。
レイアウトロジックは止まりますが再描画が止まるわけではありません。また、配置されているコントロールのレイアウトロジックが止まるわけでもありません。
また、レイアウトロジックが止まってもSizeChangedイベントは発生します。

なので、SuspendLayoutを行ってもコントロールのスケーリングを行うFormScalingは実行されますし、その中でスケーリングが行われるコントロールも再描画されることになります。

フォームのサイズをプログラムのみで変更するのであれば、SizeChangedイベントではなくLayoutイベントを使用してスケーリングを行うようにすれば、SuspendLayoutResumeLayoutの間はLayoutイベントが発生しないので、最終的なフォームサイズでスケーリングが行えるかと思います。
手動でフォームのリサイズを行うのであれば、ResizeBeginイベントSuspendLayoutし、ResizeEndイベントResumeLayoutを行うようにするなど工夫すればリサイズ中はスケーリングが行われず、ドラッグを終了してサイズが確定した時にスケーリングが行われます。

投稿2021/05/09 02:17

YAmaGNZ

総合スコア10242

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

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

hanbee.com

2021/05/09 11:57

YAmaGNZ様、ご回答ありがとうございます。 そもそも間違った動作ではなかったということですね。 SizechangeイベントではなくLayoutイベントというものをいま試してみているところですが、 FormScalingのメソッドのところで違うエラーが起こっているので、 もうちょっと格闘したいと思います。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問