Làm sao xác định được UserForm đang active?

Liên hệ QC

Hoàng Trọng Nghĩa

Chuyên gia GPE
Thành viên BQT
Moderator
Tham gia
17/8/08
Bài viết
8,662
Được thích
16,720
Giới tính
Nam
Nhờ các Thầy Cô, Anh Chị giúp đỡ:

Tôi có một File với 2 UserForm, khi mở Form1, rồi từ Form1 mở Form2 (không đóng Form1). Từ Form2 bấm nút Kiểm tra, làm sao xác định được Form1 vẫn đang còn mở hoặc đã đóng?

Xin cảm ơn rất nhiều!
 

File đính kèm

Lần chỉnh sửa cuối:
Nhờ các Thầy Cô, Anh Chị giúp đỡ:

Tôi có một File với 2 UserForm, khi mở Form1, rồi từ Form1 mở Form2 (không đóng Form1). Từ Form2 bấm nút Kiểm tra, làm sao xác định được Form1 vẫn đang còn mở hoặc đã đóng?

Xin cảm ơn rất nhiều!

Dùng Function sau:

Mã:
Function FormIsLoaded(UFName As String) As Boolean
Dim UF As Integer
For UF = 0 To VBA.UserForms.Count - 1
FormIsLoaded = UserForms(UF).Name = UFName
If FormIsLoaded Then
Exit Function
Else
MsgBox "Form ban tim khong thay mo"
End If
Next UF
End Function

Kiểm tra trên form2

Mã:
Private Sub CommandButton1_Click()
If FormIsLoaded("UserForm1") Then
MsgBox "Userform1 dang mo"
End If


End Sub

Nguồn: http://www.pcreview.co.uk/forums/thread-1002033.php
 
Upvote 0
Nhờ các Thầy Cô, Anh Chị giúp đỡ:

Tôi có một File với 2 UserForm, khi mở Form1, rồi từ Form1 mở Form2 (không đóng Form1). Từ Form2 bấm nút Kiểm tra, làm sao xác định được Form1 vẫn đang còn mở hoặc đã đóng?

Xin cảm ơn rất nhiều!

Không biết như thế này đã đúng theo ý của bác Thiện chưa?
Mã:
Private Sub CommandButton1_Click()
'làm sao de xac dinh UserForm1 dang Active?
    If (UserForm1 Is Nothing) Then
        MsgBox "UserForm1 is inactive"
    ElseIf Not UserForm1.Visible Then
        MsgBox "UserForm1 is inactive"
    Else
        MsgBox "UserForm1 is active"
    End If
End Sub
 
Upvote 0
Code của TuanVNUNI dựa vào thuộc tính Visiable e không ổn.
Mình thử bằng cách này. Trên Form1 thêm 1 TextBox1 và Code sửa như sau

Mã:
Private Sub CommandButton1_Click()
  UserForm2.Show
 [B][COLOR=Red] Me.Hide[/COLOR][/B]
End Sub
Code của Form2 sửa như sau:

Mã:
Private Sub CommandButton1_Click()
'làm sao de xac dinh UserForm1 dang Active?
    If (UserForm1 Is Nothing) Then
        MsgBox "UserForm1 is inactive"
    ElseIf Not UserForm1.Visible Then
        MsgBox "UserForm1 is inactive"
    Else
        MsgBox "UserForm1 is active"
    End If
 [B][COLOR=Red]   MsgBox UserForm1.TextBox1[/COLOR][/B]
    
End Sub

Theo trình tự, mở Form1--> Gõ GPE vào TextBox1 --> Nhấn nút mở Form2 -->Nhấn nút kiểm tra thì có thông báo Inactive nhưng vẫn lấy được giá trị của TextBox1 là GPE. Vậy Form1 vẫn tồn tại và chỉ ẩn đi thôi. Trong khi Thien yêu cầu xác định đóng chưa?
 
Upvote 0
Như vậy, theo Anh Sealand thì mình phải làm thế nào? Đúng là khi dùng code của Anh Tuân thì ngắn gọn, nhưng khi kiểm tra Form chưa mở hình như nó có load Form này lên để xác định hay sao đó.
 
