có thể tạo Userform vừa khít với các loại màn hình

Liên hệ QC

NguyenthiH

Thành viên mới đăng ký
Tham gia
11/12/16
Bài viết
949
Được thích
175
Giới tính
Nữ
Chào mọi người!
Em hay tạo Userform để nhập liệu, khi tạo em chỉnh kích thước cho vừa với màn hình 14 Inch của Laptop nhà, nhưng khi mang File đó lên làm ở máy công ty thì mở Form lên lại không vừa với màn hình của máy công ty.
Vậy có code nào chỉnh cho Userform luôn vừa với mọi loại màn hình được không ah!
Em cám ơn mọi người.
 
Code hiệu chỉnh lần cuối của Thầy Ndu vẫn chưa can đối (Book2)
và Code của Thầy Tuân và của Thầy Ndu em sưu tầm trên DD (Book1) được can đối.
 

File đính kèm

  • Book2.xlsb
    51.2 KB · Đọc: 86
  • Book1.xlsb
    59.1 KB · Đọc: 138
Upvote 0
Code hiệu chỉnh lần cuối của Thầy Ndu vẫn chưa can đối (Book2)
và Code của Thầy Tuân và của Thầy Ndu em sưu tầm trên DD (Book1) được can đối.
Code Book1 là cố tình chỉnh riêng ListBox cho nó khớp màn hình hiện tại. Vậy đặt trường hợp có nhiều controls "bị bệnh" như thế thì bạn tính sao?
Controls nào "bị bệnh" làm sao bạn biết trước được? Bởi nó còn tùy thuộc vào kích thước từng màn hình (laptop khác, desktop khác...)
 
Upvote 0
Code của Thầy Tuân và của Thầy Ndu em sưu tầm trên DD (Book1) được can đối.
Cũng không chuẩn.
1. Trong UserForm_Initialize sau dòng SetWindowLong thêm
Mã:
ReDim arr(1 To 60, 1 To 1)
    For k = 1 To 60
        arr(k, 1) = "hic hic " & k
    Next
    ListBox1.List = arr
Mở Form và cuộn ListBox1 xuống cuối. Bạn không nhìn thấy mục cuối cùng - mục "hic hic 60" bị che.

2. Không phải lúc nào ListBox cũng "với" tới tận cạnh dưới của Form. Có những th ở dưới ListBox còn nhiều thứ.
Kiểu cố tình kéo ListBox tới tận cạnh dưới của Form là vô lý.
Mã:
 ''Thuat toan nam tai day!
    With ListBox1
        .Height = Me.InsideHeight - .Top - 6
    End With
Thuật toán gì? Nếu dưới ListBox người ta có những thứ khác thì vẫn cứ kéo ListBox xuống dưới cùng?

Bạn hãy sửa Height của ListBox1 thành 220 rồi mở Form xem có chuẩn không nhé
 
Upvote 0
Tới Thầy Ndu:
Code của Thầy vẫn chưa cân đối (Lệch vế bên trái)
Tới Thầy Batman1:
Em đã chỉnh Height của ListBox1 bằng 220, nhưng Form vẫn chưa chuẩn (ListBox1 đụng tới TaskBar luôn, không thấy phấn dưới của Form). còn code kéo listBox là của Anh Hoang Trong Nghĩa đó.
 
Upvote 0
Bạn có thể xem ví dụ cùng mã nguồn tôi làm về zoom userform tại đây:
zoomform.gif

File nguồn:
http://bluesofts.net/phong-to-va-thu-nho-userform-va-controls-trong-excel-vba.html
 
Upvote 0
Bạn có thể xem ví dụ cùng mã nguồn tôi làm về zoom userform tại đây:
Tôi e rằng cái này không đúng theo ước muốn của chủ đề tài.
Ta thêm 1 ListBox2 nữa "vươn" tới cạnh dưới của Form.
1. Khi mở Form thì nó ở dạng max và TextBox2, ToggleButton1 và cmdClose bị cụt bên phải.
2. Nếu click max button để về kích thước thiết kế rồi "nắm" góc dưới bên phải di chuyển thì a. Nếu kéo sang bên phải mở rộng Form thì đến lúc ListBox2 và cmdClose bị cụt ở dưới.
b. Nếu kéo xuống để tăng chiều cao của Form thì ListBox2, Label3 và Label4 càng ngày càng xa cạnh dưới của Form, xuất hiện khoảng trống càng ngày càng lớn dưới 3 control này.
c. Nếu kéo lên để giảm chiều cao của Form thì ListBox2, Label3, cmdClose và Label4 càng ngày càng cụt đi

