解像度や画面サイズを意識しない画面レイアウト
端末の解像度やウィンドウサイズを意識せずに画面レイアウトを作成したいが、WinFormsのAnchorでは実現ができない。フォームサイズに合わせて自動で各コントロールのサイズを調整する必要があるが調べたところ既にC#公開されている方がいたのでそれをそのままVBにしたのを備忘録として残す。
参考
オリジナル
C# Resize ALL Controls at Runtime
上記のカスタム
C# 画面サイズに合わせて自由にControlsをリサイズ
Resizeクラス
下記クラスを作成する。
clsResize.vb
Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Text
Imports System.Windows.Forms
Public Class clsResize
Private _arr_control_storage As List(Of System.Drawing.Rectangle) = New List(Of System.Drawing.Rectangle)()
Private showRowHeader As Boolean = False
Private FontTable As Dictionary(Of String, Single)
Private ControlTable As Dictionary(Of String, System.Drawing.Rectangle)
Public Sub New(ByVal _form_ As Form)
form = _form_
_formSize = _form_.ClientSize
_fontsize = _form_.Font.Size
Dim _controls = _get_all_controls(form)
FontTable = New Dictionary(Of String, Single)()
ControlTable = New Dictionary(Of String, System.Drawing.Rectangle)()
For Each control As Control In _controls
FontTable.Add(control.Name, control.Font.Size)
ControlTable.Add(control.Name, control.Bounds)
Next
End Sub
Private _fontsize As Single
Private _formSize As System.Drawing.SizeF
Private form As Form
Public Sub _get_initial_size()
Dim _controls = _get_all_controls(form)
For Each control As Control In _controls
_arr_control_storage.Add(control.Bounds)
If control.[GetType]() = GetType(DataGridView) Then _dgv_Column_Adjust((CType(control, DataGridView)), showRowHeader)
Next
End Sub
Public Sub _resize()
Dim _form_ratio_width As Double = CDbl(form.ClientSize.Width) / CDbl(_formSize.Width)
Dim _form_ratio_height As Double = CDbl(form.ClientSize.Height) / CDbl(_formSize.Height)
Dim _controls = _get_all_controls(form)
Dim _pos As Integer = -1
For Each control As Control In _controls
Me._fontsize = FontTable(control.Name)
_pos += 1
Dim _controlSize As System.Drawing.Size = New System.Drawing.Size(CInt((_arr_control_storage(_pos).Width * _form_ratio_width)), CInt((_arr_control_storage(_pos).Height * _form_ratio_height)))
Dim _controlposition As System.Drawing.Point = New System.Drawing.Point(CInt((_arr_control_storage(_pos).X * _form_ratio_width)), CInt((_arr_control_storage(_pos).Y * _form_ratio_height)))
control.Bounds = New System.Drawing.Rectangle(_controlposition, _controlSize)
If control.[GetType]() = GetType(DataGridView) Then _dgv_Column_Adjust((CType(control, DataGridView)), showRowHeader)
control.Font = New System.Drawing.Font(form.Font.FontFamily, CSng((((Convert.ToDouble(_fontsize) * _form_ratio_width) / 2) + ((Convert.ToDouble(_fontsize) * _form_ratio_height) / 2))))
Next
End Sub
Private Sub _dgv_Column_Adjust(ByVal dgv As DataGridView, ByVal _showRowHeader As Boolean)
Dim intRowHeader As Integer = 0
Const Hscrollbarwidth As Integer = 5
If _showRowHeader Then
intRowHeader = dgv.RowHeadersWidth
Else
dgv.RowHeadersVisible = False
End If
For i As Integer = 0 To dgv.ColumnCount - 1
If dgv.Dock = DockStyle.Fill Then
dgv.Columns(i).Width = ((dgv.Width - intRowHeader) / dgv.ColumnCount)
Else
dgv.Columns(i).Width = ((dgv.Width - intRowHeader - Hscrollbarwidth) / dgv.ColumnCount)
End If
Next
End Sub
Private Shared Function _get_all_controls(ByVal c As Control) As IEnumerable(Of Control)
Return c.Controls.Cast(Of Control)().SelectMany(Function(item) _get_all_controls(item)).Concat(c.Controls.Cast(Of Control)()).Where(Function(control) control.Name <> String.Empty)
End Function
End Class
使い方
①LoadイベントでResizeクラスの_get_initial_sizeを呼ぶ
②SizeChangedイベントでResizeクラスの_resizeを呼ぶ
TestForm.vb
Public Class TestForm
Private _form_resize As clsResize
Public Sub New()
InitializeComponent()
_form_resize = New clsResize(Me)
AddHandler Me.Load, AddressOf TestForm_Load
AddHandler Me.SizeChanged, AddressOf TestForm_SizeChanged
End Sub
Private Sub TestForm_Load(sender As Object, e As EventArgs)
_form_resize._get_initial_size()
End Sub
Private Sub TestForm_SizeChanged(sender As Object, e As EventArgs)
_form_resize._resize()
End Sub
End Class