Upvote 0
Như vậy, theo Anh Sealand thì mình phải làm thế nào? Đúng là khi dùng code của Anh Tuân thì ngắn gọn, nhưng khi kiểm tra Form chưa mở hình như nó có load Form này lên để xác định hay sao đó.
Dùng API đi cho dễ
Tại UserForm2, ta đặt code thế này:
PHP:
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
  (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
PHP:
Private Sub CommandButton1_Click()
  Dim hWnd As Long
  hWnd = FindWindow("ThunderDFrame", UserForm1.Caption)
  MsgBox Hex(hWnd)
End Sub
Thí nghiệm 2 trường hợp ở UserForm1
Trường hợp 1:
PHP:
Private Sub CommandButton1_Click()
  UserForm2.Show
  Me.Hide
End Sub
Và trường hợp 2:
PHP:
Private Sub CommandButton1_Click()
  UserForm2.Show
  Unload Me
End Sub
Xem thử kết quả khi bấm Button trên UserForm2 thì nó ra kết quả gì? Từ đó rút ra kết luận
 
Upvote 0
Cách của Ndu là chắc ăn. Minh Thien tham khảo thêm bài này
 
Upvote 0
Ah... mà sao ta lại tự mình làm khó mình thế nhỉ?
Nghĩ lại thấy làm vầy vẫn ngon lành:
1> Đặt 1 biến check kiểu Boolean vào trong 1 Module
PHP:
Public Check As Boolean
2> Tại UserForm1, dùng sự kiện InitializeTerminate để gán giá trị cho biến check
PHP:
Private Sub UserForm_Initialize()
  Check = True
End Sub
PHP:
Private Sub UserForm_Terminate()
  Check = False
End Sub
Vậy nếu UserForm1 ta có code sau:
PHP:
Private Sub CommandButton1_Click()
  Unload Me
  UserForm2.Show
End Sub
hoặc
PHP:
Private Sub CommandButton1_Click()
    Me.Hide
    UserForm2.Show
End Sub
Thì tại UserForm2, chỉ cần thế này là đủ:
PHP:
Private Sub CommandButton1_Click()
  MsgBox Check
End Sub
Kết quả = True <==> Form đã load (bất kể nó ẩn hay hiện) và =False cho trường hợp ngược lại
Hic...
-----------------
Lưu ý:
- Unload Me hoặc Me.Hide phải được viết trước dòng UserForm2.Show ---> Nếu làm ngược lại thì chẳng tác dụng gì (đồng nghĩa UserForm1 sẽ không thể đóng)
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Code của TuanVNUNI dựa vào thuộc tính Visiable e không ổn.
Mình thử bằng cách này. Trên Form1 thêm 1 TextBox1 và Code sửa như sau

Mã:
Private Sub CommandButton1_Click()
  UserForm2.Show
 [B][COLOR=Red] Me.Hide[/COLOR][/B]
End Sub
Code của Form2 sửa như sau:

Mã:
Private Sub CommandButton1_Click()
'làm sao de xac dinh UserForm1 dang Active?
    If (UserForm1 Is Nothing) Then
        MsgBox "UserForm1 is inactive"
    ElseIf Not UserForm1.Visible Then
        MsgBox "UserForm1 is inactive"
    Else
        MsgBox "UserForm1 is active"
    End If
 [B][COLOR=Red]   MsgBox UserForm1.TextBox1[/COLOR][/B]
    
End Sub

Theo trình tự, mở Form1--> Gõ GPE vào TextBox1 --> Nhấn nút mở Form2 -->Nhấn nút kiểm tra thì có thông báo Inactive nhưng vẫn lấy được giá trị của TextBox1 là GPE. Vậy Form1 vẫn tồn tại và chỉ ẩn đi thôi. Trong khi Thien yêu cầu xác định đóng chưa?

Anh sealand ơi, trong VBA, tất cả các Userform khi đã đóng rồi mà anh lại gọi UserForm1.TextBox1 thì là load lại nó mà. Cứ kiểm tra lại bằng tất cả các cánh mà xem. Anh cho các đoạn code đóng form rồi anh gọi bất kỳ thuộc tính nào của form đó thì form lại được load lại, kể cả dùng API cũng vậy mà thôi,... Thủ trưởng hỏi thủ kho rằng "Cửa kho đã đóng chưa?" Thủ kho kiểm tra rồi báo "đã đóng", Thủ trưởng vào kho lấy đồ và đã mở lại cửa kho, quay ra thủ trưởng bảo "Cửa kho đang mở".... Logic của anh bị sai.

Dưới đây là code theo cách của anh Tuấn, tôi cho thêm đoạn kiểm tra theo cách của anh Sealand
Mã:
Private Sub CommandButton1_Click()
  MsgBox Check [COLOR="Red"]'Thủ kho báo cửa đã đóng[/COLOR]
  MsgBox UserForm1.Caption [COLOR="Red"]'Thủ trưởng lấy đồ (đương nhiên phải mở cửa kho)[/COLOR]
  MsgBox Check [COLOR="Red"]'Kiểm tra lại thấy cửa kho đang mở[/COLOR]
End Sub

Các của anh Tuấn cũng đúng nhưng cách chúng ta test/kiểm tra sai logic thì nó lại là sai :).

