显示带有超时值的消息框

问题描述 投票:5回答:4

问题来自这样的代码。

Set scriptshell = CreateObject("wscript.shell")
    Const TIMEOUT_IN_SECS = 60
    Select Case scriptshell.popup("Yes or No? leaving this window for 1 min is the same as clicking Yes.", TIMEOUT_IN_SECS, "popup window", vbYesNo + vbQuestion)
        Case vbYes
            Call MethodFoo
        Case -1
            Call MethodFoo
    End Select

这是一种显示带有VBA(或VB6)超时的消息框的简单方法。

在Excel 2007中(显然有时也会在Internet Explorer中发生)弹出窗口不会超时,而是等待用户输入。

这个问题很难调试,因为它偶尔会发生,我不知道重现问题的步骤。我认为这是Office模式对话框和Excel无法识别超时已过期的问题。

http://social.technet.microsoft.com/Forums/en-US/ITCG/thread/251143a6-e4ea-4359-b821-34877ddf91fb/

我找到的解决方法是:

A.使用Win32 API调用

Declare Function MessageBoxTimeout Lib "user32.dll" Alias "MessageBoxTimeoutA" ( _
ByVal hwnd As Long, _
ByVal lpText As String, _
ByVal lpCaption As String, _
ByVal uType As Long, _
ByVal wLanguageID As Long, _
ByVal lngMilliseconds As Long) As Long

Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" ( _
ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long

Public Sub MsgBoxDelay()
    Const cmsg As String = "Yes or No? leaving this window for 1 min is the same as clicking Yes."
    Const cTitle As String = "popup window"
    Dim retval As Long
    retval = MessageBoxTimeout(FindWindow(vbNullString, Title), cmsg, cTitle, 4, 0, 60000)

    If retval <> 7 Then
        Call MethodFoo
    End If

End Sub  

B.使用手动计时器和VBA用户表单,其设计看起来像一个消息框。使用全局变量或类似函数来保存需要传递回调用代码的任何状态。确保使用提供的vbModeless参数调用userform的Show方法。

C.在MSHTA进程中包含对wscript.popup方法的调用,这将允许代码用完进程并避免Office的模式性质。

CreateObject("WScript.Shell").Run "mshta.exe vbscript:close(CreateObject(""WScript.Shell"").Popup(""Test"",2,""Real%20Time%20Status%20Message""))"

在VBA中显示带有超时值的消息框时,A,B或C的最佳方式或您自己的答案是什么?

vba excel-vba messagebox winapi wsh
4个回答
7
投票

这是一个很长的答案,但有很多理由可以解决:它也是一个迟到的回复,但事情已经改变,因为一些回复(和类似的问题)已经发布在堆栈上。这就像三相AC上的真空吸尘器一样糟糕,因为当它们被发布时它们是很好的答案并且很多想法都进入了它们。

简短的版本是:我注意到脚本WshShell Popup解决方案在一年前停止在VBA中工作,我为VBA MsgBox函数编写了一个有效的API计时器回调。

如果你急需一个答案,请直接跳到标题VBA代码下的代码调用带有超时的消息框 - 我做了,我确实有成千上万的自我解雇'MsgPopup'代替VBA.MsgBox的实例编辑,下面的代码适合自包含的模块。

然而,这里的VBA编码器 - 包括我自己 - 需要一些解释,为什么完美的代码似乎不再起作用。如果您了解原因,您可以使用隐藏在文本中的“取消”对话框的部分解决方法。

我注意到脚本WshShell Popup解决方案在一年前停止在VBA中工作 - 'SecondsToWait'超时被忽略了,对话框就像熟悉的VBA.MsgBox一样挂了:

MsgPopup = objWShell.PopUp(Prompt, SecondsToWait, Title, Buttons)

我想我知道原因:你不能再从打开它的线程以外的任何地方向对话框窗口发送WM_CLOSE或WM_QUIT消息。同样,User32 DestroyWindow()函数不会关闭对话框窗口,除非它被打开对话框的线程调用。

