---------------------------------------------------------
The Liberty Basic Newsletter - Issue #55 - NOV 99
             1999, Alyce Watson
             All Rights Reserved
---------------------------------------------------------
In this issue:

1 - Request
2 - A real Windows status bar!
3 - A multi-part status bar!
4 - An interesting status bar demo.
---------------------------------------------------------
1 - REQUEST

I am soliciting contributions for newsletter articles.
Some possible subjects follow, but articles of any
kind that deal with programming are welcome.  Please
send submissions to me at 

mailto:awatson@wctc.net

Submissions become the property of the LB Newsletter.
Not all submissions may be published.  Submissions may
be edited for publication.

Ideas:

text commands & string manipulation 
using mmsystem.dll
benchmarking and timing methods
theory of debugging 
dates & calendars
using the resizehandler
math functions 
programming tools - setting flags, ini files
conditional statements/boolean expressions
Programmer's Spotlight
Use of a specific GUI designer, such as E-Pro
Use of an add-on DLL
accessing directories/drives
INPUT and OPEN commands
Web sources for programmers
Book reviews of programming books
How to convert code from another language to LB
Legal issues for shareware authors
Algorithms
Using the runtime engine

Thank you,
Alyce Watson
---------------------------------------------------------
2 - A REAL WINDOWS STATUS BAR!

Recently, Brent Thorn shared an example that created a
real Windows status bar.  Thanks, Brent!  I have added
to that routine, but please credit Brent (lbgui) if you
use these methods in your code.

Contact Brent Thorn
mailto:lbgui@aol.com

Also, special thanks to John Worthington for supplying
the values for the status bar constants.

You may create a status bar with this method on Win95 and
Win98.  You may also do this on later versions of Win3.1.
To use Win3.1, you must have Win32s on your system.  If
you are not sure whether you have Win32s, do a search of
your Windows directories.


Steps to create a simple status bar:

1)  Get the handle of the program window with LB's 
    HWND function.
    hwnd = hwnd(#1)

2)  Open commctrl.dll and user.dll
    open "commctrl.dll" for dll as #cctl
    open "user" for dll as #user

3)  Initialize the commctrl.dll
    calldll #cctl, "InitCommonControls", re as void

4)  Set up style variables.  These are Windows constants
    that are put together with OR.  In this case, the
    minimum needed is:
    style = _WS_VISIBLE or _WS_CHILD 

5)  Make a null terminated string that contains the text
    that appears on the status bar at start-up:
    text$ = "I'm a real status bar!" + chr$(0)

6)  Assign an ID number to the status bar.  This number
    is not used in Liberty BASIC, but must be part of
    the API function call:
    id = 1   

7)  Make the API call that creates the status bar.  If
    successful, the function returns the status bar handle:

    calldll #cctl, "CreateStatusWindow", _
    style as long, _
    text$ as ptr, _
    hwnd as word, _
    id as word, _
    stat.hwnd as word

8)  Set up a routine that allows the status bar to resize
    itself when the window is resized by a user.  This is
    done by sending a windows message to the status bar.
    The message to send is _WM_SIZE.  The word parameter
    in this case is 0.  The long parameter contains the
    desired new width in its loword, and the desired new
    height in its hiword.  We do not need to tell the
    status bar what height it should be, so that part
    of the long parameter is 0.  The width should be
    equal to the WindowWidth, so that is all the long
    parameter should contain.

    calldll #user, "SendMessage", _
    stat.hwnd as word, _
    _WM_SIZE as word, _
    0 as word, _
    WindowWidth as long, _
    re as long


Steps to change the status text:

1)  This requires that a Windows message be sent.
    You must have the handle of the status bar as
    the first parameter.  The second parameter is
    the value for the Windows constant SB_SETTEXT.
    This value is not set within Liberty BASIC, so
    it must be passed into the call as 1025.
    The word parameter is 0.  The long parameter
    contains a pointer to the address of the null
    terminated string containing the new status
    bar caption.  In Liberty BASIC, the syntax is:

    text$ = "Changed!" + chr$(0)

    calldll #user,  "SendMessage", _
    stat.hwnd as word, _
    1025 as word, _
    0 as word, _
    text$ as ptr, _
    r as dword

And now, here is some sample code that uses this method:
---------------------------------------------------------
' Original Code for Status Bar by Brent Thorn:
' lbgui@aol.com
'
' This is a simple example that creates a
' status bar and demonstrates how to
' change the text it contains.
'

nomainwin
' Open DLLs
open "commctrl.dll" for dll as #cctl
open "user" for dll as #user


' Open window
WindowWidth=200:WindowHeight=150
button #1.b, "Change Status Text",[change],UL,10,50
open "Status Bar Test" for window as #1


' Set up events
print #1, "trapclose [quit]"
print #1, "resizehandler [size]"


