Cách đóng hộp MsgBox tự động? (2 người xem)

Liên hệ QC

Người dùng đang xem chủ đề này

PhanTuHuong

VBA & VB.NET for Excel & AutoCad
Thành viên danh dự
Tham gia
13/6/06
Bài viết
7,186
Được thích
24,644
Tôi muốn hộp thông báo tự động đóng sau một khoảng thời gian nhất định, không biết có thực hiện được không?

Tôi đã làm đối với UserForm thì ổn. Còn anh MsgBox thì chưa biết thế nào?
 
Thì dùng phiên bản W (phục vụ unicobe) thay cho phien bản A thôi. Tức dùng MessageBoxTimeoutW
Cho code sau vào 1 Modele riêng, vd. Module3
Mã:
#If VBA7 Then
    Public Declare PtrSafe Function MessageBoxTimeoutW Lib "user32" (ByVal hWnd As LongPtr, _
                                                        ByVal lpText As String, ByVal lpCaption As String, _
                                                        ByVal uType As Long, ByVal wLanguageId As Integer, _
                                                        ByVal dwMilliseconds As Long) As Long
#Else
    Public Declare Function MessageBoxTimeoutW Lib "user32" (ByVal hWnd As Long, _
                                                        ByVal lpText As String, ByVal lpCaption As String, _
                                                        ByVal uType As Long, ByVal wLanguageId As Integer, _
                                                        ByVal dwMilliseconds As Long) As Long
#End If

Function MsgBoxTimeout(ByVal message As String, ByVal timeout As Long, Optional ByVal Title As String = "Message", Optional ByVal flags As VbMsgBoxStyle = vbOKOnly) As VbMsgBoxResult
    MsgBoxTimeout = MessageBoxTimeoutW(0, StrConv(message, vbUnicode), StrConv(Title, vbUnicode), flags, 0, timeout)
End Function

hoặc

Mã:
#If VBA7 Then
    Public Declare PtrSafe Function MessageBoxTimeoutW Lib "user32" (ByVal hWnd As LongPtr, _
                                                        ByVal lpText As LongPtr, ByVal lpCaption As LongPtr, _
                                                        ByVal uType As Long, ByVal wLanguageId As Integer, _
                                                        ByVal dwMilliseconds As Long) As Long
#Else
    Public Declare Function MessageBoxTimeoutW Lib "user32" (ByVal hWnd As Long, _
                                                        ByVal lpText As Long, ByVal lpCaption As Long, _
                                                        ByVal uType As Long, ByVal wLanguageId As Integer, _
                                                        ByVal dwMilliseconds As Long) As Long
#End If

Function MsgBoxTimeout(ByVal message As String, ByVal timeout As Long, Optional ByVal Title As String = "Message", Optional ByVal flags As VbMsgBoxStyle = vbOKOnly) As VbMsgBoxResult
    MsgBoxTimeout = MessageBoxTimeoutW(0, StrPtr(message), StrPtr(Title), flags, 0, timeout)
End Function

Code trong UserForm1 (xóa khai báo các hàm API đang có)
Mã:
Private Sub CommandButton1_Click()
    MsgBoxTimeout "Ch" & ChrW(7841) & "y th" & ChrW(7917) & Chr(10) & _
                    "N" & ChrW(7871) & "u " & ChrW(273) & ChrW(432) & ChrW(7907) & "c s" & _
                    ChrW(7869) & " t" & ChrW(7921) & " t" & ChrW(7855) & "t", _
                    4000, "Thông báo", vbInformation
End Sub
Tham số 4000 = 4 giây sao Anh ... Em chưa hiểu tính kiểu gì ra 4000 ...... nếu được mong anh giải thích dùm
Em cảm ơn
 
Upvote 0
Tham số 4000 = 4 giây sao Anh ... Em chưa hiểu tính kiểu gì ra 4000 ...... nếu được mong anh giải thích dùm
Em cảm ơn
Tôi cố tình thay dwTimeout của người hỏi thành dwMilliseconds - một cái tên nói lên điều cụ thể.
Còn 4000 vì người ta muốn đóng sau 4 s mà.
 
