Cách đóng hộp MsgBox tự động? (3 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ì đúng vậy! UserForm dễ hơn!
Vấn đề là bạn vẫn dùng Sleep thì chẳng hay tí nào ---> Cố gắng SetTimer xem ---> Hàm này tuyệt cú mèo, nhưng cũng hơi khó dùng

Ngoài cái code đó của em ra còn có cái này nữa là em làm được:

PHP:
Private Sub Dem2()
  Dim SetTime As Double, kt As Double
  SetTime = TimeSerial(0, 0, 2)   'Hoac TimeValue("00:00:2")
  Do
    Label3.Caption = Format(SetTime, "HH:mm:ss")
    SetTime = SetTime - TimeValue("00:00:01")
    kt = Timer
    Do While Timer - kt < 1
      DoEvents
      If Label3.Caption = "00:00:00" Then: Unload Me: Exit Sub
    Loop
  Loop
End Sub
 
Private Sub UserForm_Activate()
  Dem2
End Sub

Chứ SetTimer như Thầy nói thì em bó cái tay:

PHP:
Declare Function SetTimer Lib "user32" (ByVal hWnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
Declare Function KillTimer Lib "user32" (ByVal hWnd As Long, ByVal nIDEvent As Long) As Long
 
Lần chỉnh sửa cuối:
Upvote 0
Chứ SetTimer như Thầy nói thì em bó cái tay:
Tặng đồng chí đây:
1> Trong UserForm
PHP:
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
  (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" _
  (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
PHP:
Private Sub UserForm_Initialize()
  Dim hT As Double
  iT = 50: Total = iT: sWidth = Label2.Width / iT
  hT = Me.Height - Me.InsideHeight
  hWnd = FindWindow("ThunderDFrame", Me.Caption)
  SetWindowLong hWnd, -16, &H84080080
  Me.Height = Me.Height - hT
End Sub
2> Trong Module
PHP:
Private Declare Function SetTimer Lib "user32" _
  (ByVal hWnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
Private Declare Function KillTimer Lib "user32" (ByVal hWnd As Long, ByVal nIDEvent As Long) As Long
Public iT As Long, Total As Long, hWnd As Long, sWidth As Double
PHP:
Private Sub ACForm()
  With UserForm1
    .Label1.Caption = .Label4.Caption & Int(iT / 10) + 1 & " giây sau nhé!.. Ec.. Ec.."
    .Label2.Width = sWidth * iT
    .Label3.ForeColor = IIf(Int(iT / 5) Mod 2, &H8000000E, &HFF&)
  End With
  If (iT Mod 10) = 0 Then Beep
  iT = iT - 1
  If iT = 0 Then
    StopMsg
    Unload UserForm1
  End If
End Sub
PHP:
Sub StartMsg()
  StopMsg
  UserForm1.Show
  SetTimer hWnd, 0, 100, AddressOf ACForm
End Sub
PHP:
Sub StopMsg()
  KillTimer hWnd, 0
  Unload UserForm1
End Sub
Cái MsgBox giả lập ấy có hình dáng thế này

untitled.JPG

Xem code chẳng có vòng lập nào đâu nhé ---> Cái SetTimer nó điều khiển tất, đến khi gọi KillTimer thì dừng
Cái hay của SetTimer là khi chạy nó chẳng ảnh hưởng đến bất kỳ công việc nào của ta cả (tức nó chạy, nó cứ chạy... Việc ta, ta cứ làm...)
Chạy thử file xem ngon lành không?
(File hoàn tất với sự gợi ý của Nguyễn Duy Tuân)
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Tặng đồng chí đây:
1> Trong UserForm
PHP:
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
  (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" _
  (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
PHP:
Private Sub UserForm_Initialize()
  Dim hT As Double
  iT = 50: Total = iT: sWidth = Label2.Width / iT
  hT = Me.Height - Me.InsideHeight
  hWnd = FindWindow("ThunderDFrame", Me.Caption)
  SetWindowLong hWnd, -16, &H84080080
  Me.Height = Me.Height - hT
End Sub
2> Trong Module
PHP:
Private Declare Function SetTimer Lib "user32" _
  (ByVal hWnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
Private Declare Function KillTimer Lib "user32" (ByVal hWnd As Long, ByVal nIDEvent As Long) As Long
Public iT As Long, Total As Long, hWnd As Long, sWidth As Double
PHP:
Private Sub ACForm()
  With UserForm1
    .Label1.Caption = .Label4.Caption & Int(iT / 10) + 1 & " giây sau nhé!.. Ec.. Ec.."
    .Label2.Width = sWidth * iT
    .Label3.ForeColor = IIf(Int(iT / 5) Mod 2, &H8000000E, &HFF&)
  End With
  If (iT Mod 10) = 0 Then Beep
  iT = iT - 1
  If iT = 0 Then
    StopMsg
    Unload UserForm1
  End If
End Sub
PHP:
Sub StartMsg()
  StopMsg
  UserForm1.Show
  SetTimer hWnd, 0, 100, AddressOf ACForm
End Sub
PHP:
Sub StopMsg()
  KillTimer hWnd, 0
  Unload UserForm1
End Sub
Cái MsgBox giả lập ấy có hình dáng thế này

View attachment 51703

Xem code chẳng có vòng lập nào đâu nhé ---> Cái SetTimer nó điều khiển tất, đến khi gọi KillTimer thì dừng
Cái hay của SetTimer là khi chạy nó chẳng ảnh hưởng đến bất kỳ công việc nào của ta cả (tức nó chạy, nó cứ chạy... Việc ta, ta cứ làm...)
Chạy thử file xem ngon lành không?
(File hoàn tất với sự gợi ý của Nguyễn Duy Tuân)
thêm đoạn mã code vào ThisWorkbook:
PHP:
Option Explicit
Private Sub Workbook_open()
 On Error Resume Next
    UserForm1.Show
End Sub
thì nó hiện lên UF rồi đứng ở đó lên không thấy run gì cả !
 
Upvote 0
thêm đoạn mã code vào ThisWorkbook:
PHP:
Option Explicit
Private Sub Workbook_open()
 On Error Resume Next
    UserForm1.Show
End Sub
thì nó hiện lên UF rồi đứng ở đó lên không thấy run gì cả !
Đồng chí này máy móc quá ---> Đâu phải show form lên là nó chạy đâu ---> Trước đó nó còn làm vài thứ khác cơ mà
Hic...
Muốn tự động mở form khi file khởi động, chỉ việc sửa tên sub StartMsg thành Auto_Open thì xong
Còn muốn dùng sự kiện Workbook_open thì phải thế này:
PHP:
Private Sub Workbook_open()
  StartMsg
End Sub
 
Upvote 0
Mình tìm thấy được cái này hiển thị thông báo đơn giản và có thể đóng lại theo thời gian hẹn trước gửi mọi người tham khảo.
 

File đính kèm

Upvote 0
Mình tìm thấy được cái này hiển thị thông báo đơn giản và có thể đóng lại theo thời gian hẹn trước gửi mọi người tham khảo.
Dùng WScript.Shell mình đã từng nói nhiều lần rồi mà
Chẳng hạn tại đây:
http://www.giaiphapexcel.com/forum/showthread.php?38289-H%C3%A0m-ChrW-hi%E1%BB%83n-th%E1%BB%8B-kh%C3%B4ng-ch%C3%ADnh-x%C3%A1c&
MsgBox loại này còn có khả năng hiển thị được tiếng Việt Unicode nữa đấy
(có điều cái chức năng hẹn giờ thì không mấy ổn định)
 
Lần chỉnh sửa cuối:
Upvote 0
Nhờ các Bác sửa lỗi giúp em.
Sau khi em khai báo lại các hàm "user32"

File "Form_CountDown_2.xlsm" đã chạy được rồi. Nhưng sau khi đã xuất lệnh chạy thì vào VBA chỉnh sửa chương trình thì Excel bị treo.
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
em có được một thanh viên cao thủ chỉ thêm cách tạo msgbox tự động đóng nhưng khi không chọn gì thì giá trị nó luôn là -1
vậy có cách nào cho nó chọn một trong các nút mình định sẵn được không ạ
em có chỉnh sửa lại thế này
PHP:
Public Function UniMsgbox(Optional NoiDung As String = "", _
            Optional TieuDe As String = "Thông Báo", _
            Optional ThoiGianDong As Byte = 1, _
            Optional KieuNutLenh As Byte = 0, _
            Optional KieuIcon As Byte = 0, _
            Optional LenhMacDinh As Byte = 1)
Rem     'KieuNutLenh:   0   -OK     | 1 -OK Cancel  | 2 - Abort Retry Ignore    | 3 - Yes No CanCel     | 4- Yes No | 5- Retry Cancel
Rem     'KieuIcon:      16  -(X)    | 32-(?)        | 48-/!\                    | 64-(!)                | 0-....
Rem     'UniMsgbox:     1   -OK     | 2 - Cancel    | 3 - Abort                 | 4 - Retry             | 5- Ignore | 6- Yes    | 7- No
    LenhMacDinh = WorksheetFunction.Min(WorksheetFunction.Max(LenhMacDinh, 1), 3)
    UniMsgbox = CreateObject("Wscript.shell").PopUp(NoiDung, ThoiGianDong, TieuDe, KieuNutLenh + KieuIcon + (LenhMacDinh - 1) * 256)
If UniMsgbox = -1 And KieuNutLenh > 0 Then
    Dim Arr As Variant
    Arr = Switch(LenhMacDinh = 1, Array(1, 3, 6, 6, 4), LenhMacDinh = 2, Array(2, 4, 7, 7, 2), LenhMacDinh = 3, Array(2, 5, 2, 7, 2))
    UniMsgbox = Arr(KieuNutLenh - 1)
End If
End Function


Sub TEST1()
Dim Arr As Variant
Arr = Array("", "OK", "Cancel", "Abort", "Retry", "Ignore", "Yes", "No")
UniMsgbox "Gia tri Msgbox tra ve : " & Arr(UniMsgbox("Dung Co Chon Gi Het Nha", "Test", 1, 3, 0, 1))
UniMsgbox "Gia tri Msgbox tra ve : " & Arr(UniMsgbox("Dung Co Chon Gi Het Nha", "Test", 1, 3, 0, 2))
UniMsgbox "Gia tri Msgbox tra ve : " & Arr(UniMsgbox("Dung Co Chon Gi Het Nha", "Test", 1, 3, 0, 3))
End Sub
mà thấy nó rườm rà chỗ tự xử lý sao ấy, có cách nào dễ hơn không ạ
 
Lần chỉnh sửa cuối:
Upvote 0
Các loại MsgBox mà ta từng biết trên Excel, chẳng có cái nào có thể viết tiếng Việt Unicode trên Title cả
Muốn hoàn hảo thì dùng MsgBox của Windows đi!
(chữ THÔNG BÁO nó hiện đựoc là vì... hên ---> ký tự Ô có charcode = 212, ký tự Á có charcode = 193... đều < 255)

Kính gửi anh ndu96081631
Em có file tự động đóng MsgBox nhưng không thể đưa Unicode cho dòng thông báo được. Anh giúp em hiển thị tiếng Việt thì tốt quá.
Em sử dụng code này do khi chạy trên Form, khi MsgBox hiển thị, nếu mình không bấm OK mà bấm trực tiếp vào Form nó sẽ ẩn bảng MsgBox. Code này nó vẫn tiếp tục làm việc (sẽ tắt MsgBox) khi mình làm việc khác trên Form.
Cảm ơn anh nhiều
 

File đính kèm

Upvote 0
Em có file tự động đóng MsgBox nhưng không thể đưa Unicode cho dòng thông báo được. Anh giúp em hiển thị tiếng Việt thì tốt quá.
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
 
Lần chỉnh sửa cuối:
Upvote 0
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 Long, ByVal lpCaption As Long, _
                                                        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

Hay quá. Em cảm ơn bác nhiều lắm.
Chỉ có điều, nếu dùng: MsgBoxTimeout = MessageBoxTimeoutW(0, StrPtr(message), StrPtr(Title), flags, 0, timeout)
thì ra toàn chữ Nhật hay TQ gì đấy.
Còn nếu dùng cái này: MsgBoxTimeout = MessageBoxTimeoutW(0, StrConv(message, vbUnicode), StrConv(Title, vbUnicode), flags, 0, timeout)
thì OK.

Em xin cảm ơn bác một lần nữa!
 
Upvote 0
Code mình tương tự code của batman1, chỉ # chút xíu, đố ai tìm ra và tại sao :)
Cậu xóa hết code của UserForm1, pass code dưới vào, test thử nhen:
Mã:
#If VBA7 Then
Private Declare PtrSafe Function MessageBoxTimeout Lib "user32" _
        Alias "MessageBoxTimeoutW" (ByVal hWnd As LongPtr, _
            ByVal lpText As LongPtr, ByVal lpCaption As LongPtr, _
            ByVal wType As VbMsgBoxStyle, ByVal wlange As Long, _
            ByVal dwTimeout As Long) As Long
#Else
Private Declare Function MessageBoxTimeout Lib "user32" _
        Alias "MessageBoxTimeoutW" (ByVal hWnd As Long, _
            ByVal lpText As Long, ByVal lpCaption As Long, _
            ByVal wType As VbMsgBoxStyle, ByVal wlange As Long, _
            ByVal dwTimeout As Long) As Long
#End If

Public Function MsgBoxUniTimeout(ByVal strText As String, ByVal strCaption As String, ByVal wType As VbMsgBoxStyle, ByVal dwTimeout As Long) As Long
    MsgBoxUniTimeout = MessageBoxTimeout(0, StrPtr(strText), StrPtr(strCaption), wType, 0, dwTimeout)
End Function

Private Sub CommandButton1_Click()
    Call MsgBoxUniTimeout("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", "Thông báo", vbInformation, 6000)
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Hì hì, đang test trên Office 2010, x64, quên xóa.
Sữa rồi đó cô nương :)
 
Upvote 0
Chỉ có điều, nếu dùng: MsgBoxTimeout = MessageBoxTimeoutW(0, StrPtr(message), StrPtr(Title), flags, 0, timeout)
thì ra toàn chữ Nhật hay TQ gì đấy.
Làm gì có

Tôi cho bạn 2 phiên bản.

Nếu dùng phiên bản 2 thì mới có
MsgBoxTimeout = MessageBoxTimeoutW(0, StrPtr(message), StrPtr(Title), flags, 0, timeout)

Nhưng với phiên bản 2 thì phải
#If VBA7 Then
Public Declare PtrSafe Function MessageBoxTimeoutW Lib "user32" (ByVal hWnd As LongPtr, _
ByVal lpText As Long, ByVal lpCaption As Long, _
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

Đã cố tình tách 2 phiên bản riêng rẽ nhau (để ở 2 [...code] ... [/...code] khác nhau), đọc mà không hiểu thì bótay.com
 
Lần chỉnh sửa cuối:
Upvote 0
Function StrPtr(Ptr As String) As LongPtr
Member of VBA._HiddenModule
Trên x86, LongPtr = Long
Trên x64, LongPtr = LongLong
Pointer, handle... trong win64 luôn là 64 bit size.
 
Upvote 0
Đúng là quên. Ở trên là LongPtr, ở dưới là Long. Đã sửa ở bài đầu
 
Upvote 0
BSTR to and from a DLL: Visual Basic - Visual C++/Delphi...
Again from the MSDN documentation (in a remote part of it, to be honest !), we read what follows:
  1. Visual Basic always creates a new BSTR containing ANSI characters (not UNICODE ones!) when passing a string to a DLL
  2. Visual Basic always gets a BSTR containing UNICODE characters when getting a string from a DLL
This can be a problem, from the DLL point of view, as Visual C++ always exports and imports UNICODE strings.

So, the DLL must deal at runtime, with both the cases of input BSTR:
  1. If called from a Visual Basic application: input BSTR contains ANSI characters
  2. If called from a Visual C++ application: input BSTR contains UNICODE characters
Luckily enough, the DLL will always export BSTR with UNICODE characters.
 
Upvote 0
Web KT

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

Back
Top Bottom