Cấp độ bài viết: căn bản
Tác giả: lsqk (học từ sách "Kỹ thuật lập trình Visual Basic 5" của Ngọc Anh Thư Press)
Mình có xem qua box này và box "Thủ thuật, mẹo vặt", nhưng không thấy có topic nào hướng dẫn vấn đề này cả, mình mạn phép post bài này vậy. Theo mình thấy, việc lập trình để control tự chỉnh kích cỡ khi kích cỡ của form thay đổi là rất cần thiết. Nếu không biết làm điều này, bạn có thể tắt nút Maximize của form, nhưng chương trình như vậy sẽ bất tiện và kém chuyên nghiệp hơn hẳn.
Đầu tiên, bạn phải hiểu rằng để control tự chỉnh kích cỡ khi kích cỡ form thay đổi, thì chúng ta cần phải giữ vững tỉ lệ giữa các thuộc tính left và width của control với thuộc tính width của form và giữa thuộc tính top và height của control với thuộc tính height của form. Có như thế thì vị trí và kích cỡ của các control mới hợp lý được. Vậy ta cần gán tỉ lệ này vào một biến và bảo đảm biến đó không thay đổi. Biến được nạp giá trị vào lúc form load và giữ nguyên giá trị tới khi form unload. Biến này là biến cấp module. Bạn cũng có thể tạo mỗi control 4 biến phụ thuộc, nhưng như vậy… khổ lắm!

Bắt tay vào làm việc, đầu tiên, ở namespace bạn hãy tạo một structure như sau:
- Public Structure ControlProportions
- Public TopProp As Single
- Public LeftProp As Single
- Public HeightProp As Single
- Public WidthProp As Single
- End Structure
Nếu chương trình của bạn chỉ có một form thôi thì bạn có thể để structure là Private cũng được. Nhưng nếu có nhiều form thì nên để là Public để dùng chung.
Tiếp đó, trong class của form, bạn nhập vào như sau:
- Dim ArrayProportions() As ControlProportions
- Private Sub ArrayInitialize()
- Dim I As Integer
- For I = 0 To Controls.Count - 1
- With ArrayProportions(I)
- .LeftProp = Controls(I).Left / Me.Size.Width
- .TopProp = Controls(I).Top / Me.Size.Height
- .WidthProp = Controls(I).Width / Me.Size.Width
- .HeightProp = Controls(I).Height / Me.Size.Height
- End With
- Next
- End Sub
Rồi bạn chọn sự kiện form_load, nhập vào như sau:
- Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
- ReDim ArrayProportions(0 To Controls.Count - 1)
- ArrayInitialize()
- End Sub
Có ai thắc mắc vì sao phải là count – 1 mà không phải là count không?

Vì mảng bắt đầu từ 0!

Tiếp đó, bạn chọn sự kiện form_resize, nhập vào như sau:
- Private Sub Form1_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize
- Dim I As Integer
- For I = 0 To Controls.Count - 1
- Controls(I).Left = ArrayProportions(I).LeftProp * Me.Size.Width
- Controls(I).Top = ArrayProportions(I).TopProp * Me.Size.Height
- Controls(I).Width = ArrayProportions(I).WidthProp * Me.Size.Width
- Controls(I).Height = ArrayProportions(I).HeightProp * Me.Size.Height
- Next
- End Sub
Trên đây là hướng dẫn lập trình tự chỉnh kích cỡ control với những form không dùng container. Nếu dùng container thì mã sẽ dài dòng hơn:
Bạn vẫn khai báo structure như cũ, bắt đầu từ mảng trở đi phải thay đổi. Cụ thể, trong class của form bạn khai báo mảng như sau:
- Dim ArrPro(,) As ControlProportions
Sub ArrayInitialize như sau:
- Private Sub ArrayInitialize()
- Dim i As Short = 0, n As Short = 0
- For i = 0 To Controls.Count - 1
- With ArrPro(i, 0)
- .LeftProp = Controls(i).Left / Me.Size.Width
- .TopProp = Controls(i).Top / Me.Size.Height
- .WidthProp = Controls(i).Width / Me.Size.Width
- .HeightProp = Controls(i).Height / Me.Size.Height
- End With
- If Controls(i).Controls.Count > 0 Then
- For n = 1 To Controls(i).Controls.Count
- With ArrPro(i, n)
- .LeftProp = Controls(i).Controls(n - 1).Left / Controls(i).Width
- .TopProp = Controls(i).Controls(n - 1).Top / Controls(i).Height
- .WidthProp = Controls(i).Controls(n - 1).Width / Controls(i).Width
- .HeightProp = Controls(i).Controls(n - 1).Height / Controls(i).Height
- End With
- Next
- End If
- Next
- End Sub
Có ai thắc mắc là tại sao phải dùng n - 1 mà không dùng n không?


Hai sự kiện form_load và form_resize như sau:
- Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
- Dim i As Short = 0, n As Short = 0, k As Short = Controls.Count
- For i = 0 To Controls.Count - 1
- If Controls(i).Controls.Count > k Then
- k = Controls(i).Controls.Count
- End If
- Next
- ReDim ArrPro(Controls.Count - 1, k)
- ArrayInitialize()
- End Sub
- Private Sub Form1_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize
- Dim i As Short = 0, n As Short = 0
- If Controls.Count > 0 Then
- For i = 0 To Controls.Count - 1
- Controls(i).Left = ArrPro(i, 0).LeftProp * Me.Size.Width
- Controls(i).Top = ArrPro(i, 0).TopProp * Me.Size.Height
- Controls(i).Width = ArrPro(i, 0).WidthProp * Me.Size.Width
- Controls(i).Height = ArrPro(i, 0).HeightProp * Me.Size.Height
- If Controls(i).Controls.Count > 0 Then
- For n = 1 To Controls(i).Controls.Count
- Controls(i).Controls(n - 1).Left = ArrPro(i, n).LeftProp * Controls(i).Width
- Controls(i).Controls(n - 1).Top = ArrPro(i, n).TopProp * Controls(i).Height
- Controls(i).Controls(n - 1).Width = ArrPro(i, n).WidthProp * Controls(i).Width
- Controls(i).Controls(n - 1).Height = ArrPro(i, n).HeightProp * Controls(i).Height
- Next
- End If
- Next
- End If
- End Sub
Có ai thắc mắc vì sao phải có điều kiện If Controls.Count > 0 ở đây không?


Nếu bạn sử dụng nhiều container lồng nhau thì bạn thêm chiều cho mảng, khai báo thêm biến kiểu short và thêm vòng lặp tương tự như trên.
Có ai thắc mắc container là cái gì không?

