Articles - Dialogs

Using 'Windows' style Dialogs

 

That Doesn't Look Good

The first goal of many OneWorld programmers is generally to create software that is consistent with what the users are accustomed to.  While the functionality is of chief importance we don't want to throw anything at the user that is strange looking, or beyond the Graphical User Interface they see using other software packages.  The obvious effect is confusion.

 

This article is focused on Dialog Boxes.  I'm sure anyone who's designed, or written an interface can imagine a scenario where the software should halt and inform the user of an error, or supply information.  Perhaps the software needs to present a questionable date to the user and ask what to do about it. 

The Tool falls short where dialog boxes are concerned.  In fact, there are only   two methods left to a programmer, either use the Message Box Form, or create a new form that's a Fix/Inspect (or something similar).  If a return values is required then only the second method just mentioned can be used. 

 

Lets Look at the JDE Options:

Below are the two methods JDE's tool set gives us.  First is their Message Form, and second is the Fix/Inspect Form.

 

Here is the Message Box that JDE gives us.  It looks fine from here actually.  It's relatively small and you can see the application that called the message window. 

But, what are it's limitations?  For one thing, it's all hard coded.  All the text is written right onto the form and the programmer has to create an individual window for every conceivable error they want to report with a Message Box.

The upside is that the programmer can ask the user questions and receive a response.   Also, the message can be dynamic, so the programmer needs only one Form that can report any number of messages.

JDEmessage.jpg (27292 bytes)

Now, look at the second method; a new form.

The first thing I notice is that this "Message" isn't in a box.  Most users run OneWorld Applications in a maximized state.  When they do this all forms completely cover up their parents.   A message presented using this technique hides everything behind it.  A tiny message makes the whole thing look ugly.

 

So, what's wrong with that?  The problem is that our little dialog will be a full sized form that will obscure everything behind it.

But, it's still ugly.

HideDialog.jpg (23896 bytes)

 

But, There IS Another Way!:

All of these message boxes will be called by Interactive Applications.  That being the case, we can write code that uses Microsoft's WIN32 API.  JDE does it, and so can you.

If you've written many Applications, or talked to some of the 'old hands' you've probably heard of M & D Debug.  It's a simple application that we can call and pass variables from our programs to so we can see what's in those variables.  Well, did you ever stop to wonder how that thing works?  You call it by invoking a Business Function, not a form interconnect.

Let's take a look:

 

 

Here is M & D Debug as it displays when called from an application.   In the Event Rules you call the MDDebug BSFN.  Pass some variables from the applications and it shows you what's in them. 

You can see that it can be passed 5 strings, 5 Math Numerics, 5 dates, 5 characters, . . and so on.

 

mddebug.jpg (35694 bytes)

 

 

Well, lets take this same idea, but do something new with it. . . .

We're going to use the same WIN32 API call that JDE did, but make something that interacts with our users and solves the Message Box problem above.  I'm sure you see where this is going.

Take a look at what we can do:

We can show a 'Standard' MS Windows dialog box to the users with a simple OK button. . . .

 

Take a good look here.  The programmer can pass the Title, and the Message Text to the dialog.  The beats JDE's Message Box by a long shot!

OKDialog.jpg (24836 bytes)
Or, we can let them pick "Yes", or "No".  The beauty of this dialog is that it actually passes back the users selections. YesNoDialog.jpg (26049 bytes)
Here's the Data Structure . . . . MesStruct.jpg (42571 bytes)
And even the code for this little example. . .

/************************************************************************
* Variable declarations
************************************************************************/
int iNum;
int iOrigLength;
char buffer[31] = {0};
int diff = 0;
int diff1 = 0;

/************************************************************************
* Declare structures
************************************************************************/

/************************************************************************
* Declare pointers
************************************************************************/

