Resize ALL Controls at Runtime in C# và Visual Basic 6

Khi lập trình winform, các control thường được bố trí hợp lý so với kích thước form của nó. Nhưng vấn đề là: các phần mềm mình viết ra không chỉ chạy trên mật máy tính với kích thước màn hình cố định (độ phân giải cố định) và người dùng muốn thay đổi kích thước form thì các control trên đó "bị vỡ".

 

A> Resize ALL Controls at Runtime in C#

Có nhiều người sử dụng : Dock và Anchor nhưng cũng có những bất tiện nhất định

Tôi đã tìm thấy trên codeproject một class trong c# có thể thực hiện việc này khá hay

1. Thêm vào chương trình của mình một calss và copy đoạn code sau:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

public class clsResize {
 List < System.Drawing.Rectangle > _arr_control_storage = new List < System.Drawing.Rectangle > ();
 private bool showRowHeader = false;
 public clsResize(Form _form_) {
  form = _form_; //the calling form
  _formSize = _form_.ClientSize; //Save initial form size
  _fontsize = _form_.Font.Size; //Font size
 }

 private float _fontsize {
  get;
  set;
 }

 private System.Drawing.SizeF _formSize {
  get;
  set;
 }

 private Form form {
  get;
  set;
 }

 public void _get_initial_size() //get initial size//
  {
   var _controls = _get_all_controls(form); //call the enumerator
   foreach(Control control in _controls) //Loop through the controls
    {
     _arr_control_storage.Add(control.Bounds); //saves control bounds/dimension
     //If you have datagridview
     if (control.GetType() == typeof(DataGridView))
      _dgv_Column_Adjust(((DataGridView) control), showRowHeader);
    }
  }

 public void _resize() //Set the resize
  {
   double _form_ratio_width = (double) form.ClientSize.Width / (double) _formSize.Width; //ratio could be greater or less than 1
   double _form_ratio_height = (double) form.ClientSize.Height / (double) _formSize.Height; // this one too
   var _controls = _get_all_controls(form); //reenumerate the control collection
   int _pos = -1; //do not change this value unless you know what you are doing
   foreach(Control control in _controls) {
    // do some math calc
    _pos += 1; //increment by 1;
    System.Drawing.Size _controlSize = new System.Drawing.Size((int)(_arr_control_storage[_pos].Width * _form_ratio_width),
     (int)(_arr_control_storage[_pos].Height * _form_ratio_height)); //use for sizing

    System.Drawing.Point _controlposition = new System.Drawing.Point((int)
     (_arr_control_storage[_pos].X * _form_ratio_width), (int)(_arr_control_storage[_pos].Y * _form_ratio_height)); //use for location

    //set bounds
    control.Bounds = new System.Drawing.Rectangle(_controlposition, _controlSize); //Put together

    //Assuming you have a datagridview inside a form()
    //if you want to show the row header, replace the false statement of
    //showRowHeader on top/public declaration to true;
    if (control.GetType() == typeof(DataGridView))
     _dgv_Column_Adjust(((DataGridView) control), showRowHeader);

    //Font AutoSize
    control.Font = new System.Drawing.Font(form.Font.FontFamily,
     (float)(((Convert.ToDouble(_fontsize) * _form_ratio_width) / 2) +
      ((Convert.ToDouble(_fontsize) * _form_ratio_height) / 2)));

   }
  }

 private void _dgv_Column_Adjust(DataGridView dgv, bool _showRowHeader) //if you have Datagridview
  //and want to resize the column base on its dimension.
  {
   int intRowHeader = 0;
   const int Hscrollbarwidth = 5;
   if (_showRowHeader)
    intRowHeader = dgv.RowHeadersWidth;
   else
    dgv.RowHeadersVisible = false;

   for (int i = 0; i < dgv.ColumnCount; i++) {
    if (dgv.Dock == DockStyle.Fill) //in case the datagridview is docked
     dgv.Columns[i].Width = ((dgv.Width - intRowHeader) / dgv.ColumnCount);
    else
     dgv.Columns[i].Width = ((dgv.Width - intRowHeader - Hscrollbarwidth) / dgv.ColumnCount);
   }
  }

 private static IEnumerable < Control > _get_all_controls(Control c) {
  return c.Controls.Cast < Control > ().SelectMany(item =>
   _get_all_controls(item)).Concat(c.Controls.Cast < Control > ()).Where(control =>
   control.Name != string.Empty);
 }
}

2. Trong form của mình:

public partial class Form1: Form {
  clsResize _form_resize;

  public Form1() {
   InitializeComponent();

   _form_resize = new clsResize(this);
   this.Load += _Load;
   this.Resize += _Resize;
  }
  private void _Load(object sender, EventArgs e) {
   _form_resize._get_initial_size();
  }