Redmond中的某个人不喜欢在后台运行脚本的想法,并且发送WM_CLOSE命令来停止所有那些停止工作的基本警告(而且,这些天,让它们永久消失需要本地管理员权限)。

我无法想象谁会写这样的剧本,这是一个糟糕的主意!

该决定会产生后果和附带损害:单线程VBA环境中的WsScript.Popup()对象使用Timer回调实现其'SecondsToWait'超时,并且该回调发送WM_CLOSE消息,或者类似的东西......在大多数情况下会被忽略,因为它是一个回调线程,而不是对话框的所有者线程。

您可以使用“取消”按钮在弹出窗口上进行操作,并且很清楚为什么会在一两分钟内完成。

我已经尝试将一个定时器回调写入WM_CLOSE弹出窗口,在大多数情况下,对我来说也失败了。

我已经尝试了一些异乎寻常的API回调来搞乱VBA.MsgBox和WsShell.Popup窗口,我现在可以告诉你,它们没有用。你无法使用那些不存在的东西:那些对话框窗口非常简单,大多数都没有任何功能,除了按钮点击中的响应 - 是,否,确定,取消,中止,重试,忽略和帮助。

“取消”是一个有趣的问题:当您指定vbOKCancelvbRetryCancelvbYesNoCancel时,看起来您从原始Windows API获取内置对话框的免费赠品 - “取消”功能通过“关闭”按钮自动实现对话框的菜单栏(你没有得到其他按钮,但随意尝试使用包含'忽略'的对话框),这意味着....

WsShell.Popup() dialogs will sometimes respond to the SecondsToWait timeout if they have a 'Cancel' option.

objWShell.PopUp("Test&nbsp;Me",&nbsp;10,&nbsp;"Dialog&nbsp;Test",&nbsp;vbQuestion&nbsp;+&nbsp;vbOkCancel)

如果您想要的是让WsShell.Popup()函数再次响应SecondsToWait参数,那么对于阅读此内容的人来说,这可能是一个很好的解决方法。

这也意味着您可以使用回调上的SendMessage()API调用将WM_CLOSE消息发送到“取消”对话框:

SendMessage(hwndDlgBox, WM_CLOSE, ByVal 0&, ByVal 0&)

严格来说,这应该仅适用于WM_SYSCOMMAND, SC_CLOSE消息 - 命令栏中的“关闭”框是一个带有特殊命令类的“系统”菜单,但就像我说的那样,我们从Windows API获得免费赠品。

我开始工作了,我开始思考:如果我只能在那里工作,也许我最好找出实际上有什么......

答案结果显而易见:对话框有自己的一组WM_COMMAND消息参数 -

' Dialog window message parameters, replicating Enum vbMsgBoxResult:
CONST dlgOK      As Long = 1
CONST dlgCANCEL  As Long = 2
CONST dlgABORT   As Long = 3
CONST dlgRETRY   As Long = 4
CONST dlgIGNORE  As Long = 5
CONST dlgYES     As Long = 6
CONST dlgNO      As Long = 7

并且,由于这些是将用户响应返回给对话框的调用者(也就是调用线程)的“用户”消息,因此对话框很乐意接受它们并关闭它们自己。

您可以询问对话框窗口以查看它是否实现了特定命令,如果是,则可以发送该命令:

If GetDlgItem(hWndMsgBox, vbRetry) <> 0 Then
    SendMessage hWndMsgBox, WM_COMMAND, vbRetry, 0&
    Exit For
End If

剩下的挑战是检测'超时'并拦截返回的消息框响应,并替换我们自己的值:-1如果我们遵循WsShell.Popup()函数建立的约定。所以我们的'msgPopup'包含超时消息框的包装需要做三件事:

  1. 调用我们的API Timer来延迟解除对话框;
  2. 打开消息框,传入通常的参数;
  3. 要么:检测超时并替换'超时'响应... ...或者如果他们及时回复,则将用户响应返回到对话框