Upvote 0
Upvote 0
1. Hàm MessageBoxTimeout là hàm undocument của MS. Các hàm như MessageBox, MessageBoxEx... thực ra cuối cùng đều gọi tới hàm MessageBoxtTmeout này trong user32.dll, với dwMiliseconds = 0xFFFFFFFF
2. Từ VB/VBA mà gọi các hàm API xxxxxxA với ByVal param as String là 1 overhead cực kỳ nặng, tốn code, tốn time cho cả VB/VBA, cả cho các hàm nhân của Windows như ntdll, kernel32, user32....
Nếu được thì nên dùng các hàm API xxxxW

To NguyenNgocThuHien: như nhau cả, Office x64 chỉ chạy được trên Win 64.
Office x86 thì có thể chạy trên Win 64 và Win 32, nhưng vẫn là x86. Chạy trên Win64 nó chạy trên nền giả lập WOW64
 
Upvote 0
To NguyenNgocThuHien: như nhau cả, Office x64 chỉ chạy được trên Win 64.
Office x86 thì có thể chạy trên Win 64 và Win 32, nhưng vẫn là x86. Chạy trên Win64 nó chạy trên nền giả lập WOW64

Khác nhau chứ anh. Excel 32 bít cài trên win 64. Nhưng lúc đó strptr trả lại kiểu long ( như trên mạng kêu). Nên độ dài số bít của handle không hẳn chạy theo hệ điều hành? Nếu anh có máy 64 bít, cài excel32 bít thì thử xem, em không test được.
 
Upvote 0
Hì hì, em đang nhầm lẫn giữa kiểu khai báo và kiểu dữ liệu thực đó.
Mã:
Dim lp as LongPtr
Dim l as Long
Dim ll as LongLong

Debug.Print LenB(lp)
Debug.Print LenB(l)
Debug.Print LenB(ll)
Mang đoạn code này test với các bản Excel 32, 64 đi.
Ví dụ máy tui, Office 2010 64bit, in ra là 8 4 8
 
Lần chỉnh sửa cuối:
Upvote 0
Hì hì, em đang nhầm lẫn giữa kiểu khai báo và kiểu dữ liệu thực đó.
Mã:
Dim lp as LongPtr
Dim l as Long
Dim ll as LongLong

Debug.Print LenB(lp)
Debug.Print LenB(l)
Debug.Print LenB(ll)
Mang đoạn code này test với các bản Excel 32, 64 đi.
Độ dài của LongPtr thì em hiểu, nó chạy theo excel 32 hay 64 bít.

https://msdn.microsoft.com/en-us/library/office/ee691831(v=office.14).aspx

When should I use strptr, varpt, and objptr?

You should use these functions to retrieve pointers to strings, variables and objects, respectively. On the 64-bit version of Microsoft Office, these functions will return a 64-bit LongPtr, which can be passed to Declare statements. The use of these functions has not changed from previous versions of VBA. The only difference is that they now return a LongPtr.

Như trích dẫn trên thì nó khi nó vẫn có thể là 4 byte.

Em dùng 2007 nên không test có trên được, anh gửi kết quả luôn thì hay quá.
 
Upvote 0
Trích từ Help của Excel

LongPtr Data Type
LongPtr
(Long integer on 32-bit systems, LongLong integer on 64-bit systems) variables are stored as signed 32-bit (4-byte) numbers ranging in value from -2,147,483,648 to 2,147,483,647 on 32-bit systems; and signed 64-bit (8-byte) numbers ranging in value from -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 on 64-bit systems.

Note

