---------------------------------------------------------
The Liberty Basic Newsletter - Issue #42 - JUN 99
"Knowledge is a gift we receive from others."
		- Michael T. Rankin
---------------------------------------------------------
In this issue:

1.  Programmer's Spotlight on Doyle Whisenant.
2.  Doyle Whisenant, in his own words.
3.  Practical Uses for API's in Liberty BASIC
	by Doyle Whisenant

Thanks, Doyle.  This is a terrific, helpful article!

Contact Doyle:
mailto:mechanic@sonet.net

In future issues:

Binary Searches - Part 2, by Ian Davies
Gui Design
Menus
---------------------------------------------------------
Programmer's Spotlight on Doyle Whisenant

If you have read the LB message boards or mailing lists,
then you are already acquainted with Doyle.  He's the one
who is always willing to help out, answer questions, and
make interesting comments.  He's also the one who ALWAYS
says, "Thanks!"  Brosco and Alyce want to take this 
opportunity to say to Doyle, "THANK YOU ! ! ! !"

If you have surfed around the LB websites, then you also 
know Doyle as "The API Guy."  His website, MeKanixx
Designs, has all of the API calls that have been
translated into LB, with explanations and sample
programs.  There are plenty of other goodies there, too,
(including Doyle's update to FreeForm) so drop by soon at:

http://mechanic.webjump.com
---------------------------------------------------------
Doyle Whisenant in his own words:

I have been married for 23 years and have 3 wonderful girls. 
Two are married and the youngest is almost out of school. 
My main interests are electronics and programming. I have 
been interested in programming of some type for 20+ years. 
In obtaining an Associates Degree in Electronics, I learned 
some machine programming on Motorola's microcontroller  uc6809 
(anyone remember the Heath Hero robots?) and some ladder 
logic as used on Allan Bradley and GE  PLC's (Programmable 
Logic Controllers, a type of industrial computer). I had a 
little assembly programming thrown in for good measure.

I started programming in Basic 15-20 years ago. I have 
programmed basic in the following dialects:  TI99-4A , 
Commodore 64, Commodore Vic 20,  Timex Sinclair,  
IBM (Basica),  GwBasic, Qbasic,  and now Liberty Basic. 
Of all of these different basic's, Liberty Basic has got 
to be my favorite. Carl Gundel has done a wonderful job 
making Liberty Basic so easy and fun to use.
---------------------------------------------------------
Practical uses for API's in Liberty Basic
	by Doyle Whisenant, (c)1999

Carl Gundel did a wonderful job when he created Liberty 
Basic. If you have a chance, look at a Windows program 
written in C; hundreds, sometimes thousands, of lines of 
code to do even the simplest functions which are a snap 
in Liberty Basic. Liberty Basic hides most of these lines 
of code from the programmer by handling the gory details 
for you. Even so, sometimes the programmer needs to use 
an API function that is not included in Liberty Basic. 
Carl has made it possible to call almost all of the API 
functions which Windows provides for your use.

Example #1: GetVersion

When writing an application in Liberty Basic, the programmer 
doesn't know if the user is running Windows 3.1/3.11 or 
Windows 95/98. For most applications this is unimportant. 
It makes no difference in how the program runs for the user. 
Sometimes though, the program uses API or DLL calls which 
only function correctly on a 32 bit system. In a professional 
program it would be better for the programmer to check for 
the version of Windows that is on the user's computer and 
write the program accordingly.

For instance if the user is running Windows 3.1, textbox 
height minimum is 24 pixels. If the programmer creates 
a GUI (Graphical User Interface) that has a smaller textbox 
height for aesthetic reasons and uses a height smaller than 
24 pixels, it won't run under Windows 3.1. I have seen this 
several times in programs written by people on the mailing 
lists. Sometimes I have downloaded a *.tkn file in which  
the programmer has used a height of less than 24 pixels 
for the textbox height. Some great programs I'm sure - but 
users running Windows 3.1 will not be able to use them. 

How do I write a program and still make sure that both 
Windows 3.1 and Windows 95/98 users can run the program 
without problems? Consider the following code:

    'top of  program
    open "Kernel.dll" for dll as #Kernel
        calldll #Kernel,  "GetVersion", result as long
    close #Kernel

    'calculate the version of Windows running on the users system
    ver = result and hexdec("&HFFFF")
    Lowbyte$ = Str$(ver And hexdec("&HFF"))
    Highbyte$ = Trim$(Str$((ver And hexdec("&HFF00")) / 256))
    win.version$ = Lowbyte$ + "." + Highbyte$ 


    if val(win.version$) > 3.1 then 
        gosub [doWin95Setup]
    else
        gosub [doWin31Setup]
    end if
'the rest of the program code goes here
  
open "My Wonderful Program" for graphics as #1
 etc., etc,

Later in the program:

   [doWin95Setup]
       'do GUI setup for Win95/98 here
   TEXTBOX #main.tb, xpos, ypos, 100, 20
       'other Win95 specific control code here
     return

   [doWin31Setup]
      'do GUI setup for Win31 here
   TEXTBOX #main.tb, xpos, ypos, 100, 24
      'other Win31 specific code here 
    return

Of course this means more work for the programmer, doing 
two different GUI designs is not going to be easy but 
this would be a more professional program. This is only 
one example of how you can cater to the users and their 
version of Windows. I'm sure that you can think of many 
more occasions where knowing the  Windows version can 
improve your code.