在其他地方,我们需要为所有这些声明API调用,并且我们必须具有公开声明的'TimerProc'函数以供Timer API调用。该函数必须存在,它必须运行到'End Function'而没有错误或断点 - 任何中断,并且API Timer()将调用操作系统的愤怒。

使用超时调用消息框的VBA代码:

Option Explicit
Option Private Module<BR />
' Nigel Heffernan January 2016<BR />
' Modified from code published by Microsoft on MSDN, and on StackOverflow: this code is in<BR />' the public domain.<BR />
' This module implements a message box with a 'timeout'<BR />
' It is similar to implementations of the WsShell.Popup() that use a VB.MessageBox interface
' with an additional 'SecondsToWait' or 'Timeout' parameter.<BR />
Private m_strCaption As String<BR />
Public Function MsgPopup(Optional Prompt As String, _
                         Optional Buttons As VbMsgBoxStyle = vbOKOnly, _
                         Optional Title As String, _
                         Optional SecondsToWait As Long = 0) As VbMsgBoxResult<BR />
' Replicates the VBA MsgBox() function, with an added parameter to automatically dismiss the message box after n seconds
' If dismissed automatically, this will return -1: NOT 'cancel', nor the default button choice.<BR />
Dim TimerStart As Single<BR />
If Title = "" Then
    Title = ThisWorkbook.Name
End If<BR />
If SecondsToWait &GT; 0 Then
    ' TimedmessageBox launches a callback to close the MsgBox dialog
    TimedMessageBox Title, SecondsToWait
    TimerStart = VBA.Timer
End If<BR /><BR />
MsgPopup = MsgBox(Prompt, Buttons, Title)<BR /><BR />
If SecondsToWait &GT; 0 Then
    ' Catch the timeout, substitute -1 as the response
    If (VBA.Timer - TimerStart) &GT;= SecondsToWait Then
        MsgPopup = -1
    End If
End If<BR />
End Function<BR />

Public Function MsgBoxResultText(ByVal MsgBoxResult As VbMsgBoxResult) As String<BR />' Returns a text value for the integers returned by VBA MsgBox() and WsShell.Popup() dialogs<BR />
' Additional value: 'TIMEOUT', returned when the MsgBoxResult = -1<BR />' All other values return the string 'ERROR'<BR /><BR />
On Error Resume Next<BR /><BR />
If (MsgBoxResult &GT;= vbOK) And (MsgBoxResult &LT;= vbNo) Then
    MsgBoxResultText = Split("ERROR,OK,CANCEL,ABORT,RETRY,IGNORE,YES,NO,", ",")(MsgBoxResult)
ElseIf MsgBoxResult = dlgTIMEOUT Then
    MsgBoxResultText = "TIMEOUT"
Else
    MsgBoxResultText = "ERROR"
End If<BR />End Function
'
'
'
'
'
'
'
'
'
'
Private Property Get MessageBox_Caption() As String
    MessageBox_Caption = m_strCaption
End Property<BR />
Private Property Let MessageBox_Caption(NewCaption As String)
    m_strCaption = NewCaption 
End Property<BR /><BR />
Private Sub TimedMessageBox(Caption As String, Seconds As Long)
On Error Resume Next<BR />
    ' REQUIRED for Function msgPopup
   ' Public Sub  TimerProcMessageBox  MUST EXIST<BR />
    MessageBox_Caption = Caption<BR />
    SetTimer 0&, 0&, Seconds * 1000, AddressOf TimerProcMessageBox<BR />
    Debug.Print "start Timer " & Now<BR />
End Sub<BR />

