解像度や画面サイズを意識しない画面レイアウト
端末の解像度やウィンドウサイズを意識せずに画面レイアウトを作成したいが、WinFormsのAnchorでは実現ができない。フォームサイズに合わせて自動で各コントロールのサイズを調整する仕組みをメモ
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
使い方
下記のようなベースフォームを作成する。
サイズを調整したいフォームにベースフォームを継承する。
BaseForm.vb
Public Class BaseForm
Private resizeHelper As clsResize
Public Sub New()
InitializeComponent()
OnLoad(EventArgs.Empty)
End Sub
Protected Overrides Sub OnLoad(e As EventArgs)
If Not DesignMode Then
MyBase.OnLoad(e)
resizeHelper = New clsResize(Me)
resizeHelper._get_initial_size()
End If
End Sub
Protected Overrides Sub OnResize(e As EventArgs)
If Not DesignMode Then
If resizeHelper Is Nothing Then
resizeHelper = New clsResize(Me)
resizeHelper._get_initial_size()
Else
resizeHelper._resize()
End If
End If
End Sub
End Class
Form1.Designer.vb
Partial Class Form1
Inherits BaseForm
End Class