Phương pháp em làm là dùng phương pháp loại trừ.

Mã:
    If (UserForm1 Is Nothing) Then
        MsgBox "UserForm1 is inactive"
    ElseIf Not UserForm1.Visible Then
        MsgBox "UserForm1 is inactive"
    Else
        MsgBox "UserForm1 is active"
    End If
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Anh sealand ơi, trong VBA, tất cả các Userform khi đã đóng rồi mà anh lại gọi UserForm1.TextBox1 thì là load lại nó mà. Cứ kiểm tra lại bằng tất cả các cánh mà xem. Anh cho các đoạn code đóng form rồi anh gọi bất kỳ thuộc tính nào của form đó thì form lại được load lại, kể cả dùng API cũng vậy mà thôi,... Thủ trưởng hỏi thủ kho rằng "Cửa kho đã đóng chưa?" Thủ kho kiểm tra rồi báo "đã đóng", Thủ trưởng vào kho lấy đồ và đã mở lại cửa kho, quay ra thủ trưởng bảo "Cửa kho đang mở".... Logic của anh bị sai.
Hoàn toàn chính xác! Vì nó mà tôi đã gặp rắc rối khi dùng API xây dựng hàm kiểm tra form đã load hay chưa
Tôi làm thế này:
PHP:
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
   (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
PHP:
Private Function IsFormLoaded(UF As Object) As Boolean
  IsFormLoaded = FindWindow("ThunderDFrame", UF.Caption) > 0
End Function
Và kết quả sai bét ---> Sai ở chổ dù Form có đóng rồi nhưng do trong code có đoạn UF.Caption (lấy Caption) nên nó lại load trở lại
Cuối cùng phải sửa thế này mới được
PHP:
Private Function IsFormLoaded(frmCaption As String) As Boolean
  IsFormLoaded = FindWindow("ThunderDFrame", frmCaption) > 0
End Function
Gữi file cho các bạn tham khảo cách dùng API
 

File đính kèm

Upvote 0
TuanVNUNI ơi, hiểu sai ý mình rồi.
Như thế này cơ mà. Load Form1 rồi gõ cái gì đó vào TextBox bắt nó giữ làm tin. Nếu nó đóng rồi mà load lại thì chắc những cái trong TextBox cũng tiêu luôn. Mình gõ GPE vào TextBox rồi mở Form2 kiểm tra mà vẫn đọc được GPE trên TextBox thì chắc Form 1 chưa hề đóng. Nhưng kiểm tra bằng Visiable lập tức bị dính.
Mình thấy TuanVNUNI có thể Hook chính xác cả cửa sổ MsgBox thì 1 Form nào đó hoàn toàn có thể làm được. Khổ nỗi, hàm API mình quá lơ mơ, trước đây TuanVNUNI giúp mình mà sao mình vẫn khó hiểu chưa chủ động vạn dụng cho các trường hợp của mình được. Vì vậy mà hôm qua mình không giúp Minh Thien được.
 
Upvote 0
TuanVNUNI ơi, hiểu sai ý mình rồi.
Như thế này cơ mà. Load Form1 rồi gõ cái gì đó vào TextBox bắt nó giữ làm tin. Nếu nó đóng rồi mà load lại thì chắc những cái trong TextBox cũng tiêu luôn. Mình gõ GPE vào TextBox rồi mở Form2 kiểm tra mà vẫn đọc được GPE trên TextBox thì chắc Form 1 chưa hề đóng. Nhưng kiểm tra bằng Visiable lập tức bị dính.
Mình thấy TuanVNUNI có thể Hook chính xác cả cửa sổ MsgBox thì 1 Form nào đó hoàn toàn có thể làm được. Khổ nỗi, hàm API mình quá lơ mơ, trước đây TuanVNUNI giúp mình mà sao mình vẫn khó hiểu chưa chủ động vạn dụng cho các trường hợp của mình được. Vì vậy mà hôm qua mình không giúp Minh Thien được.

Vâng, chính vì thế mà thông báo kiểm tra của em là "Inactive". Nếu Userform Is Nothing Then "Unload". Vụ này chỉ cần kiểm tra theo phương pháp thông thường là được, không cần dùng API đâu anh ạ.
 
Lần chỉnh sửa cuối:
Upvote 0
Web KT

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

Back
Top Bottom