/************************************************************************
* Check for NULL pointers
************************************************************************/
if ((lpBhvrCom == (LPBHVRCOM) NULL) ||
(lpVoid == (LPVOID) NULL) ||
(lpDS == (LPDSD5500320A)    NULL))
{
jdeErrorSet (lpBhvrCom, lpVoid, (ID) 0, "4363", (LPVOID) NULL);
return ER_ERROR;
}

/************************************************************************
* Set pointers
************************************************************************/

/************************************************************************
* Main Processing
************************************************************************/
switch (lpDS->MessageType)
{
        // If a '1' is passed, show a regular OK message box.
case '1':

    iOrigLength = strlen(lpDS->MessageText);
    if (iOrigLength < 31)
    {
        memset (buffer, ' ', sizeof (buffer) - 1);
        diff1 = iOrigLength / 2;
        diff = 14 - diff1;

        strncpy(buffer + diff, lpDS->MessageText, iOrigLength);
        strcpy(lpDS->MessageText, buffer);
    }

    iNum = MessageBox( NULL, lpDS->MessageText, lpDS->MessageBoxTitle, MB_OK );
    {
        lpDS->ReturnValue = '0';
    }
    break;

        // If a '2' is passed, show a message box that allows a 'yes', or 'no'

case '2':

    iOrigLength = strlen(lpDS->MessageText);
    if (iOrigLength < 31)
    {
        memset (buffer, ' ', sizeof (buffer) - 1);
        diff1 = iOrigLength / 2;
        diff = 14 - diff1;

        strncpy(buffer + diff, lpDS->MessageText, iOrigLength);
        strcpy(lpDS->MessageText, buffer);
    }

    iNum = MessageBox (NULL, lpDS->MessageText, lpDS->MessageBoxTitle, MB_YESNO);
    {
    if ( iNum == 6)
        lpDS->ReturnValue = '1';
    else
        lpDS->ReturnValue = '0';

    }
    break;
default :
break;
}/* end of case*/

/************************************************************************
* Function Clean Up
************************************************************************/

return (ER_SUCCESS);
}

Now, we saw two styles above, and this code shows you how it's done, but there are many, many more styles supplied by Microsoft.  You can pick from the list here. . . make a dialog with "Abort, Retry, Ignore", or "Retry, Cancel", or "Help".  Just read down the list, there are quite a few options.

 

Take a look to the right.  This was taken from the MSDN Library for the MessageBox API.

 

You can even specify Icons, like the Stop Sign, or Exclamation Point that you've seen in other Windows programs.

 

Value Meaning
MB_ABORTRETRYIGNORE The message box contains three push buttons: Abort, Retry, and Ignore.
MB_CANCELTRYCONTINUE Windows 2000: The message box contains three push buttons: Cancel, Try Again, Continue. Use this message box type instead of MB_ABORTRETRYIGNORE.
MB_HELP Windows 95/98, Windows NT 4.0 and later: Adds a Help button to the message box. When the user clicks the Help button or presses F1, the system sends a WM_HELP message to the owner.
MB_OK The message box contains one push button: OK. This is the default.
MB_OKCANCEL The message box contains two push buttons: OK and Cancel.
MB_RETRYCANCEL The message box contains two push buttons: Retry and Cancel.
MB_YESNO The message box contains two push buttons: Yes and No.
MB_YESNOCANCEL The message box contains three push buttons: Yes, No, and Cancel.

 

In Conclusion:

The MessageBox WIN32 API is powerful.  It's got a lot more features than JDE's Forms and it's very simple to incorporate into a small Buisiness Function.  JDE even relied on it enough to use in one of their own debugging (albeit unsupported) tools.   It lets the programmer pass dynamic messages, titles, returns the users response, and it doesn't obscure the application that invokes it.

The code sample above doesn't call all the variations possible, but a savvy programmer can take this small piece and grow it into a very robust dialog Business Function. 

I hope this has, to some small degree, opened your eyes to some amazing possiblities within the WIN32 API if not just the MessageBox function.

Good Luck!

Oh yes, a special thanks to Mike Kissel who helped write out the code.

 

 

example graphic