MapbasicMapInfo

Better Dialogs in MapBasic

Any easy way to add some extra polish to MapBasic applications is to switch from using the MapBasic Note and Ask commands to standard Windows message boxes. While the Note command is handy for quickly giving feedback to a user, there’s zero options for customising the dialogs.

Standard MapBasic “Note” dialog – limited to an exclamation icon and “MapInfo” title bar

Let’s see what we can do about that. We’ll start by including a reference to the standard Windows dialog, which is included in the User32.dll library. I also use two tiny wrapper sub/functions (called MessageBox and MsgBox respectively). The function is used for dialogs which need to return a response (a replacement for the Ask function), and the sub for when the response isn’t important (replacement for Note). Lastly, there’s also a bunch of DEFINEs to make calling the routines more convenient and memorable.

Declare Function MsgBoxA Lib "User32.dll" Alias "MessageBoxA" (ByVal hWnd As Integer, ByVal sTxt As String, ByVal sCaption As String, ByVal iTyp As Integer) As Integer
Declare Function MsgBox(ByVal sTxt As String, ByVal sCaption As String, ByVal iType As Integer) As Integer
Declare Sub MessageBox(ByVal sTxt As String, ByVal sCaption As String, ByVal iType As Integer)
' Messagebox dialog buttons
DEFINE vbOKOnly 0
DEFINE vbOKCancel 1
DEFINE vbAbortRetryIgnore 2
DEFINE vbYesNoCancel 3
DEFINE vbYesNo 4
DEFINE vbRetryCancel 5
' Messagebox dialog icons
DEFINE vbCritical 16
DEFINE vbQuestion 32
DEFINE vbExclamation 48
DEFINE vbInformation 64
' Messagebox default button
DEFINE vbDefaultButton1 0
DEFINE vbDefaultButton2 256
DEFINE vbDefaultButton3 512
DEFINE vbDefaultButton4 768
' MsgBox Returned value
DEFINE vbOK 1
DEFINE vbCancel 2
DEFINE vbAbort 3
DEFINE vbRetry 4
DEFINE vbIgnore 5
DEFINE vbYes 6
DEFINE vbNo 7
'**************************************************************************
' Wrapper for standard Win32 Msgbox function
'**************************************************************************
Function MsgBox(ByVal sTxt As String, ByVal sCaption As String, ByVal iType As Integer) As Integer
 MsgBox = MsgBoxA(WindowInfo(WIN_MAPINFO, WIN_INFO_WND), sTxt, sCaption, iType)
End Function
'**************************************************************************
' Messagebox which doesn't return a value
'**************************************************************************
Sub MessageBox(ByVal sTxt As String, ByVal sCaption As String, ByVal iType As Integer)
 Dim i As Integer
 i = MsgBoxA(WindowInfo(WIN_MAPINFO, WIN_INFO_WND), sTxt, sCaption, iType)
End Sub

Now that we’re all setup, we can duplicate the standard MapInfo message box with the call:

Call MessageBox("Standard Windows message box", "My MapBasic Program", vbExclamation)
Message box with customised title

As seen above, MessageBox is called by passing the text of the dialog, a title caption, and one or more options. In this case we’ve used vbExclamation to copy the appearance of the Note command. Nothing too special yet, but let’s explore a little further. In some cases (such as notifying the user when an operation has successfully completed) the exclamation icon just looks wrong. Compare:

Sometimes the exclamation icon isn’t the best choice…

To the dialog created by the code

Call MessageBox("Processing Complete!", "Friendlier Dialog", vbInformation)
Much friendlier!

Let’s take the other extreme, when you need to let the user know that something really bad happened:

Call MessageBox("Something really bad happened..!", "Error", vbCritical)
Guaranteed to get attention!

The other way to use the Message Box is through the MsgBox function. This can be used to ask the user for a response, in a similar way to MapBasic’s Ask function. The big difference is that MapBasic’s Ask dialog causes your eyes to bleed:

MapBasic’s Ask dialog… what’s with all the empty space?

Let’s replace this with a standard Windows message box:

iResponse = MsgBox("Would you like to continue?", "Messagebox with two buttons", vbYesNo + vbQuestion + vbDefaultButton1)
If iResponse = vbYes Then
  ' User clicked yes
ElseIf iResponse = vbNo Then
  ' User clicked no
End If

The code above demonstrates how dialog attributes can be combined:

vbYesNo + vbQuestion + vbDefaultButton1

and how the value returned by the dialog can be checked against the vbYes and vbNo constants to determine the user’s response. Chaining options together allows for very flexible, user-friendly dialogs.  Again, the result looks much nicer (and more professional) then the built-in MapBasic function:

Using a Message Box to ask a question

So there you go! A simple little change you can make to your MapBasic programs to make them just a bit more user-friendly.

Leave a Reply

Your email address will not be published. Required fields are marked *