Robert Berke
asked on
non modal message box API that does not cause vba program to pause (without using a Userform)
My outlook mailEx program runs when Outlook does a send/receive. The program occasionally displays informational messages that I want the user to see. But, I don't want the messages to stop MailEx processing.
I solved this completely with a subroutine that displays a non-modal form. In MailEx I simply code
line33: call msgfastbox("line33","This message will stay on screen")
debug.print "But the program will continue to run"
I want to extend the this idea to Excel and Access, so I wonder if there is an API that does something similar but doesn't require a userform.
I have googled for a while and I and found some web pages that say "NO THERE IS NO SUCH API". So, please, don't point me to a potential solution, unless you are really sure that it will run non-modally.
For instance someone suggested I use "declare function myfunc Lib "User32" Alias "MessageBoxA"". Perhaps I used it wrong but the last line of code at http://www.tek-tips.com/faqs.cfm?fid=4699 WAITS for the user to click OK. I tried variations, but they all waited for user response.
In case you are interested, here is the Outlook code that I am currently using. It does exactly what I want. It displays a non-modal message box then continues executing the main program.
I solved this completely with a subroutine that displays a non-modal form. In MailEx I simply code
line33: call msgfastbox("line33","This message will stay on screen")
debug.print "But the program will continue to run"
I want to extend the this idea to Excel and Access, so I wonder if there is an API that does something similar but doesn't require a userform.
I have googled for a while and I and found some web pages that say "NO THERE IS NO SUCH API". So, please, don't point me to a potential solution, unless you are really sure that it will run non-modally.
For instance someone suggested I use "declare function myfunc Lib "User32" Alias "MessageBoxA"". Perhaps I used it wrong but the last line of code at http://www.tek-tips.com/faqs.cfm?fid=4699 WAITS for the user to click OK. I tried variations, but they all waited for user response.
In case you are interested, here is the Outlook code that I am currently using. It does exactly what I want. It displays a non-modal message box then continues executing the main program.
Sub msgFastBox(id As String, ByVal Text As String, Optional MilliSeconds)
' displays message non-modally for a few seconds.
'
' if no seconds are specified, the box will remain open until it is dismissed
' or until another msgFastBox is requested
Call writelogfile(id, Text)
frmMsgFastBox.Text.MultiLine = True
frmMsgFastBox.Text = Format$(Date, "MM/DD/YYYY") & " " & Format$(time(), "HH:MM:SS") & id & " " & Text
frmMsgFastBox.Show False
DoEvents
If Not IsMissing(MilliSeconds) Then
Sleep MilliSeconds
Unload frmMsgFastBox
End If
End Sub
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Jim, That links needs to be translated to vba before I can understand it
fyed: your solution is virtually identical to the solution I described in my first post. I will give you a few points mainly because you saved me the trouble of translating my solution into access.
fyed: your solution is virtually identical to the solution I described in my first post. I will give you a few points mainly because you saved me the trouble of translating my solution into access.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
The progress bar implementations you folks have posted are equivalent to the userform solution that I previously developed for Outlook.
But, since there is no neatly packaged API, I will give points for those contributions.
By the way, I came up with the following approach which works in in every MS Office environment.
But, since there is no neatly packaged API, I will give points for those contributions.
By the way, I came up with the following approach which works in in every MS Office environment.
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Sub test()
Call modelessMsgbox("ugly but it works")
End Sub
Sub modelessMsgbox(text)
' First create program ModelessMsg.vbs in c:\aaatmp\
' Set objargsinall = WScript.Arguments
' If WScript.Arguments.Count = 0 Then
' MsgBox "ModelessMsg.vbs not called properly: no message passed"
' Else
' WScript.echo objargsinall(0)
' End If
Set wShell = CreateObject("wscript.shell")
wshCommand = "taskkill /IM wscript.EXE /F" ' there must be a way, but this makes sure there is only one such msgbox displaying
wShell.Run wshCommand
Sleep 500
wShell.Run "wscript c:\aaatmp\test.vbs " & Chr(34) & Replace(text, Chr(34), "'") & Chr(34)
End Sub
ASKER
I should point out that my initially posted vba code had an optional interval timer.
If I used a 5 second timer, the message would not continue until the 5 seconds expired even if the user dismissed it.
I don't think the alternatives posted by the experts have that problem, so they are "better" solutions.
If I used a 5 second timer, the message would not continue until the 5 seconds expired even if the user dismissed it.
I don't think the alternatives posted by the experts have that problem, so they are "better" solutions.
ASKER
I improved my previous solution to allow an optional timeout parameter.
Option Explicit
Sub test()
Call modelessMsgbox("ugly but it works", 2)
End Sub
Sub modelessMsgbox(text, Optional timeout As Long = 5)
' Example: Call modelessMsgbox("This informational message does not stop vba".10)
' the message will be displayed for 10 seconds.
' if only 1 parameter is given, the message will display for 5 seconds
'
'
' For details, see: << https://www.experts-exchange.com/questions/27992241/non-modal-message-box-API-that-does-not-cause-vba-program-to-pause-without-using-a-Userform.html >>
' FIRST, Create the following script "c:\efgmdl\modelessMsg.vbs " (drop the leading quote)
' Set objargsinall = WScript.Arguments
' Set objshell = WScript.CreateObject("WScr ipt.Shell" )
' If WScript.Arguments.count = 0 Then
' objshell.popup "ModelessMsg.vbs not called properly: no message passed", 5
' ElseIf WScript.Arguments.count = 1 Then
' objshell.popup "1" & objargsinall(0), 5
' ElseIf WScript.Arguments.count > 1 Then
' objshell.popup objargsinall(0), objargsinall(1)
' End If
Dim wshell As Object
Set wshell = CreateObject("wscript.shel l")
wshell.Run "wscript c:\efgmdl\modelessmsg.vbs " & chr(34) & Replace(text, chr(34), "'") & chr(34) & " " & timeout
End Sub
Option Explicit
Sub test()
Call modelessMsgbox("ugly but it works", 2)
End Sub
Sub modelessMsgbox(text, Optional timeout As Long = 5)
' Example: Call modelessMsgbox("This informational message does not stop vba".10)
' the message will be displayed for 10 seconds.
' if only 1 parameter is given, the message will display for 5 seconds
'
'
' For details, see: << https://www.experts-exchange.com/questions/27992241/non-modal-message-box-API-that-does-not-cause-vba-program-to-pause-without-using-a-Userform.html >>
' FIRST, Create the following script "c:\efgmdl\modelessMsg.vbs
' Set objargsinall = WScript.Arguments
' Set objshell = WScript.CreateObject("WScr
' If WScript.Arguments.count = 0 Then
' objshell.popup "ModelessMsg.vbs not called properly: no message passed", 5
' ElseIf WScript.Arguments.count = 1 Then
' objshell.popup "1" & objargsinall(0), 5
' ElseIf WScript.Arguments.count > 1 Then
' objshell.popup objargsinall(0), objargsinall(1)
' End If
Dim wshell As Object
Set wshell = CreateObject("wscript.shel
wshell.Run "wscript c:\efgmdl\modelessmsg.vbs " & chr(34) & Replace(text, chr(34), "'") & chr(34) & " " & timeout
End Sub
ASKER
I recently created the following code so modelessMsgboxVBS can work in vbscript. (vbscript does not allow optional parameters)
Also, the previous version would only display about 1000 characters of text. This version allows display of any length string by setting the 2nd parameter to -1
To test it, use notepad to create test.vbs and insert the following code
Also create c:\testMdl\modelessMsg.vbs as described on lines 14 to 25
Also, the previous version would only display about 1000 characters of text. This version allows display of any length string by setting the 2nd parameter to -1
To test it, use notepad to create test.vbs and insert the following code
Also create c:\testMdl\modelessMsg.vbs
Sub modelessMsgboxVBS(Text, timeout)
' Example:
' Call modelessMsgbox("This informational message does not stop VBS", 10)
' The text will be displayed for 10 seconds.
'
' Normally Text should be less than 1000 characters, unless the 2nd parameter is -1
'
' if 2nd parameter is 5 the msg will display for 5 seconds
' if 2nd parameter is 0 the msg will display until user clicks OK
' if 2nd parameter is -1 the msg will be displayed with notepad and Text can be of arbitrary length.
'
' For details, see: << https://www.experts-exchange.com/questions/27992241/non-modal-message-box-API-that-does-not-cause-VBS-program-to-pause-without-using-a-Userform.html >>
' FIRST, Create the following script "c:\testMdl\modelessMsg.vbs" (drop the leading quote)
' Set objargsinall = WScript.Arguments
' Set objshell = WScript.CreateObject("WScript.Shell")
' If WScript.Arguments.count = 0 Then
' objshell.popup "ModelessMsg.vbs not called properly: no message passed", 5
' ElseIf WScript.Arguments.count = 1 Then
' objshell.popup "1" & objargsinall(0), 5
' ElseIf WScript.Arguments.count > 1 Then
' objshell.popup objargsinall(0), objargsinall(1)
' End If
Dim wshell, filePath, fileNum
Set wshell = CreateObject("wscript.shell")
If timeout = -1 Then
filePath = "c:\aaatmp\Temporary.txt"
On Error Resume Next
Kill filePath
On Error GoTo 0
Set objFileToWrite = CreateObject("Scripting.FileSystemObject").OpenTextFile(filepath,2,true)
objFileToWrite.WriteLine( "ModelessMsgBox " & Now & vbCrLf & vbCrLf & Text)
objFileToWrite.Close
Set objFileToWrite = Nothing
wshell.Run Chr(34) + filePath + Chr(34)
Else
wshell.Run "wscript c:\testMdl\modelessmsg.vbs " & Chr(34) & Replace(Text, Chr(34), "'") & Chr(34) & " " & timeout
End If
End Sub
Sub test()
Call modelessMsgbox("very long string", -1)
End Sub
call test
http://msdn.microsoft.com/en-us/library/ms644996%28v=VS.85%29.aspx#modeless_box
But really, this is nothing more then creating a message box form on the fly.
I'd keep things simple and just create the forms in Excel/Access to accomplish this.
Jim.