v...v

Ước muốn của chủ đề tài là giãn ra co vào luôn cân đối.
 
Upvote 0
Tới Thầy Tuân:
Cám ơn Thầy, nhưng File của Thầy không đúng ý của em.

Tới Thầy Ndu:
File của Thầy ở bài #25 em cũng phải kéo ListBox1 lên thì mới vừa khít.

******* Vậy là không có code nào làm cho Form và các control trên Form khi hiện ra là vừa khít với mọi loại màn hình (Tất nhiên là các Control trên Form cũng can đối theo Form)
Còn nếu dung code để kéo ListBox ra cho vừa thì lại mất dữ lieu dòng cuối trên ListBox.
Chỉ có cách là kéo bang tay(Thủ công) cho các control vừa khít thì thôi.
 
Upvote 0
Tới Thầy Tuân:
Cám ơn Thầy, nhưng File của Thầy không đúng ý của em.

Tới Thầy Ndu:
File của Thầy ở bài #25 em cũng phải kéo ListBox1 lên thì mới vừa khít.

******* Vậy là không có code nào làm cho Form và các control trên Form khi hiện ra là vừa khít với mọi loại màn hình (Tất nhiên là các Control trên Form cũng can đối theo Form)
Còn nếu dung code để kéo ListBox ra cho vừa thì lại mất dữ lieu dòng cuối trên ListBox.
Chỉ có cách là kéo bang tay(Thủ công) cho các control vừa khít thì thôi.

Muốn giải quyết vấn đề của bạn phải có một phần mềm chuyên tạo hệ thống vận hành và màn hình ảo. Phần mềm này cho phép tự tạo tất cả các loại và kích cỡ màn hình. Từ chỗ này, ta có thể trích lọc ra những thông số của các tổ hợp hệ thống & cửa sổ & màn hình khác nhau và từ đó hiệu chỉnh cỡ Form cùng các controls của nó. Néu số tổ hợp lên tới vài ngàn thì bắt buọc phải lập mọt bảng tra. Trăm thứ rắc rối.

Đại khái, để đỡ mỏi tay, bạn có thể phải chấp nhận cái size của mỗi file phải tăng lên vài MB; mỗi lần mở file, VBA phải lục lọi thông số; mỗi lần có gì mới, bạn phải update bảng tra, vv...

Bạn nên nhớ rằng co những ngừoi dùng nhiều màn hình. Nếu code hoàn chỉnh thì phải khắc phục được trường hợp ngừoi ta kéo app từ màn hình này sang màn hình khác.

Để hiểu rõ hơn toi nói gì, bạn có thể vào các nơi dùng mã nguồn mở (như Ubuntu chẳng hạn) xem thử code họ viết 1 cái driver nào đó và lấy khái niệm về sự phức tạp của vấn đề.
 
Upvote 0
Code Book1 là cố tình chỉnh riêng ListBox cho nó khớp màn hình hiện tại. Vậy đặt trường hợp có nhiều controls "bị bệnh" như thế thì bạn tính sao?
Controls nào "bị bệnh" làm sao bạn biết trước được? Bởi nó còn tùy thuộc vào kích thước từng màn hình (laptop khác, desktop khác...)

Kinh nghiệm:
Code nên tạo cho người dùng 1 cửa hậu. Bấm mọt tổ hợp phím nào đó thì form sẽ trở về vị trí/kích cỡ mặc định.
 
Upvote 0
Kinh nghiệm:
Code nên tạo cho người dùng 1 cửa hậu. Bấm mọt tổ hợp phím nào đó thì form sẽ trở về vị trí/kích cỡ mặc định.
Chính vậy mà mình cố tình thiết kế UserForm với 3 nút: Max, Min, Close... để nếu sau khi phóng to mà thấy không vừa ý thì bấm nút giữa phục hồi
Hồi trước mình cũng từng nghien cứu vụ phóng to này nhưng sau đó.. nản, bởi có khi form chạy ngon trên mấy mình mà sang máy khác lại.. méo xẹo... Ghét bỏ luôn hổng thèm nghiên cứu nữa (dù sao cũng chỉ là làm màu, có cũng tốt mà không có cũng không chết Tây nào)
 