&#35;If VBA7 And Win64 Then     ' 64 bit Excel under 64-bit windows<BR />                                ' Use LongLong and LongPtr<BR /><BR />
    Public Sub TimerProcMessageBox(ByVal hwnd As LongPtr, _
                                   ByVal wMsg As Long, _
                                   ByVal idEvent As LongPtr, _
                                   ByVal dwTime As LongLong)
    On Error Resume Next<BR />
    ' REQUIRED for Function msgPopup
    ' https://msdn.microsoft.com/en-US/library/windows/desktop/ms644907(v=vs.85).aspx<BR />
    ' Closes a dialog box (Shell.Popup or VBA.MsgBox) having a caption stored in MessageBox_Caption
    ' This TimerProc sends *any* message that can close the dialog: the objective is solely to close
    ' the dialog and resume the VBA thread. Your caller must detect the expired TimerProc interval
    ' and insert a custom return value (or default) that signals the 'Timeout' for responses.<BR />
    ' The MsgPopup implementation in this project returns -1 for this 'Timeout'<BR />
    Dim hWndMsgBox As LongPtr   ' Handle to VBA MsgBox<BR />
    KillTimer hWndMsgBox, idEvent<BR />
    hWndMsgBox = 0
    hWndMsgBox = FindWindow("&#35;32770", MessageBox_Caption)<BR />
    If hWndMsgBox &LT;&GT; 0 Then<BR />
        ' Enumerate WM_COMMAND values
        For iDlgCommand = vbOK To vbNo
            If GetDlgItem(hWndMsgBox, iDlgCommand) &LT;&GT; 0 Then
                SendMessage hWndMsgBox, WM_COMMAND, iDlgCommand, 0&
                Exit For
            End If
        Next iDlgCommand<BR />
    End If<BR />
    End Sub<BR />

&#35;ElseIf VBA7 Then    ' 64 bit Excel in all environments<BR />                         ' Use LongPtr only<BR /><BR />
    Public Sub TimerProcMessageBox(ByVal hwnd As LongPtr, _
                                   ByVal wMsg As Long, _
                                   ByVal idEvent As LongPtr, _
                                   ByVal dwTime As Long)
    On Error Resume Next<BR />                         
    ' REQUIRED for Function msgPopup
    ' https://msdn.microsoft.com/en-US/library/windows/desktop/ms644907(v=vs.85).aspx<BR />
    ' Closes a dialog box (Shell.Popup or VBA.MsgBox) having a caption stored in MessageBox_Caption
    ' This TimerProc sends *any* message that can close the dialog: the objective is solely to close
    ' the dialog and resume the VBA thread. Your caller must detect the expired TimerProc interval
    ' and insert a custom return value (or default) that signals the 'Timeout' for responses.<BR />    
    ' The MsgPopup implementation in this project returns -1 for this 'Timeout'<BR />
    Dim hWndMsgBox  As LongPtr          ' Handle to VBA MsgBox
    Dim iDlgCommand As VbMsgBoxResult   ' Dialog command values: OK, CANCEL, YES, NO, etc<BR />
    KillTimer hwnd, idEvent<BR />
    hWndMsgBox = 0
    hWndMsgBox = FindWindow("&#35;32770", MessageBox_Caption)<BR />
    If hWndMsgBox &LT;&GT; 0 Then<BR />
        ' Enumerate WM_COMMAND values 
        For iDlgCommand = vbOK To vbNo
            If GetDlgItem(hWndMsgBox, iDlgCommand) &LT;&GT; 0 Then
                SendMessage hWndMsgBox, WM_COMMAND, iDlgCommand, 0&
                Exit For
            End If
        Next iDlgCommand<BR />
    End If<BR />
    End Sub<BR />

&#35;Else    ' 32 bit Excel<BR /><BR />
    Public Sub TimerProcMessageBox(ByVal hwnd As Long, _
                                   ByVal wMsg As Long, _
                                   ByVal idEvent As Long, _
                                   ByVal dwTime As Long)
    On Error Resume Next<BR />
    ' REQUIRED for Function msgPopup<BR />
    ' The MsgPopup implementation in this project returns -1 for this 'Timeout'<BR />
    Dim hWndMsgBox As Long    ' Handle to VBA MsgBox<BR />
    KillTimer hwnd, idEvent<BR />
    hWndMsgBox = 0
    hWndMsgBox = FindWindow("&#35;32770", MessageBox_Caption)<BR />
    If hWndMsgBox &LT;&GT; 0 Then<BR />
        ' Enumerate WM_COMMAND values 
        For iDlgCommand = vbOK To vbNo
            If GetDlgItem(hWndMsgBox, iDlgCommand) &LT;&GT; 0 Then
                SendMessage hWndMsgBox, WM_COMMAND, iDlgCommand, 0&
                Exit For
            End If
        Next iDlgCommand<BR />
    End If<BR />
    End Sub<BR />