If the programmer wants to really make sure his or her 
program will run for everyone, then he/she should consider 
doing something like the following at the start of the program:

   dw = DisplayWidth 
   dh = DisplayHeight

if dw > 640 and dh > 480 then goto [checkFor800] '800x600 or larger
   'do 640x480 display setup
   'set up different fonts, etc
    goto [start]
end if

[checkFor800]
if dw > 800 and dh > 600 then  'must be larger so do 1024x768   
    'do 1024x768 display setup
else                           'nope got to be 800x600
    'do 800x600 display setup
end if

[start]                       
               



Example #2: SetWindowText

This call uses the SetWindowText API call to change the 
titlebar of your window to reflect the file name, add your 
program version info, etc. Liberty Basic now has the new 
command - TitleBar - which will do the same thing but it 
only works for the main window. If you want to change the 
caption on any other window type you must use this call to 
do so. Thanks to Tom Record because his code is where I 
picked up this little gem.

Please note that the "GetParent" handle is required only 
for graphic and text windows. The call won't work  for 
dialog and window type windows. For the latter two window 
types, use the normal hwnd (hg below) handle for the call to work.

open "" for graphics as #graphics 
'use GetParent for win handle for graphics, text types
 hg = hwnd(#graphics)
 open "USER" for dll as #user
     CallDLL #user, "GetParent", _
        hg AS word, _     'handle of graphics window
        hParent AS word   'return is handle of Parent window

 calldll #user, "SetWindowText", _
         hParent as word, _         'use Parent window handle here only for graphics, text types
         "Title was changed!" as ptr, _ 'use normal window handle for dialog, window types
         result as void
 close #user



Example #3: GetModuleHandle

Have you ever wanted to run another program such as notepad 
using code from your Liberty Basic application? This is easy, 
just use "run notepad.exe". You probably need to know when 
the user has finished using notepad in order for your program 
to continue. How do you accomplish this?

Well the designers of the Windows API thought of this and 
included the call "GetModuleHandle".  Note how easy it is to 
tell if notepad is running. Of course you may have to supply 
the full path to the application that is being checked.

'result=0 when the file is closed
'result>0 when the file is open

open "kernel.dll" for dll as #kernel

calldll #kernel, "GetModuleHandle", _
"notepad.exe" as ptr, _
result as short

close #kernel
If result=0 then print "File is not open"
if result>0 then print "File is open already!"


Example #4: ShellExecute

What do you do when you want to run a file on the user's 
computer but you don't have the faintest clue of the path 
to the user's application? Also, maybe the user has a different 
program to use for that particular file type. Since there are 
literally dozens of applications that can run the same file 
types, how do you know what application the user has associated 
with the file type you want to run?

The following call takes care of opening your file on the user's 
system no matter what application the user has associated with 
the particular file type. An example is shown below that uses a 
bmp file opened in the user's associated application. 


lpszOp$ = "open" + chr$(0)          'Open or Print
lpszFile$ = "carl.bmp" + chr$(0)    'file name
lpszParams$="" + chr$(0)            'used only for *.exe type files
lpszDir$ = "c:\lb14w\" + chr$(0)    'your application file folder

open "shell" for dll as #shell
  calldll #shell, "ShellExecute", _
    hDeskTop as word, _       ' the hwnd of the parent form.
    lpszOp$ as ptr,_          ' open or print
    lpszFile$ as ptr,_        ' file to open or print
    lpszParams$ as ptr, _     ' no parameters
    lpszDir$ as ptr, _        ' default directory
    _SW_SHOWNORMAL as short, _  ' API parameters i.e. _SW_SHOWNORMAL,
    result as word              ' _SW_HIDE or _SW_SHOWMINNOACTIVE etc
    close #shell
 
Below is a list of the values that you can specify in the 
Shellexecute call above. They are listed in the correct 
liberty Basic format. 


Value			Meaning

_SW_HIDE	Hides the window and activates another window.

_SW_MAXIMIZE	Maximizes the specified window.

_SW_MINIMIZE	Minimizes the specified window and activates 
the next top-level window in the Z order.

_SW_RESTORE	Activates and displays the window. If the 
window is minimized or maximized, Windows restores it to 
its original size and position. An application should specify 
this flag when restoring a minimized window.

_SW_SHOW	Activates the window and displays it in its 
current size and position. 

_SW_SHOWDEFAULT	Sets the show state based on the SW_ flag 
specified in the STARTUPINFO structure passed to the 
CreateProcess function by the program that started the 
application. An application should call ShowWindow with
this flag to set the initial show state of its main window.

_SW_SHOWMAXIMIZED	Activates the window and displays 
it as a maximized window.

_SW_SHOWMINIMIZED	Activates the window and displays 
it as a minimized window.

_SW_SHOWMINNOACTIVE	Displays the window as a minimized window. 
The active window remains active.

_SW_SHOWNA	Displays the window in its current state. The 
active window remains active.

_SW_SHOWNOACTIVATE	Displays a window in its most recent 
size and position. The active window remains active.

_SW_SHOWNORMAL	Activates and displays a window. If the window 
is minimized or maximized, Windows restores it to its original 
size and position. An application should specify this flag 
when displaying the window for the first time.


Well that's about all for now. What other API calls would 
you like to see in the newsletter? I certainly am not the 
best qualified to write about this subject but if there is 
enough interest, I might be persuaded to give it a try. 
Thanks for reading!

---------------------------------------------------------
 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
---------------------------------------------------------