LongPtr is not a true data type because it transforms to a Long in 32-bit environments, or a LongLong in 64-bit environments. Using LongPtr enables writing portable code that can run in both 32-bit and 64-bit environments. Use LongPtr for pointers and handles.

  • LongPtr - VBA now includes a variable type alias: LongPtr. The actual data type that LongPtr resolves to depends on the version of Office that it is running in: LongPtr resolves to Long in 32-bit versions of Office, and LongPtr resolves to LongLong in 64-bit versions of Office. Use LongPtr for pointers and handles.
  • LongLong – The LongLong data type is a signed 64-bit integer that is only available on 64-bit versions of Office. Use LongLong for 64-bit integrals. Conversion functions must be used to explicitly assign LongLong (including LongPtr on 64-bit platforms) to smaller integral types. Implicit conversions of LongLong to smaller integrals are not allowed.
  • PtrSafe – The PtrSafe keyword asserts that a Declare statement is safe to run in 64-bit versions of Office.
 
Upvote 0
Excel/Office của em là 32 bit, thì nó ra vậy là đúng rồi, chứ nhầm gì em ?
 
Upvote 0
Tôi cố tình thay dwTimeout của người hỏi thành dwMilliseconds - một cái tên nói lên điều cụ thể.
Còn 4000 vì người ta muốn đóng sau 4 s mà.
Em thấy cùng 1 vấn đề là Tự đông Close Msgbox trong 1 khoãng thời gian cho trước ta có thể sử dụng:
1/ Hàm API như anh viết
2/ CreateObject("Wscript.shell").PopUp

Vậy Em muốn Hỏi:

1/ Vấn đề em muốn hỏi là giữa 2 cái đó có sự yêu việt gì khác biệt trong sử dụng tự động đóng Msgbox
2/ Nếu nó như nhau thì tại sao Bác Bill lại sinh 2 cái khác biệt vậy ???
3/ Sử dụng API hay CreateObject yêu việt hơn ... Hay yêu việt hơn trong trường hợp nào ?! Tại sao

Mong Anh chỉ thêm cho Em một chút để em hiểu sâu hơn một chút xử lý cùng một vấn đề ở nhiều góc độ khác nhau xem có gì khác

Em cảm ơn
 
Upvote 0
Em thấy cùng 1 vấn đề là Tự đông Close Msgbox trong 1 khoãng thời gian cho trước ta có thể sử dụng:
1/ Hàm API như anh viết
2/ CreateObject("Wscript.shell").PopUp

Vậy Em muốn Hỏi:

1/ Vấn đề em muốn hỏi là giữa 2 cái đó có sự yêu việt gì khác biệt trong sử dụng tự động đóng Msgbox
2/ Nếu nó như nhau thì tại sao Bác Bill lại sinh 2 cái khác biệt vậy ???
3/ Sử dụng API hay CreateObject yêu việt hơn ... Hay yêu việt hơn trong trường hợp nào ?! Tại sao

Mong Anh chỉ thêm cho Em một chút để em hiểu sâu hơn một chút xử lý cùng một vấn đề ở nhiều góc độ khác nhau xem có gì khác

Em cảm ơn
Cái này bạn tự kiểm nghiệm, so sánh thôi.
Tôi không dùng Popup, mà cũng chả bao giờ so sánh. Tôi không đam mê những vấn đề loại như thế.
 
Upvote 0
Em thấy cùng 1 vấn đề là Tự đông Close Msgbox trong 1 khoãng thời gian cho trước ta có thể sử dụng:
1/ Hàm API như anh viết
2/ CreateObject("Wscript.shell").PopUp

Vậy Em muốn Hỏi:

1/ Vấn đề em muốn hỏi là giữa 2 cái đó có sự yêu việt gì khác biệt trong sử dụng tự động đóng Msgbox
2/ Nếu nó như nhau thì tại sao Bác Bill lại sinh 2 cái khác biệt vậy ???
3/ Sử dụng API hay CreateObject yêu việt hơn ... Hay yêu việt hơn trong trường hợp nào ?! Tại sao