Upvote 0
Chính vậy mà mình cố tình thiết kế UserForm với 3 nút: Max, Min, Close... để nếu sau khi phóng to mà thấy không vừa ý thì bấm nút giữa phục hồi
Hồi trước mình cũng từng nghien cứu vụ phóng to này nhưng sau đó.. nản, bởi có khi form chạy ngon trên mấy mình mà sang máy khác lại.. méo xẹo... Ghét bỏ luôn hổng thèm nghiên cứu nữa (dù sao cũng chỉ là làm màu, có cũng tốt mà không có cũng không chết Tây nào)
Nói chung giao nhiệm vụ theo dõi cho người nào thì sử dụng máy của người đó và chỉ tốn công sửa Form 1 lần (vậy là xong nhiệm vụ), còn muốn code thì phải dựa vào độ phân giải màn hình của từng loại máy tính sẽ phức tạp ra mà không có tác dụng gì nhiều.
 
Lần chỉnh sửa cuối:
Upvote 0
Việc cân đối 100% là rất là khó. Ngay cả khi bạn chả zoom gì, chả phủ kín màn hình mà kích thước ListBox đã thay đổi. Bạn thử như sau:
1. Trong tập tin của Tuân bạn xóa code UserForm_Resize
2. Các sub còn lại thay bằng
Mã:
Private Sub UserForm_Activate()
    Debug.Print ListBox1.Height
End Sub

Private Sub UserForm_Initialize()
Dim Arr(1 To 60, 1 To 1)
    Debug.Print ListBox1.Height
    For k = 1 To 60
        Arr(k, 1) = "hic hic " & k
    Next
    ListBox1.List = Arr
End Sub
Bạn sẽ thấy trong UserForm_Initialize ListBox1.Height = 87,75 = kích thước thiết kế trong cửa sổ Properties. Nhưng ở Activate ListBox1.Height = 81. Tức cho dù bạn thiết kế trong cửa sổ Properties "khít" thì khi hiện Form (sau khi nhập các mục vào ListBox1) ListBox1 sẽ ngắn đi 6,75 [points], tức sẽ "lòi" ra khoảng trống ở dưới = 6,75 [points]
---------
Tôi thử một cách khác, có chuẩn không thì bạn tự kiểm tra, vì tôi ngại test lắm. Chỉ mới test cho các controls trong tập tin của Tuân. Được hay không thì tôi cũng không quan tâm nữa. Chuyện hoa hòe hoa sói tôi không ham.
1. Trong tập tin của Tuân bạn thêm khai báo (nếu biến đã có thì thôi)
Mã:
Dim hwnd As Long, wStyle As Long, OldWidth As Double, OldHeight As Double, OldInsideWidth As Double, OldInsideHeight As Double, lastScaleX As Double, lastScaleY As Double

2. Thay 2 sub UserForm_Initialize và UserForm_Resize bằng 2 sub mới
Mã:
Private Sub UserForm_Initialize()
Dim c As MSForms.Control, Arr()
    OldWidth = Width
    OldHeight = Height
    OldInsideWidth = InsideWidth
    OldInsideHeight = InsideHeight
    lastScaleX = 1
    lastScaleY = 1
    For Each c In Controls
        If TypeName(c) = "ListBox" Then c.Tag = c.Height
    Next c
    If Val(Application.Version) < 9 Then
        hwnd = FindWindow("ThunderXFrame", Caption)  'XL97
    Else
        hwnd = FindWindow("ThunderDFrame", Caption)  'XL2000
    End If
    wStyle = GetWindowLong(hwnd, GWL_STYLE)
    SetWindowLong hwnd, GWL_STYLE, wStyle Or WS_MINIMIZEBOX Or WS_MAXIMIZEBOX '  Or WS_THICKFRAME
    ReDim arr(1 To 60, 1 To 1)
    For k = 1 To 60
        arr(k, 1) = "hic hic " & k
    Next
    ListBox1.List = arr
End Sub

Private Sub UserForm_Resize()
    ScaleFormControls
End Sub