&#35;End If

以下是API声明 - 请注意VBA7,64位Windows和普通32位的条件声明:

'&nbsp;Explanation&nbsp;of&nbsp;compiler&nbsp;constants&nbsp;for&nbsp;64-Bit&nbsp;VBA&nbsp;and&nbsp;API&nbsp;declarations&nbsp;:
'&nbsp;https://msdn.microsoft.com/en-us/library/office/ee691831(v=office.14).aspx

&#35;If&nbsp;VBA7&nbsp;And&nbsp;Win64&nbsp;Then&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'&nbsp;64&nbsp;bit&nbsp;Excel&nbsp;under&nbsp;64-bit&nbsp;windows&nbsp;'&nbsp;Use&nbsp;LongLong&nbsp;and&nbsp;LongPtr
&nbsp;&nbsp;&nbsp;&nbsp;Private&nbsp;Declare&nbsp;PtrSafe&nbsp;Function&nbsp;FindWindow&nbsp;Lib&nbsp;"user32"&nbsp;Alias&nbsp;"FindWindowA"&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(ByVal&nbsp;lpClassName&nbsp;As&nbsp;String,&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ByVal&nbsp;lpWindowName&nbsp;As&nbsp;String)&nbsp;As&nbsp;LongPtr
&nbsp;&nbsp;&nbsp;&nbsp;Private&nbsp;Declare&nbsp;PtrSafe&nbsp;Function&nbsp;SendMessage&nbsp;Lib&nbsp;"user32"&nbsp;Alias&nbsp;"SendMessageA"&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(ByVal&nbsp;hwnd&nbsp;As&nbsp;LongPtr,&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ByVal&nbsp;wMsg&nbsp;As&nbsp;Long,&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ByVal&nbsp;wParam&nbsp;As&nbsp;Long,&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ByRef&nbsp;lParam&nbsp;As&nbsp;Any&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)&nbsp;As&nbsp;LongPtr
&nbsp;&nbsp;&nbsp;&nbsp;Private&nbsp;Declare&nbsp;PtrSafe&nbsp;Function&nbsp;SetTimer&nbsp;Lib&nbsp;"user32"&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(ByVal&nbsp;hwnd&nbsp;As&nbsp;LongPtr,&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ByVal&nbsp;nIDEvent&nbsp;As&nbsp;LongPtr,&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ByVal&nbsp;uElapse&nbsp;As&nbsp;Long,&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ByVal&nbsp;lpTimerFunc&nbsp;As&nbsp;LongPtr&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)&nbsp;As&nbsp;Long
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Public&nbsp;Declare&nbsp;PtrSafe&nbsp;Function&nbsp;KillTimer&nbsp;Lib&nbsp;"user32"&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(ByVal&nbsp;hwnd&nbsp;As&nbsp;LongPtr,&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ByVal&nbsp;nIDEvent&nbsp;As&nbsp;LongPtr&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)&nbsp;As&nbsp;Long
&nbsp;&nbsp;&nbsp;&nbsp;Private&nbsp;Declare&nbsp;PtrSafe&nbsp;Function&nbsp;GetDlgItem&nbsp;Lib&nbsp;"user32"&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(ByVal&nbsp;hWndDlg&nbsp;As&nbsp;LongPtr,&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ByVal&nbsp;nIDDlgItem&nbsp;As&nbsp;Long&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)&nbsp;As&nbsp;LongPtr
&nbsp;&nbsp;&nbsp;&nbsp;
&#35;ElseIf&nbsp;VBA7&nbsp;Then&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'&nbsp;VBA7&nbsp;in&nbsp;all&nbsp;environments,&nbsp;including&nbsp;32-Bit&nbsp;Office&nbsp;&nbsp;'&nbsp;Use&nbsp;LongPtr&nbsp;for&nbsp;ptrSafe&nbsp;declarations,&nbsp;LongLong&nbsp;is&nbsp;not&nbsp;available

