Using a timeout parameter with a Visual FoxPro message box

Applying a timeout to VFP's MESSAGEBOX() function could cause more problems than it's worth.

By Mike Lewis

In Visual FoxPro version 7.0, Microsoft added a timeout parameter to the MESSAGEBOX() function. By passing a positive integer as the fourth parameter, you stipulate that the message box will automatically close after that number of milliseconds.

Sounds straightforward, doesn't it? Unfortunately, using a timeout parameter with the MESSAGEBOX() function gives rise to a number of problems.

The message box has its own taskbar button

This might not be obvious at first, but when you call MESSAGEBOX() with a timeout parameter, the message box opens with a separate button on the Windows taskbar (Figure 1). If the user then clicks anywhere else in your application, the application window will come to the front, hiding the message box. But the message box is still active at this point, and the application is still in a modal state.

Figure 1

Figure 1: Note the additional taskbar button.

If the user wasn't paying attention when this happened, chances are they'll think the app has frozen. Even if they see the new taskbar button, they're likely to be confused about why it's there - especially as the behavior is completely non-typical of Windows applications.

Make is system modal?

One possible workaround would be to make the message box system modal. You do that by adding 4096 to the value in the second parameter. In fact, doing that doesn't really make the box system modal in the usual sense of the term. It simply forces it to appear on top of all other windows. It doesn't prevent you interacting with other applications, but it does mean that the message will always be at the front of the screen, even if your Visual FoxPro app is minimized.

This workaround avoids the possibility of the user not seeing the message and thinking that your application is hanging. But forcing a message to the front in this way is not exactly polite behavior. You might feel differently, but I wouldn't want my applications to do it unless absolutely necessary.

Timer issues

Here's another problem. When a message box with a timeout is active, any timers in your application will fail to fire.

To demonstrate, consider this code:

LOCAL loTimer
loTimer = CREATEOBJECT("MyTimer")
loTimer.Interval = 1000

MESSAGEBOX("Hello world", 0, "Test", 0)

DEFINE CLASS MyTimer AS Timer 
  FUNCTION Timer
    ACTIVATE SCREEN 
    ? "Timer fired"
ENDDEFINE 

When you run this code, a normal message box will appear. Because the fourth parameter to MESSAGEBOX() is zero, there will be no timeout in force. As long as you leave the box open, the timer object will write a message to the background screen every second. This is what you would expect.

Now, change that fourth parameter to 10000. There is now a ten-second timeout in force. You'll see that the timer object no longer writes anything to the background screen - neither during the ten seconds that the message box is open nor when it eventually closes.

I don't know whether this is a bug or a feature, but it's certainly not what you would expect. It could cause all kinds of unwanted effects in an application that relies heavily on timers.

Poor UI

But my most serious reservation is that a message box with a timeout is simply a poor user interface. Think about it. You give the user some information to read. But then you suddenly remove that information, without warning and for no obvious reason. What if the user was part way through reading the message when it disappeared? Or if they saw the message but didn't have time to even start reading it? It's not exactly going to inspire confidence.

For all these reasons, I would be very cautious about passing that fourth parameter to the MESSAGEBOX() function. If you absolutely must apply a timeout to your messages, consider creating your own message box form. It wouldn't necessarily solve the user interface issue, but at least it wouldn't suffer from the other problems highlighted here.

December 2011

Please note: The information given on this site has been carefully checked and is believed to be correct, but no legal liability can be accepted for its use. Do not use code, components or techniques unless you are satisfied that they will work correctly with your sites or applications.

If you found this article useful, please tell your friends: