---------------------------------------------------------
The Liberty Basic Newsletter - Issue #51 - OCT 99

       1999, Cliff Bros and Alyce Watson
             All Rights Reserved
---------------------------------------------------------
In this issue:

Liberty BASIC Message Boxes
Message Box Tutorial - by Larry Dunham
Borland Message Boxes
---------------------------------------------------------
Liberty BASIC Message Boxes

Liberty BASIC has two built-in message boxes, that are
very easy to use; NOTICE and CONFIRM.

NOTICE is used when you need to give the user a small
amount of information, such as error messages, or
copyright information.

The notice command displays a dialog box containing the
string expression you desire, and an OK button which the 
user activates by clicking with the mouse after the message 
is read. Pressing ENTER also closes the notice dialog box.

The basic form for NOTICE generates a message box
containing an exclamation icon, the text string you
place in the command, and a titlebar caption that
says "Notice."  Here is the format:

    notice "This program (c) Side by Side Software, 1999"

The other form for NOTICE generates a message box that also
contains the exclamation icon and the text string you
place in the command.  Additionally, it contains the 
caption on the titlebar which you specify.  You specify 
a caption by placing it as the first part of the string 
expression, then including the ascii character for a 
carriage return, which is chr$(13) then specifying the 
text string for the actual message.  You must place the 
chr$(13) outside of the double quote marks that enclose 
the caption string and the message string.  This is done 
by concatenating (adding together) the strings using a 
simple plus (+) sign.  Format:

    notice "Error!" + chr$(13) + "Number too large!"

Any additional carriage returns will force carriage
returns (line breaks) into the message itself.  You
might want to do this so that line breaks occur at
logical breaks in the message contents.  For instance:

    notice "Hello!" _
    + chr$(13) + "Side by Side Software" _
    + chr$(13) + "Brosco - brosco@orac.net.au" _
    + chr$(13) + "Alyce - awatson@wctc.net"
    

CONFIRM is used when you need to get a yes/no decision from
the user.  The format for the command includes the text 
string for the message that will be displayed on the dialog
box, then a semicolon (;) and a receiver variable, which
will be filled with the response corresponding to the
button pushed by the user.

    CONFIRM "Do you wish to save your work?"; answer$

The CONFIRM message box contains two buttons, "Yes" and
"No."  If the user clicks on the "Yes" button, the
receiver variable will contain the string "yes"  This button
is also activated if the user presses the ENTER key on the 
keyboard.  If the user clicks on the "No" button, the 
receiver variable will contain the string "no"  You 
cannot change the caption on the titlebar of a CONFIRM
message box.  It will always be "Please Confirm."

Usage:

[quit]
  ' confirm that the user wants to quit:
  CONFIRM "Are you sure you want to QUIT?"; answer$
  if answer$ = "no" then [inputLoop]

  close #main  :   end
---------------------------------------------------------
Although Liberty BASIC Message boxes are easy to use, they
do not allow as many options as Windows message boxes 
created with API calls.  Larry Dunham has written a
comprehensive tutorial on the use of Windows message
boxes.  Thanks Larry, for a great article!  This one 
should be of interest to everybody.
---------------------------------------------------------
-- Message Box Tutorial --
by Larry Dunham - mailto:LDunham509@aol.com
Copyright  1999 Dunham Business Systems

One of the things I strive for in writing Liberty Basic 
programs is to keep the user interface as standard as I 
can, so that the user has as little "figuring out" to do 
as possible.  

Perhaps one of the most common user actions is responding 
to a message box.  You could create new message boxes from 
scratch for each message that the user needs to respond to, 
but Windows already has this feature built into it, so why 
re-invent the wheel?  Using the Windows message box function 
not only saves the programmer a lot of custom coding, it 
gives a more polished, professional look to the user interface.

Calling Windows message boxes from your application requires 
setting just four components:

* Type  (What buttons appear? -- OK, OK/Cancel, Retry/Cancel, etc.)
* Title (What goes in the colored bar at the top of the message box?)
* Message (What does the box tell the user?)
* Icon (Which of the standard message icons should appear?)

When the box appears, the user clicks a button and a 
"RESULT" is returned that tells your program which button 
was clicked.  In turn, the "RESULT" can be tied to 
[branch] labels in your program to perform an action 
corresponding to the user response.

Let us say we want to notify the user that a file has been 
updated successfully.  Here is code we might use:

'*************** BEGIN PROGRAM ******************
'IF YOU WISH TO COPY THIS CODE INTO YOUR PROGRAM, 
'COPY ONLY THE SNIPPET PART -- OTHER LINES ARE 
'INCLUDED SOLELY TO MAKE THIS A COMPLETE EXECUTABLE 
'CODE SAMPLE...

nomainwin
OPEN "My Program" for window as #main

'*************** BEGIN SNIPPET ******************
Open "user" for dll as #user
    h=hwnd(#main)
    wtype =  _MB_ICONASTERISK or _MB_OK
    message$ = "The file has been updated."
    title$ = "Operation Successful"
    sound = _MB_ICONASTERISK
    calldll #user, "MessageBeep", _
        sound as word, _
        result as void
    calldll #user, "Messagebox", _
        h as word, _
        message$ as ptr, _
        title$ as ptr, _
        wtype as word, _
        RESULT as short
    if RESULT=1 then close #user
'****************  END SNIPPET  *****************

close #main
'**************** END PROGRAM *******************



-- SETTING UP THE WINDOW --

In the example above, there is a line that reads:
wtype =  _MB_ICONASTERISK or _MB_OK

This designates a box with the "Information" icon and 
an "OK" button.  There are six different types of message 
boxes that can be called, and four different icons that 
can be used. These are selected by simply inserting the 
proper designation in the "wtype" line, using the format

wtype = <icon type> or <box type>

The icons to choose from are:
_MB_ICONASTERISK (can access same icon with _MB_ICONINFORMATION)
    (lower case "i" )
_MB_ICONEXCLAMATION 
    (exclamation point)
_MB_ICONHAND (can access same icon with_MB_ICONSTOP)
    (stop sign [Win3.1] or circle with X [Win95/98])
_MB_ICONQUESTION 
    (question mark)

The box type designations (describing the buttons to appear) are:
_MB_OK          
_MB_OKCANCEL
_MB_YESNO
_MB_YESNOCANCEL
_MB_RETRYCANCEL
_MB_ABORTRETRYIGNORE


-- SOUNDING OFF --

The sound played as the message box appears is also selectable. 
In your Windows Control Panel, sounds (.wav files) can be 
designated to play in the event of certain occurences.  The 
message box routine can access five different Windows-defined 
sounds, and selects the sound with the line:

sound = <sound type>

The choices are:
sound = _MB_ICONASTERISK  (Plays .wav file for Windows Asterisk event)
sound = _MB_ICONEXCLAMATION  (Plays .wav file for Windows Exclamation event)
sound = _MB_ICONQUESTION  (Plays .wav file for Windows Question event)
sound = _MB_ICONHAND  (Plays .wav file for Windows Critical Stop event)
sound = _MB_OK  (Plays .wav file for Windows default sound)

Typically you would select the sound matching the icon you 
chose in the wtype line, but for a simple OK box you might 
choose _MB_OK.

In the above example, "h" is set equal to the handle of the 
window or dialog box controlling the action.  If you opened 
the window as #main, then hwnd(#main) is the Windows internal 
designation for that window.  Likewise, if you opened the 
window or dialog box as #comm, then you would set h equal 
to hwnd(#comm).  When calling a message box from a dialog 
box, use the handle of the dialog box in the hwnd() 
parameter--do not use the handle of a control contained 
in that dialog box.

The string "message$" contains the main text of the message 
box, while  "title$" contains the words that are to appear 
in the message box's title bar.


-- GETTING RESULTS --

OK--you've commanded Windows to create your message box, it 
sat on the screen, big as life, and the user clicked a 
button--now what?  Once a button was clicked, the variable 
"RESULT" was invested with a value indicating which 
button was clicked.  The possible values held by RESULT 
are below:

If OK was clicked,  RESULT will always equal 1
If Cancel was clicked,  RESULT will always equal 2
If Abort was clicked,   RESULT will always equal 3
If Retry was clicked,   RESULT will always equal 4
If Ignore was clicked,  RESULT will always equal 5
If Yes was clicked,     RESULT will always equal 6
If No was clicked,  RESULT will always equal 7

From there it becomes a simple matter to direct the program 
flow to a branch label based on the value of RESULT. The 
last line of the snippet above is:

if RESULT=1 then close #user

This message handler can be used for directing program 
flow with a simple addendum, like so:
if RESULT=1 then close #user : goto [branchlabel]

Let's say we have tax program with a YES/NO/CANCEL routine 
that says "Calculating Federal Tax....Calculate State Tax 
also?"  The message handlers could read:

if RESULT=6 then close #user : phrase$="Fed / State taxes.": goto [showresult]
if RESULT=7 then close #user : phrase$="Federal taxes only.": goto [showresult]
if RESULT=2 then close #user : phrase$="Calculation Cancelled.": goto [showresult]

A complete routine might be:

'*************** BEGIN PROGRAM ******************
'IF YOU WISH TO COPY THIS CODE INTO YOUR PROGRAM, 
'COPY ONLY THE SNIPPET PART -- OTHER LINES ARE 
'INCLUDED SOLELY TO MAKE THIS A COMPLETE EXECUTABLE 
'CODE SAMPLE...

nomainwin
OPEN "My Program" for window as #main

'*************** BEGIN SNIPPET ******************
Open "user" for dll as #user
    h=hwnd(#main)
    wtype =  _MB_ICONQUESTION or _MB_YESNOCANCEL
    message$ = "Calculating Federal Tax....Calculate State Tax also?"
    title$ = "Tax Calculation"
    sound = _MB_ICONQUESTION
    calldll #user, "MessageBeep", _
        sound as word, _
        result as void
    calldll #user, "Messagebox", _
        h as word, _
        message$ as ptr, _
        title$ as ptr, _
        wtype as word, _
        RESULT as short
if RESULT=6 then close #user : phrase$="Fed / State taxes.": goto [showresult]
if RESULT=7 then close #user : phrase$="Federal taxes only.": goto [showresult]
if RESULT=2 then close #user : phrase$="Calculation Cancelled.": goto 
[showresult]
'****************  END SNIPPET  *****************

[showresult]
Open "user" for dll as #user
    h=hwnd(#main)
    wtype =  _MB_ICONASTERISK or _MB_OK
    message$ = phrase$
    title$ = "Result"
    sound = _MB_OK
    calldll #user, "MessageBeep", _
        sound as word, _
        result as void
    calldll #user, "Messagebox", _
        h as word, _
        message$ as ptr, _
        title$ as ptr, _
        wtype as word, _
        RESULT as short
    if RESULT=1 then close #user

close #main
end

'**************** END PROGRAM *******************


---  A LA MODAL ---

Here's another little tidbit that might come in handy sometime.  
Windows message boxes have one of three possible modal states.  
A modal message (or dialog) box is one that requires the box 
be acknowledged before continuing; it disables something until 
you do.  By default, Windows message boxes are Application 
Modal--that is, you can switch to other Windows programs or open 
new ones, but you cannot continue in the application which 
called the message box until you click one of the buttons.  

A message box can also be Task Modal, which is just like 
Application Modal in that it does not affect other Windows 
programs, it only disables access to the calling function.  
The Task Modal box, however, can be used without a window 
handle to attach it to.  That is, it can be called from 
applications or libraries which do not themselves have 
window handles, and thus the hwnd parameter is NULL.
(editor's note:  NULL is passed as 0 in Liberty BASIC
API calls.)

The third modal state is System Modal.  A message box so 
defined actually suspends access to ALL Windows functions 
until the box is acknowledged.  When a System Modal message 
box appears, you won't be able to switch to another 
application, minimize or resize a window, or even access 
the Win 95 start button.  For this reason, System Modal 
message boxes should be reserved for urgent error messages 
affecting the integrity of the system, like running out 
of memory.

Defining them is simple.  If you want a message box to be 
Application Modal, do nothing except call the message 
box as demonstrated above.  The other two types are 
created by "OR-ing" the parameter with the "wtype" line 
in the DLL call, like so:

wtype =  _MB_ICONASTERISK or _MB_OK or _MB_SYSTEMMODAL

The modal state parameters are:
_MB_APPLMODAL (If you feel you must define it--it's the default anyway)
_MB_TASKMODAL
_MB_SYSTEMMODAL

Calling the _MB_SYSTEMMODAL parameter with a _MB_ICONHAND 
type box is a last-resort usage since Windows will always 
force such a message box to be displayed, no matter how low 
memory resources are.  The message and title strings for 
these special message boxes should be hard-coded, and not 
reside in a resource file, since the attempt to load them may 
fail if system resources are low.  Also, the message text will 
be limited to three lines, and will not wordwrap, so you will 
need to insert carriage returns in the message string where 
line breaks are desired.
(editor's note:  Liberty BASIC does not make use of
resource files.)


-- HOT BUTTONS --

Finally, there's a little matter of default buttons.  The 
default button in a message box is the one that "presses 
itself" when you press the <ENTER> key.  You'll recognize 
it visually by a dotted line around the button label.  
Unless otherwise defined, The first button in a box is 
always the default.  In a YES/NO box, it's the YES button
--in ABORT/RETRY/IGNORE, it's the ABORT button.

It may be however, that the function of the message box 
makes the first button undesirable as a default, in case 
<Enter> was inadvertantly pressed.  (Consider a message box 
reading "Are you certain you wish to format your hard 
drive?"  Would you want "Yes" to execute if you accidently 
bumped the <Enter> key?)

To set a default button, the parameters are:
_MB_DEFBUTTON1 (First button - Default setting if no parameter specified)
_MB_DEFBUTTON2 (Second button)
_MB_DEFBUTTON3 (Third button)

just "OR" the parameter on the "wtype", as in:

wtype =  _MB_ICONQUESTION or _MB_YESNOCANCEL or _MB_DEFBUTTON2
(Sets second button as default)

In any message box containing a Cancel button, the <Esc> 
key always executes the Cancel function, no matter which 
button is set as the default.

In coding these boxes, rather than having umpteen message 
box calls, you may wish to set each of the different box 
types you plan to use as subroutines, and call them as you 
need them, just changing the title and message text 
strings before calling them.  

Hopefully, this little introduction to Windows message boxes 
will help you add a more professional touch to your user 
interfaces--have fun!

Larry Dunham
Dunham Business Systems
---------------------------------------------------------
---------------------------------------------------------
Borland Message Boxes

Borland has a message box that we may use, just as we may
use the Windows message boxes.  Most systems already have
a copy of the Borland DLL that accomplishes this.  We will
include it with the newsletter for those who do not have
it.  Place it in the same directory as the program that will 
utilize it, or place it in your Windows\System directory.
It functions exactly as the Windows message boxes 
that Larry has described.  It has a different look, and
that is the only reason to use the Borland DLL message
boxes.  They are more colorful.

    open "Test" for window as #main
    h=hwnd(#main)
    wtype =  _MB_ICONEXCLAMATION  or _MB_YESNOCANCEL or _MB_DEFBUTTON2 
    message$ = "This looks different!"
    title$ = "A Borland Message Box"

    playwave "augah.wav", async   

    open "bwcc.dll" for dll as #bwcc
    calldll #bwcc, "bwccMessageBox", _
        h as word, _
        message$ as ptr, _
        title$ as ptr, _
        wtype as word, _
        RESULT as short
    close #bwcc
    close #main

The RESULT codes are the same as the Windows message box
results, as listed above.  You must still use the
Windows MessageBeep function to play a sound.  You may
instead play a wav that you have included with your program
files.  Play it asynchronously, so that the message box
will appear immediately.  A wav played synchronously will
halt program execution until it if finished.  Augah.wav
is also included in the attached ZIP file.
---------------------------------------------------------
Newsletter compiled and edited by: Brosco and Alyce.
Comments, requests or corrections: Hit 'REPLY' now!
mailto:brosco@orac.net.au or mailto:awatson@mail.wctc.net
---------------------------------------------------------