' Get window handles
hwnd = hwnd(#1)


' Init common controls
calldll #cctl, "InitCommonControls", _
re as void


' Flags for status window creation -
' these are the minimum:
style = _WS_VISIBLE or _WS_CHILD


' Text to appear on status bar -
' must be null terminated
text$ = "I'm a real status bar!" + chr$(0)


' Windows and controls created via API
' must be assigned an ID number
' which is not used in LB.
id = 1


' create status bar
' output style, text$, hwnd, id
' input stat.hwnd

GOSUB [create.status.bar]

' the status bar handle is now = stat.hwnd



[loop]
input a$ ' Wait for events


[create.status.bar]
' input style, text$, hwnd, id
' output stat.hwnd

calldll #cctl, "CreateStatusWindow", _
style as long, _
text$ as ptr, _
hwnd as word, _
id as word, _
stat.hwnd as word

RETURN


[change]'put new text on status bar
' input text$, stat.hwnd
' output: none
' 1025 is the constant value to change status bar text

IF text$ = "Changed!" + chr$(0) then
    text$ = "I'm different!" + chr$(0)
ELSE
    text$ = "Changed!" + chr$(0)
END IF

calldll #user,  "SendMessage", _
stat.hwnd as word, _
1025 as word, _
0 as word, _
text$ as ptr, _
r as dword

GOTO [loop]



[size]
' Tell the status bar to resize itself
' input stat.hwnd
' output:  none

calldll #user, "SendMessage", _
stat.hwnd as word, _
_WM_SIZE as word, _
0 as word, _
WindowWidth as long, _
re as long
goto [loop]


[quit]
' Tell status bar to kill itself
' input stat.hwnd

calldll #user, "SendMessage", _
stat.hwnd as word, _
_WM_DESTROY as word, _
0 as word, _
0 as long, _
re as long
' Close handles
close #1
close #cctl
close #user

end
---------------------------------------------------------
3 - A MULTI-PART STATUS BAR!

Steps to create a multi-part status bar:

1)  All steps in the first example must be done.

2)  Build a STRUCT that will contain the X location
    for the end of each part, or segment of the
    status bar.  Here it is called prt and contains
    information for three segments:

    struct prt,end1 as short, end2 as short,end3 as short

3)  Fill the struct with the values for the X location
    for the end of each segment.  The last value should
    be set to -1, so that the last segment will always
    continue to the right edge of the window.

    prt.end1.struct=140
    prt.end2.struct=230
    prt.end3.struct=-1

5)  Determine the total number of parts to set in the
    status bar.  This will probably be equal to the
    number of items in the struct.

    number.parts=3

5)  Send a Windows message to SET the parts of the
    status bar.  The first parameter will be the
    handle of the status bar.  The second parameter
    will be 1028, which is the value for SB_SETPARTS.
    The word parameter is the number of parts you
    want to make.  The long parameter is a pointer to
    the struct containing the X - END values for the parts.

    calldll #user,  "SendMessage", _
    stat.hwnd as word, _
    1028 as word, _
    number.parts as word, _
    prt as struct, _
    r as dword

6)  The text for the first part is set when the status bar
    is created.  The text for the remaining parts must
    be set as in the earlier example, with a Windows
    message, but this time, we must be sure to include
    the ID for the part we want to set text on.  The
    positions are numbered beginning with 0, so when
    setting text on the first part, use an ID of 0.  The
    second part has an ID of 1, the third part has an ID
    of 2, and so on.

    calldll #user,  "SendMessage", _
    stat.hwnd as word, _
    1025 as word, _
    segment.ID as word, _
    text$ as ptr, _
    r as dword

And here is an example program that includes a multi-part
status bar:
---------------------------------------------------------
' Original Code for Status Bar by Brent Thorn:
' lbgui@aol.com
'
' This example creates a multi-part
' status bar and demonstrates how to
' set the text in the segments.
'

nomainwin
' Open DLLs
open "commctrl.dll" for dll as #cctl
open "user" for dll as #user


' Open window
WindowWidth=600:WindowHeight=150
statictext #1, "Resize this window.",10,10,300,30
open "Status Bar Test" for window as #1


' Set up events
print #1, "trapclose [quit]"
print #1, "resizehandler [size]"