&nbsp;&nbsp;&nbsp;&nbsp;Private&nbsp;Declare&nbsp;PtrSafe&nbsp;Function&nbsp;FindWindow&nbsp;Lib&nbsp;"user32"&nbsp;Alias&nbsp;"FindWindowA"&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(ByVal&nbsp;lpClassName&nbsp;As&nbsp;String,&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ByVal&nbsp;lpWindowName&nbsp;As&nbsp;String)&nbsp;As&nbsp;LongPtr
&nbsp;&nbsp;&nbsp;&nbsp;Private&nbsp;Declare&nbsp;PtrSafe&nbsp;Function&nbsp;SendMessage&nbsp;Lib&nbsp;"user32"&nbsp;Alias&nbsp;"SendMessageA"&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(ByVal&nbsp;hwnd&nbsp;As&nbsp;LongPtr,&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ByVal&nbsp;wMsg&nbsp;As&nbsp;Long,&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ByVal&nbsp;wParam&nbsp;As&nbsp;Long,&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ByRef&nbsp;lParam&nbsp;As&nbsp;Any&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)&nbsp;As&nbsp;LongPtr
&nbsp;&nbsp;&nbsp;&nbsp;Private&nbsp;Declare&nbsp;PtrSafe&nbsp;Function&nbsp;SetTimer&nbsp;Lib&nbsp;"user32"&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(ByVal&nbsp;hwnd&nbsp;As&nbsp;LongPtr,&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ByVal&nbsp;nIDEvent&nbsp;As&nbsp;Long,&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ByVal&nbsp;uElapse&nbsp;As&nbsp;Long,&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ByVal&nbsp;lpTimerFunc&nbsp;As&nbsp;LongPtr)&nbsp;As&nbsp;LongPtr
&nbsp;&nbsp;&nbsp;&nbsp;Private&nbsp;Declare&nbsp;PtrSafe&nbsp;Function&nbsp;KillTimer&nbsp;Lib&nbsp;"user32"&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(ByVal&nbsp;hwnd&nbsp;As&nbsp;LongPtr,&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ByVal&nbsp;nIDEvent&nbsp;As&nbsp;Long)&nbsp;As&nbsp;Long
&nbsp;&nbsp;&nbsp;&nbsp;Private&nbsp;Declare&nbsp;PtrSafe&nbsp;Function&nbsp;GetDlgItem&nbsp;Lib&nbsp;"user32"&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(ByVal&nbsp;hWndDlg&nbsp;As&nbsp;LongPtr,&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ByVal&nbsp;nIDDlgItem&nbsp;As&nbsp;Long&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)&nbsp;As&nbsp;LongPtr
&#35;Else
&nbsp;&nbsp;&nbsp;&nbsp;Private&nbsp;Declare&nbsp;Function&nbsp;FindWindow&nbsp;Lib&nbsp;"user32"&nbsp;Alias&nbsp;"FindWindowA"&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(ByVal&nbsp;lpClassName&nbsp;As&nbsp;String,&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ByVal&nbsp;lpWindowName&nbsp;As&nbsp;String)&nbsp;As&nbsp;Long
&nbsp;&nbsp;&nbsp;&nbsp;Private&nbsp;Declare&nbsp;Function&nbsp;SendMessage&nbsp;Lib&nbsp;"user32"&nbsp;Alias&nbsp;"SendMessageA"&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(ByVal&nbsp;hwnd&nbsp;As&nbsp;Long,&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ByVal&nbsp;wMsg&nbsp;As&nbsp;Long,&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ByVal&nbsp;wParam&nbsp;As&nbsp;Long,&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ByRef&nbsp;lParam&nbsp;As&nbsp;Any&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)&nbsp;As&nbsp;Long
&nbsp;&nbsp;&nbsp;&nbsp;Private&nbsp;Declare&nbsp;Function&nbsp;SetTimer&nbsp;Lib&nbsp;"user32"&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(ByVal&nbsp;hwnd&nbsp;As&nbsp;Long,&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ByVal&nbsp;nIDEvent&nbsp;As&nbsp;Long,&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ByVal&nbsp;uElapse&nbsp;As&nbsp;Long,&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ByVal&nbsp;lpTimerFunc&nbsp;As&nbsp;Long)&nbsp;As&nbsp;Long
&nbsp;&nbsp;&nbsp;&nbsp;Public&nbsp;Declare&nbsp;Function&nbsp;KillTimer&nbsp;Lib&nbsp;"user32"&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(ByVal&nbsp;hwnd&nbsp;As&nbsp;Long,&nbsp;_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ByVal&nbsp;nIDEvent&nbsp;As&nbsp;Long)&nbsp;As&nbsp;Long
&nbsp;&nbsp;&nbsp;&nbsp;Private&nbsp;Declare&nbsp;Function&nbsp;GetDlgItem&nbsp;Lib&nbsp;"user32"&nbsp;_<BR />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(ByVal&nbsp;hWndDlg,&nbsp;ByVal&nbsp;nIDDlgItem&nbsp;As&nbsp;Long)&nbsp;As&nbsp;Long
&#35;End&nbsp;If