Mong Anh chỉ thêm cho Em một chút để em hiểu sâu hơn một chút xử lý cùng một vấn đề ở nhiều góc độ khác nhau xem có gì khác

Em cảm ơn

Tôi chả hiểu mô tê gì trong cái thớt này cả.
Nhưng câu 2 tôi có thể tạm trả lòi cho bạn:
- VBA là một ngôn ngữ dùng để hổ trợ Excel. Vì vậy Microsoft có quyền đặt nó như tạp pí lù. Và họ cũng bắt buộc phải cho nó tạp pí lù để có thể vừa ý nhiều tầng lớp, nhiều phiên bản (của office).
Vì vậy, nếu bạn có thấy 2 cái gì đó "như nhau" thì cứ như bài #57 nói; bạn tự nghĩ ra những trường hợp để test chúng. Có thể làn đầu bạn thấy lộng cộng và có thể mất cả tháng trời. Nhưng sau khi thử chừng vài chục lần, bạn sẽ quen và biết cách thử hiệu quả hơn.

Riêng cho VBScript (không phải VBA) thì thế này:
Ngôn ngữ Script dùng để hổ trợ quản lý máy và hệ điều hành cho nên nó chỉ thích ứng với giao diện đơn giản. Ba cái API phức tạp vốn chỉ nên dùng khi không còn cách nào khác.
 
Upvote 0
Mới phát hiện ra vầy chạy Code bài 31 xong xuất hiện Msgbox có nút OK nếu không chọn OK thì mặc định sau 4s nó tự thoát

1/ Vậy khi xuất hiện Msgbox thì ko chọn OK cứ để vậy và thao tác vài thứ linh tinh khác trên Sheet thì sau 4s nó cũng tự thoát
2/ Còn Với CreateObject("Wscript.shell").Popup thao tác như mục 1 thì nó vẫn cứ đơ ra đó hoài không thoát ............ tại sao ?
3/ Nếu ta không thao tác gì thêm thì CreateObject("Wscript.shell").Popup nó mới tự thoát .....Tại sao ta ???

Vậy là API nhiều khả năng chính xác hơn .Popup
Bạn nào rảnh test xem có đúng không .............,,,,,,,.........Code két mà có quậy tanh bành ra mới thấy
 
Upvote 0
Reverse ra thì dài dòng, nên em nói nôm na vầy thôi.
Wscript.Shell COM object được implement trong System32 (hay SysWOW64) wshom.ocx.
Method Popup được MS coder code nôm na như sau:
Function prototype:
virtual long __stdcall CWshShell::Popup(unsigned short *, struct tagVARIANT *, struct tagVARIANT *, struct tagVARIANT *, int *)
1. CreateThread với ThreadProc là 1 hàm ngắn, chỉ gọi MessageBoxW
2.Thực hiện Wait với timeout chỉ định = các hàm API sau: MsgWaitForMultipleObjects và parse message loop với PeekMessage, TranslateMessage, DispatchMessage
3. Trong trường hợp user click OK, Wait proc return, call GetExitCodeThread và CloseHandle cho thread vừa tạo.
4. User không click OK, msgbox vẫn còn display, gọi hàm EnumThreadWindows với hThread là handle của thread vừa tạo, trong EnumProc gọi PostMessage cho hWnd của thread đó, tức hWnd của MessageBoxW,
với uMsg = WM_QUIT, wParam = 0xABCDEFBB, lParam = 0
5. Xong, window của MessageBoxW đã mất, gọi WaitForSingleObject(hThread, INFINITE) cho ThreadProc ở trên thoát, thread thoát, gọi CloseHandle(hThread)
Xong method Popup.
Do phải sinh thread cho MessageBox, nên time schedule cho thread không còn chính xác khi user thực hiện các tác vụ khác, đẩy thread đó xuống không còn ưu tiên chiếm CPU time.
Nên các bạn thấy nó không đúng thời gian timeout là vậy.
 
Lần chỉnh sửa cuối:
Upvote 0
Web KT

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

Back
Top Bottom