' Get window handles
hwnd = hwnd(#1)


' Init common controls
calldll #cctl, "InitCommonControls", _
re as void


' Flags for status window creation -
' these are the minimum:
style = _WS_VISIBLE or _WS_CHILD


' Text to appear on status bar -
' must be null terminated
text$ = "I'm a real status bar!" + chr$(0)


' Windows and controls created via API
' must be assigned an ID number
' which is not used in LB.
id = 1


' create status bar
' output style, text$, hwnd, id
' input stat.hwnd

GOSUB [create.status.bar]

' the status bar handle is now = stat.hwnd


' create a struct to hold the length of
' the segments in the status bar:
struct prt,end1 as short, end2 as short,end3 as short

' fill the struct with x values for length of segments
' a value of -1 will create a segment
' which ends at the right edge of the window
prt.end1.struct=140
prt.end2.struct=230
prt.end3.struct=-1

'determine the number of segments:
number.parts=3

' output stat.hwnd, number.parts, prt
GOSUB [set.parts]

' set text to be contained in segments
' segment ID numbers begin at 0,
' so the ID of the second segment is 1
' output segment.ID, stat.hwnd, text$ 

segment.ID=1
text$="Second Part"+chr$(0)
GOSUB [set.text]

segment.ID=2
text$="Third Part"+chr$(0)
GOSUB [set.text]


[loop]
input a$ ' Wait for events


[create.status.bar]
' input style, text$, hwnd, id
' output stat.hwnd

calldll #cctl, "CreateStatusWindow", _
style as long, _
text$ as ptr, _
hwnd as word, _
id as word, _
stat.hwnd as word

RETURN


[set.parts]
' input stat.hwnd, number.parts, prt
' output:  none
' 1028 is SB_SETPARTS

calldll #user,  "SendMessage", _
stat.hwnd as word, _
1028 as word, _
number.parts as word, _
prt as struct, _
r as dword

RETURN



[set.text]
' input text$, stat.hwnd, segment.ID
' output: none
' 1025 is SB_SETTEXT

calldll #user,  "SendMessage", _
stat.hwnd as word, _
1025 as word, _
segment.ID as word, _
text$ as ptr, _
r as dword

RETURN





[size]
' Tell the status bar to resize itself
' input stat.hwnd
' output:  none

calldll #user, "SendMessage", _
stat.hwnd as word, _
_WM_SIZE as word, _
0 as word, _
WindowWidth as long, _
re as long
goto [loop]


[quit]
' Tell status bar to kill itself
' input stat.hwnd

calldll #user, "SendMessage", _
stat.hwnd as word, _
_WM_DESTROY as word, _
0 as word, _
0 as long, _
re as long
' Close handles
close #1
close #cctl
close #user

end
---------------------------------------------------------
4 - AN INTERESTING STATUS BAR DEMO:

No steps here, since they are already documented.
Have fun!
---------------------------------------------------------
' Original Code for Status Bar by Brent Thorn:
' lbgui@aol.com
'
' This example creates a multi-part
' status bar and demonstrates how to
' set the text in the segments.
' It includes a dynamic display change.

nomainwin
' Open DLLs
open "commctrl.dll" for dll as #cctl
open "user" for dll as #user


' Open window
WindowWidth=300:WindowHeight=150
statictext #1, "Watch the Clock!",10,10,300,30
open "Status Bar Test" for window as #1


' Set up events
print #1, "trapclose [quit]"
print #1, "resizehandler [size]"


' Get window handles
hwnd = hwnd(#1)


' Init common controls
calldll #cctl, "InitCommonControls", _
re as void


' Flags for status window creation -
' these are the minimum:
style = _WS_VISIBLE or _WS_CHILD


' Text to appear on status bar -
' must be null terminated
text$ = DATE$() + chr$(0)


' Windows and controls created via API
' must be assigned an ID number
' which is not used in LB.
id = 1


' create status bar
' output style, text$, hwnd, id
' input stat.hwnd

GOSUB [create.status.bar]

' the status bar handle is now = stat.hwnd


' create a struct to hold the length of
' the segments in the status bar:
struct prt,end1 as short, end2 as short

' fill the struct with x values for length of segments
' a value of -1 will create a segment
' which ends at the right edge of the window
prt.end1.struct=140
prt.end2.struct=-1

'determine the number of segments:
number.parts=2

' output stat.hwnd, number.parts, prt
GOSUB [set.parts]


[loop]'make a clock display
SCAN
segment.ID=1

IF text$<>TIME$()+chr$(0) THEN
    text$=TIME$()+chr$(0)
    GOSUB [set.text]
END IF

goto [loop]


[create.status.bar]
' input style, text$, hwnd, id
' output stat.hwnd

calldll #cctl, "CreateStatusWindow", _
style as long, _
text$ as ptr, _
hwnd as word, _
id as word, _
stat.hwnd as word

RETURN


[set.parts]
' input stat.hwnd, number.parts, prt
' output:  none
' 1028 is SB_SETPARTS

calldll #user,  "SendMessage", _
stat.hwnd as word, _
1028 as word, _
number.parts as word, _
prt as struct, _
r as dword

RETURN



[set.text]
' input text$, stat.hwnd, segment.ID
' output: none
' 1025 is SB_SETTEXT

calldll #user,  "SendMessage", _
stat.hwnd as word, _
1025 as word, _
segment.ID as word, _
text$ as ptr, _
r as dword

RETURN





[size]
' Tell the status bar to resize itself
' input stat.hwnd
' output:  none

calldll #user, "SendMessage", _
stat.hwnd as word, _
_WM_SIZE as word, _
0 as word, _
WindowWidth as long, _
re as long
goto [loop]


[quit]
' Tell status bar to kill itself
' input stat.hwnd

calldll #user, "SendMessage", _
stat.hwnd as word, _
_WM_DESTROY as word, _
0 as word, _
0 as long, _
re as long
' Close handles
close #1
close #cctl
close #user

end
---------------------------------------------------------
mailto:awatson@wctc.net
---------------------------------------------------------