Private&nbsp;Enum&nbsp;WINDOW_MESSAGE
    WM_ACTIVATE&nbsp;=&nbsp;6
    WM_SETFOCUS&nbsp;=&nbsp;7
    WM_KILLFOCUS&nbsp;=&nbsp;8
    WM_PAINT&nbsp;=&nbsp;&HF
    WM_CLOSE&nbsp;=&nbsp;&H10
    WM_QUIT&nbsp;=&nbsp;&H12
    WM_COMMAND&nbsp;=&nbsp;&H111
    WM_SYSCOMMAND&nbsp;=&nbsp;&H112
End&nbsp;Enum

'&nbsp;Dialog&nbsp;Box&nbsp;Command&nbsp;IDs&nbsp;-&nbsp;replicates&nbsp;vbMsgBoxResult,&nbsp;with&nbsp;the&nbsp;addition&nbsp;of&nbsp;'dlgTIMEOUT'
Public Enum DIALOGBOX_COMMAND
    dlgTIMEOUT&nbsp;=&nbsp;-1
    dlgOK&nbsp;=&nbsp;1
    dlgCANCEL&nbsp;=&nbsp;2
    dlgABORT&nbsp;=&nbsp;3
    dlgRETRY&nbsp;=&nbsp;4
    dlgIGNORE&nbsp;=&nbsp;5
    dlgYES&nbsp;=&nbsp;6
    dlgNO&nbsp;=&nbsp;7
End Enum

最后一点:我欢迎有经验的MFC C ++开发人员提出改进建议,因为您将更好地掌握“对话”窗口背后的基本Windows消息传递概念 - 我使用的是过于简化的语言,它是可能是我理解中的过度简化在我的解释中突然变成了彻头彻尾的错误。


5
投票

使用答案A. Win32解决方案。这符合要求,并且到目前为止测试非常稳健。

Declare Function MessageBoxTimeout Lib "user32.dll" Alias "MessageBoxTimeoutA" ( _ 
ByVal hwnd As Long, _ 
ByVal lpText As String, _ 
ByVal lpCaption As String, _ 
ByVal uType As Long, _ 
ByVal wLanguageID As Long, _ 
ByVal lngMilliseconds As Long) As Long 

Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" ( _ 
ByVal lpClassName As String, _ 
ByVal lpWindowName As String) As Long 