3. Thêm
Mã:
Private Sub ScaleFormControls()
Dim scaleX As Double, scaleY As Double, x As Double, y As Double, c As MSForms.Control
    scaleX = InsideWidth / OldInsideWidth
    scaleY = InsideHeight / OldInsideHeight
    x = scaleX / lastScaleX
    y = scaleY / lastScaleY
    For Each c In Controls
        c.Left = c.Left * x
        c.Top = c.Top * y
        c.Width = c.Width * x
        If TypeName(c) = "ListBox" Then
            c.Height = c.Tag * scaleY
        Else
            c.Height = c.Height * y
        End If
        On Error Resume Next
        c.Font.Size = c.Font.Size * y
        On Error GoTo 0
    Next c
    lastScaleX = scaleX
    lastScaleY = scaleY
End Sub

4. Hiện tại chỉ có 2 trạng thái: max khít màn hình và kích thước thiết kế. Nếu bạn muốn test kéo ra kéo vào thì bỏ dấu nháy trước Or WS_THICKFRAME.
Tất nhiên thu nhỏ thì cũng chỉ nên tới lúc vẫn còn nhìn được chữ trên các Label, ListBox v...v Để khi thu nhỏ phóng to vẫn có thể về lại kích thước thiết kế thì thêm
Mã:
Private Sub UserForm_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
    Width = OldWidth
    Height = OldHeight
End Sub
Khi muốn về lại kích thước thiết kế thì click đúp vào chỗ trống trên Form
 
Upvote 0
Cám ơn Thầy Batman1, Chổ khai báo biến (1) thêm vào Module hay trong Form.
Vì em không biết thêm vào chổ nào nên em không Test được.
Mong Thầy chỉ cho.
 
Upvote 0
Bạn phải có kiến thức abc tối thiểu và biết suy nghĩ chứ không chỉ tập copy/paste.
Bạn muốn khai báo ở Module cũng được nhưng với DIM kia thì chắc chắn code trong Form không thể truy cập tới các biến kia. Vậy tùy bạn.
 
Upvote 0
Em đã thử khai báo biến (1) vào Userform_Initialize nhưng code chạy lỗi ngay chổ
"WS_MINIMIZEBOX" nên em mới hỏi khai báo vào đâu?
Mong Thầy chỉ rỏ.
 
Upvote 0
Em đã thử khai báo biến (1) vào Userform_Initialize nhưng code chạy lỗi ngay chổ
"WS_MINIMIZEBOX" nên em mới hỏi khai báo vào đâu?
Các biến của tôi thì liên quan gì tới WS_MINIMIZEBOX?

Thứ nhất là tôi không tin. Vì trong tập tin của Tuân (tôi ghi rất rõ: Trong tập tin của Tuân bạn thêm khai báo) trong UserForm1 ngay trên đầu có
Option Explicit

Private Const GWL_STYLE = (-16)
Private Const WS_MAXIMIZEBOX = &H10000
Private Const WS_MINIMIZEBOX = &H20000
Private Const WS_THICKFRAME = &H40000
Thứ nữa là bạn hãy nhìn xem trong những biến mà tôi đề nghị khai báo có biến nào tên là WS_MINIMIZEBOX không. Rõ ràng là không.

WS_MINIMIZEBOX là hằng số của Tuân (của Windows), nhưng tôi có đả động gì tới WS_MINIMIZEBOX đâu?

Trong bài tôi ghi rất rõ, thêm cái gì, thay cái gì của Tuân bằng cái mới.

Tôi cố tình không nói để bạn tự đọc kỹ và động não. Không thì suốt đời bạn chỉ đi hỏi mà không học thêm được cái gì.
 
Upvote 0
Xin lỗi Thầy!
Em lấy File của em, nên bị lỗi.
 
Lần chỉnh sửa cuối:
Upvote 0
Chào Thầy Batman1!
Code của Thầy đã chuẩn, nhưng khi Form bung toàn màn hình và các Control giãn ra cân đối theo Form, nhưng ColumWidth của các cột trong ListBox không giãn ra theo, nên khi nhập dữ liệu đập ListBox thì lại không cân đối.
Em xin đưa File Thầy xem giúp.
Trong File nhấn mặt cười sẽ hiện Form, gỏ đại các ký tự vào các TextBox: Tên hàng hóa, DVT, Số Lượng, Thành Tiền rồi Enter thì thấy dữ liệu nạp vào ListBox không cân đối.
Mong Thầy xem giúp.
 