  private void _Resize(object sender, EventArgs e) {
   _form_resize._resize();
  }
  .....................................

 

Như vậy khi thay đổi kích thước form thì các control cũng thay đổi theo tỷ lệ thích hợp

B> Resize ALL Controls at Runtime in Visual Basic 6

Trong Visual Basic 6 không có tính năng Dock hay Anchor và  tôi cũng đã từng sử dụng một modul có tính năng tương tự: "AutoResize.bas "

1. Toàn bộ code của modul như sau:

Public Type ctrObj
Name As String
Index As Long
Parrent As String
Top As Long
Left As Long
Height As Long
Width As Long
ScaleHeight As Long
ScaleWidth As Long
FontSize As Integer
End Type

Private FormRecord() As ctrObj
Private ControlRecord() As ctrObj
Private bRunning As Boolean
Private MaxForm As Long
Private MaxControl As Long

Private Function ActualPos(plLeft As Long) As Long
If plLeft < 0 Then
ActualPos = plLeft + 75000
Else
ActualPos = plLeft
End If
End Function

Private Function FindForm(pfrmIn As Form) As Long
Dim i As Long

FindForm = -1
If MaxForm > 0 Then
For i = 0 To (MaxForm - 1)
If FormRecord(i).Name = pfrmIn.Name Then
	FindForm = i
	Exit Function
End If
Next i
End If
End Function

Private Function AddForm(pfrmIn As Form) As Long
Dim FormControl As Control
Dim i As Long
ReDim Preserve FormRecord(MaxForm + 1)

FormRecord(MaxForm).Name = pfrmIn.Name
FormRecord(MaxForm).Top = pfrmIn.Top
FormRecord(MaxForm).Left = pfrmIn.Left
FormRecord(MaxForm).Height = pfrmIn.Height
FormRecord(MaxForm).Width = pfrmIn.Width
FormRecord(MaxForm).ScaleHeight = pfrmIn.ScaleHeight

FormRecord(MaxForm).ScaleWidth = pfrmIn.ScaleWidth
AddForm = MaxForm
MaxForm = MaxForm + 1

For Each FormControl In pfrmIn
i = FindControl(FormControl, pfrmIn.Name)
If i < 0 Then i = AddControl(FormControl, pfrmIn.Name)
Next FormControl
End Function

Private Function FindControl(inControl As Control, inName As String) As Long
Dim i As Long

FindControl = -1
For i = 0 To (MaxControl - 1)
If ControlRecord(i).Parrent = inName Then
If ControlRecord(i).Name = inControl.Name Then
On Error Resume Next

If ControlRecord(i).Index = inControl.Index Then
	FindControl = i
	Exit Function
End If
On Error GoTo 0

End If
End If
Next i
End Function

Private Function AddControl(inControl As Control, inName As String) As Long
ReDim Preserve ControlRecord(MaxControl + 1)
On Error Resume Next

ControlRecord(MaxControl).Name = inControl.Name
ControlRecord(MaxControl).Index = inControl.Index
ControlRecord(MaxControl).Parrent = inName

If TypeOf inControl Is Line Then
ControlRecord(MaxControl).Top = inControl.y1
ControlRecord(MaxControl).Left = ActualPos(inControl.x1)
ControlRecord(MaxControl).Height = inControl.y2
ControlRecord(MaxControl).Width = ActualPos(inControl.x2)
Else
ControlRecord(MaxControl).Top = inControl.Top
ControlRecord(MaxControl).Left = ActualPos(inControl.Left)
ControlRecord(MaxControl).Height = inControl.Height
ControlRecord(MaxControl).Width = inControl.Width
End If
'
If TypeOf inControl Is Label Or TypeOf inControl Is TextBox Then

If TypeOf inControl Is Station Then
ControlRecord(MaxControl).FontSize = inControl.Font.Size
End If

ControlRecord(MaxControl).FontSize = inControl.Font.Size
End If

inControl.IntegralHeight = False

On Error GoTo 0
AddControl = MaxControl
MaxControl = MaxControl + 1
End Function

Private Function PerWidth(pfrmIn As Form) As Long
Dim i As Long

i = FindForm(pfrmIn)
If i < 0 Then i = AddForm(pfrmIn)

PerWidth = (pfrmIn.ScaleWidth * 100) \ FormRecord(i).ScaleWidth
End Function

Private Function PerHeight(pfrmIn As Form) As Single
Dim i As Long

i = FindForm(pfrmIn)
If i < 0 Then i = AddForm(pfrmIn)

PerHeight = (pfrmIn.ScaleHeight * 100) \ FormRecord(i).ScaleHeight
End Function

Private Sub ResizeControl(inControl As Control, pfrmIn As Form)
On Error Resume Next
Dim i As Long
Dim widthfactor As Single, heightfactor As Single
Dim minFactor As Single
Dim yRatio, xRatio, lTop, lLeft, lWidth, lHeight, lFontSize As Long

yRatio = PerHeight(pfrmIn)
xRatio = PerWidth(pfrmIn)
i = FindControl(inControl, pfrmIn.Name)

If inControl.Left < 0 Then
lLeft = CLng(((ControlRecord(i).Left * xRatio) \ 100) - 75000)
Else
lLeft = CLng((ControlRecord(i).Left * xRatio) \ 100)
End If

lTop = CLng((ControlRecord(i).Top * yRatio) \ 100)
lWidth = CLng((ControlRecord(i).Width * xRatio) \ 100)
lHeight = CLng((ControlRecord(i).Height * yRatio) \ 100)

If TypeOf inControl Is Line Then
If inControl.x1 < 0 Then
inControl.x1 = CLng(((ControlRecord(i).Left * xRatio) \ 100) - 75000)
Else
inControl.x1 = CLng((ControlRecord(i).Left * xRatio) \ 100)
End If

inControl.y1 = CLng((ControlRecord(i).Top * yRatio) \ 100)
If inControl.x2 < 0 Then
inControl.x2 = CLng(((ControlRecord(i).Width * xRatio) \ 100) - 75000)
Else
inControl.x2 = CLng((ControlRecord(i).Width * xRatio) \ 100)
End If

inControl.y2 = CLng((ControlRecord(i).Height * yRatio) \ 100)
Else
inControl.Move lLeft, lTop, lWidth, lHeight
inControl.Move lLeft, lTop, lWidth
inControl.Move lLeft, lTop
End If

If TypeOf inControl Is Label Or TypeOf inControl Is TextBox Then

lFontSize = CLng((ControlRecord(i).FontSize * yRatio) \ 100)
inControl.Font.Size = lFontSize

End If

End Sub

Public Sub ResizeForm(pfrmIn As Form)
Dim FormControl As Control
Dim isVisible As Boolean
Dim StartX, StartY, MaxX, MaxY As Long
Dim bNew As Boolean

If Not bRunning Then
bRunning = True

If FindForm(pfrmIn) < 0 Then
bNew = True
Else
bNew = False
End If

If pfrmIn.Top < 30000 Then
isVisible = pfrmIn.Visible
On Error Resume Next

If Not pfrmIn.MDIChild Then
On Error GoTo 0
'pfrmIn.Visible = False
Else
If bNew Then
StartY = pfrmIn.Height
StartX = pfrmIn.Width
On Error Resume Next

For Each FormControl In pfrmIn
If FormControl.Left + FormControl.Width + 200 > MaxX Then _
MaxX = FormControl.Left + FormControl.Width + 200
If FormControl.Top + FormControl.Height + 500 > MaxY Then _
	MaxY = FormControl.Top + FormControl.Height + 500
	If FormControl.x1 + 200 > MaxX Then _
		MaxX = FormControl.x1 + 200
		If FormControl.y1 + 500 > MaxY Then _
			MaxY = FormControl.y1 + 500
			If FormControl.x2 + 200 > MaxX Then _
				MaxX = FormControl.x2 + 200
				If FormControl.y2 + 500 > MaxY Then _
					MaxY = FormControl.y2 + 500
				Next FormControl
				On Error GoTo 0