Public Sub MsgBoxDelay() 
    Const cmsg As String = "Yes or No? leaving this window for 1 min is the same as clicking Yes." 
    Const cTitle As String = "popup window" 
    Dim retval As Long 
    retval = MessageBoxTimeout(FindWindow(vbNullString, Title), cmsg, cTitle, 4, 0, 60000) 

    If retval <> 7 Then 
        Call MethodFoo 
    End If 

End Sub

0
投票

从这篇文章中的示例开始,我的最终代码如下:

' Coded by Clint Smith
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' tMsgBox Function (Timered Message Box)
' By Clint Smith, clintasm@gmail.com
' Created 04-Sep-2014
' This provides an publicly accessible procedure named
' tMsgBox that when invoked instantiates a timered
' message box.  Many constants predefined for easy use.
' There is also a global result variable tMsgBoxResult.
' This was written using undocumented procedure in user32.dll
' due to a buggy WScript.shell result where message window did
' not close after timer expiration.
'
' Defaults to regular information top most message box with ok
' button only.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Public Const mbBTN_Ok = vbOKOnly                       'Default
Public Const mbBTN_OkCancel = vbOKCancel
Public Const mbBTN_AbortRetryIgnore = vbAbortRetryIgnore
Public Const mbBTN_YesNoCancel = vbYesNoCancel
Public Const mbBTN_YesNo = vbYesNo
Public Const mbBTN_RetryCancel = vbRetryCancel
Public Const mbBTN_CanceTryagainContinue = &H6
Public Const mbICON_Stop = vbCritical
Public Const mbICON_Question = vbQuestion
Public Const mbICON_Exclaim = vbExclamation
Public Const mbICON_Info = vbInformation
Public Const mbBTN_2ndDefault = vbDefaultButton2
Public Const mbBTN_3rdDefault = vbDefaultButton3
Public Const mbBTN_4rdDefault = vbDefaultButton4
Public Const mbBOX_Modal = vbSystemModal
Public Const mbBTN_AddHelp = vbMsgBoxHelpButton
Public Const mbTXT_RightJustified = vbMsgBoxRight
Public Const mbWIN_Top = &H40000                        'Default

Public Const mbcTimeOut = 32000
Public Const mbcOk = vbOK
Public Const mbcCancel = vbCancel
Public Const mbcAbort = vbAbort
Public Const mbcRetry = vbRetry
Public Const mbcIgnore = vbIgnore
Public Const mbcYes = vbYes
Public Const mbcNo = vbNo
Public Const mbcTryagain = 10
Public Const mbcContinue = 11

Public Const wAccessWin = "OMain"
Public Const wExcelWin = "XLMAIN"
Public Const wWordWin = "OpusApp"

Public tMsgBoxResult As Long

Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
    (ByVal lpClassName As String, _
    ByVal lpWindowName As String) As Long

Declare Function tMsgBoxA Lib "user32.dll" _
    Alias "MessageBoxTimeoutA" ( _
    ByVal hwnd As Long, _
    ByVal lpText As String, _
    ByVal lpCaption As String, _
    ByVal uType As Long, _
    ByVal wLanguageID As Long, _
    ByVal lngMilliseconds As Long) As Long

Public Sub tMsgBox( _
    Optional sMessage As String = "Default: (10 sec timeout)" & vbLf & "Coded by Clint Smith", _
    Optional sTitle As String = "Message Box with Timer", _
    Optional iTimer As Integer = 10, _
    Optional hNtype As Long = mbBTN_Ok + mbWIN_Top, _
    Optional hLangID As Long = &H0, _
    Optional wParentType As String = vbNullString, _
    Optional wParentName As String = vbNullString)
    AppHWnd = FindWindow(wParentType, wParentName)
    tMsgBoxResult = tMsgBoxA(AppHWnd, sMessage, sTitle, hNtype, hLangID, 1000 * iTimer)
End Sub

0
投票

简单

Call CreateObject("WScript.Shell").Popup("Timed message box", 1, "Title", vbOKOnly)
最新问题
© www.soinside.com 2019 - 2024. All rights reserved.