File đính kèm

  • Book1.xlsb
    56 KB · Đọc: 132
Upvote 0
nhưng khi Form bung toàn màn hình và các Control giãn ra cân đối theo Form, nhưng ColumWidth của các cột trong ListBox không giãn ra theo, nên khi nhập dữ liệu đập ListBox thì lại không cân đối.
Đúng là quên. Chính vì làm chuẩn mất thời gian vì nếu không nghĩ kỹ thì dễ quên nhiều vấn đề.

Tôi thường bỏ công để viết rõ ràng nhưng nếu bạn lại không chịu đọc kỹ như lần trước thì bạn tự tìm hiểu. Lần này tôi sẽ không trả lời. Không thể "thời gian của người khác thì không tiếc".

Bạn hãy đọc kỹ những điểm sau:

0. Tôi vẫn cứ lấy tập tin của Tuân làm căn cứ. Bạn tự chuyển code sang tập tin của mình.

1. Để làm thật khít, thật chuẩn 100% là chuyện khó, mất công. Mà tôi không muốn mất thời gian về chuyện này. Và chắc chả ai rỗi hơi cả. Vậy nếu bạn rất cần thì đặt hàng để ai đó làm cho. Lúc này thì khác, vì khách hàng là thượng đế mà. Anh muốn rực rỡ, vô bổ cũng có người làm. Càng nhiều rực rỡ thì việc càng nhiều, tiền công càng cao, ai mà chả thích làm ra càng nhiều tiền, đúng không?

2. Bạn hãy test lần nữa và cho kết quả test để mọi người biết. Lúc đó có thể có người khác giúp bạn - bằng cách khác hoặc làm chuẩn hơn. Riêng tôi không muốn làm nữa.

3. Trong UserForm_Initialize thay
Mã:
For Each c In Controls
    If TypeName(c) = "ListBox" Then c.Tag = c.height
Next c
bằng
Mã:
For Each c In Controls
        If TypeName(c) = "ListBox" Or TypeName(c) = "ComboBox" Then
            If c.ColumnWidths = "" Then
                c.Tag = String(c.ColumnCount, "a")
                c.Tag = Replace(c.Tag, "a", (c.Width - 13) / c.ColumnCount & " pt;") & c.height
            Else
                c.Tag = c.ColumnWidths & ";" & c.height
            End If
        End If
    Next c

4. Trong code của UserForm1 thêm code
Mã:
Private Sub CalcColWidths(ByVal c As MSForms.Control, ByVal zoomX As Double)
Dim k As Long, s As String, cSize
    If c.ColumnCount = 1 Then Exit Sub
    s = Replace(c.Tag, " pt", "")
    cSize = Split(Left(s, InStrRev(s, ";") - 1), ";")
    For k = LBound(cSize) To UBound(cSize)
        cSize(k) = cSize(k) * zoomX
    Next k
    c.ColumnWidths = Join(cSize, " pt;") & " pt"
End Sub

5. Thay Sub ScaleFormControls bằng sub mới
Mã:
Private Sub ScaleFormControls()
Dim scaleX As Double, scaleY As Double, x As Double, y As Double, cSize, c As MSForms.Control
    scaleX = InsideWidth / OldInsideWidth
    scaleY = InsideHeight / OldInsideHeight
    x = scaleX / lastScaleX
    y = scaleY / lastScaleY
    For Each c In Controls
        c.Left = c.Left * x
        c.Top = c.Top * y
        c.Width = c.Width * x
        If TypeName(c) = "ListBox" Then
            cSize = Split(c.Tag, ";")
            c.height = cSize(UBound(cSize)) * scaleY
        Else
            c.height = c.height * y
        End If
'        goi CalcColWidths sau khi xac dinh Height cua ListBox
        If TypeName(c) = "ListBox" Or TypeName(c) = "ComboBox" Then
            CalcColWidths c, scaleX
        End If
        On Error Resume Next
        c.Font.Size = c.Font.Size * y
        On Error GoTo 0
    Next c
    lastScaleX = scaleX
    lastScaleY = scaleY
End Sub
 
Upvote 0
Web KT

Bài viết mới nhất

Back
Top Bottom