				pfrmIn.Height = MaxY
				pfrmIn.Width = MaxX
			End If
			On Error GoTo 0

		End If

		For Each FormControl In pfrmIn
			ResizeControl FormControl, pfrmIn
		Next FormControl
		On Error Resume Next

		If Not pfrmIn.MDIChild Then
			On Error GoTo 0
			pfrmIn.Visible = isVisible
		Else
			If bNew Then
				pfrmIn.Height = StartY
				pfrmIn.Width = StartX

				For Each FormControl In pfrmIn
					ResizeControl FormControl, pfrmIn
				Next FormControl
			End If
		End If
		On Error GoTo 0

	End If
	bRunning = False
End If
End Sub

Public Sub SaveFormPosition(pfrmIn As Form)
Dim i As Long

If MaxForm > 0 Then
For i = 0 To (MaxForm - 1)
	If FormRecord(i).Name = pfrmIn.Name Then
		FormRecord(i).Top = pfrmIn.Top
		FormRecord(i).Left = pfrmIn.Left
		FormRecord(i).Height = pfrmIn.Height
		FormRecord(i).Width = pfrmIn.Width
		Exit Sub
	End If
Next i
AddForm (pfrmIn)
End If
End Sub

Public Sub RestoreFormPosition(pfrmIn As Form)
Dim i As Long

If MaxForm > 0 Then
For i = 0 To (MaxForm - 1)
If FormRecord(i).Name = pfrmIn.Name Then
	If FormRecord(i).Top < 0 Then
		pfrmIn.WindowState = 2
	ElseIf FormRecord(i).Top < 30000 Then
		pfrmIn.WindowState = 0
		pfrmIn.Move FormRecord(i).Left, FormRecord(i).Top, FormRecord(i).Width, FormRecord(i).Height
	Else
		pfrmIn.WindowState = 1
	End If
	Exit Sub
End If
Next i
End If
End Sub

 

2. Sử dụng trong form:

chỉ cần thêm  đoạn code này vào trong code của form

Private Sub Form_Resize()
ResizeForm Me
End Sub

Hảy thử và tận hưởng thành quả.

Chapichuse

Đam mê công nghệ

You may also like...

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *