---------------------------------------------------------
The Liberty Basic Newsletter - Issue #100 - SEP 2002
    2002, http://groups.yahoo.com/group/lbnews/
             All Rights Reserved
Individual authors retain copyrights to their works.
---------------------------------------------------------
The truth always turns out to be simpler than you thought.
--Richard Feynman, physicist, educator
---------------------------------------------------------
In this issue:
	Notes from the editor
	Use of Color in Graphics
	Bitmap Graphics Tutorial
	Bitmap Color Formats
	Tipcorner 
		- Getting the dimensions of a bitmap
		- SCAN vs WAIT
	Text Input Boxes - Text and Background Colour
			     - by Ray Fisher
	An Easy Calendar Control
	Shareware Marketing by Eldron Gill
	Demos:
		- Date/Time Picker by Brent Thorn
		- Text Line-Wrap by Bill Jennings
		- Combining Commands by David Connor
	Submissions
---------------------------------------------------------
NOTES FROM THE EDITOR

Wow, this is Issue #100 of the Liberty BASIC Newsletter!
It has grown and changed since its inception in April,
1999, when it was a simple 10KB text mailing.  Thanks to
the great community who makes it possible!

Special thanks to Eldron Gill for his incredibly informative
article about shareware marketing!

Thanks also to Brent Thorn for yet another great demo.
This one provides a really cool calendar tool for Liberty 
BASIC users!

Thanks Ray Fisher for a great article on creating
custom colored text controls!

Thanks Bill Jennings, for the clever line-wrap routine!

Thanks David Connor, for adding to the scripting language
from issue #98!

It is easy to help out with The Liberty BASIC Newsletter.
See the "Submissions" topic at the bottom of each newsletter.
We accept demo code, which will generally be described
briefly in the body of the newsletter, with the BAS file
included as an attachment.  

We LOVE to get articles for publication!  An article is
more than commented code.  It might contain explanations
for all steps and routines used in code, or it might detail 
a list of programmer's resources, or it might give advice
on debugging, or it might discuss a general programming area
(such as database programming), or it might give in-depth 
instructions for using certain commands, or it might...
er, you get the idea!  An article can be "about" anything
that might help people write or distribute programs in
Liberty BASIC.

We also LOVE to get suggestions for articles!  Topics chosen
come from our own experience and areas of interest, and from
questions and discussions on the various Liberty BASIC public
forums.  If you have a suggestion, then send it to one of
the team!

The newsletter is published by a team.  If you think you'd
like to join the team, just write to one of us at the
email addresses given at the bottom of each issue.

Please consider sending comments on the newsletters.  It
is difficult to know if any of the articles are useful to
our readers, or even if anybody reads them, unless we
receive some comments from time to time!  If you find
something of interest in a newsletter, please take just a 
moment to write to the author of the article and let him
know that it was helpful!

	-Alyce Watson-
---------------------------------------------------------
USE OF COLOR IN GRAPHICS    (novice level) 
  - part two in a series of graphics tutorials
  - by Alyce Watson (copyright 2002)

There are three commands that are used in graphicboxes and 
graphics windows to specify color.  They are:

color
backcolor
fill

The color commands are not case sensitive, so color, Color, 
COLOR and CoLoR are all acceptable.

COLOR
Color sets the foreground color.  This is the color of the pen 
used to draw the borders of all drawn objects, like lines, 
circles and boxes.  It is also the color of graphic text.


BACKCOLOR
Backcolor sets the color that will fill drawn objects.  For 
instance, a "boxfilled" will be filled with the color set by 
the BACKCOLOR command.  Backcolor is also the color that appears 
behind graphics text.


FILL
Fill covers the graphics area - either the entire graphicbox or 
the entire workspace of a graphics window - with the color 
specified.  Issuing a FILL command will cover over everything 
previously drawn on the graphics area.


NAMED COLORS
There are sixteen named colors to use with the three COLOR commands:

black
white
darkgray
lightgray
red
darkred
green
darkgreen
blue
darkblue
cyan
darkcyan
pink
darkpink
yellow
brown

Here is a tiny program that uses the color commands with 
named colors.  It illustrates that text is backed by the 
BACKCOLOR and not by the FILL color.  Run the program and 
notice that the part of the text that is over the cyan 
interior of the circle blends in with the circle, but 
the part of the text that is on the yellow-filled 
background still displays a cyan BACKCOLOR.  (Tutorials 
on drawing objects and text will follow later in the 
series of graphics tutorials.)

nomainwin
open "Colors" for graphics_nsb_nf as #1
print #1, "down"
print #1, "color red"
print #1, "backcolor cyan"
print #1, "fill yellow"
print #1, "place 100 100"
print #1, "circlefilled 80"
print #1, "place 30 30"
print #1, "\Hello World"
wait

Running the program above will show you a window that contains in 
addition to the text, a circle bordered in red and filled with cyan, 
against a window that is filled with yellow.  A single line of code 
has been added to make the program below.  A FILL command is issued 
after the other graphics commands, but before the WAIT statment.  
Running the new version of the program produces a graphics window 
filled with blue, and nothing else!  The FILL command covers all 
previous graphics.

nomainwin
open "Colors" for graphics_nsb_nf as #1
print #1, "down"
print #1, "color red"
print #1, "backcolor cyan"
print #1, "fill yellow"
print #1, "place 100 100"
print #1, "circlefilled 80"
print #1, "place 30 30"
print #1, "\Hello World"
print #1, "fill blue"
wait


BUTTONFACE
There is one more named color.  It is BUTTONFACE.  This will 
match the system's buttonface color.  In a standard Windows 
color scheme, this will be lightgray.  In other color schemes, 
this color might be blue, or green, or very pale gray, or tan, 
or any color specified by the user in a custom color scheme.  
It is good to know this color so we can match our graphics to 
the user's system.  We could fill a graphicbox with lightgray, 
which would match many user's color schemes, but it would look 
very wrong to the user who has an "all blue" color scheme on his 
system.  If instead, we fill with BUTTONFACE, then the users with 
the standard color scheme will see lightgray, but the guy with an 
"all blue" color scheme will see a blue box that matches all the 
other colors on his system.  Here is a modified demo that uses 
BUTTONFACE:

nomainwin
open "Colors" for graphics_nsb_nf as #1
print #1, "down"
print #1, "color red"
print #1, "backcolor cyan"
print #1, "fill buttonface"
print #1, "place 100 100"
print #1, "circlefilled 80"
wait


RGB
RGB stands for Red, Green, Blue.  Each color has a red component, 
a green component and a blue component.  Each of these components 
is in the range of 0 - 255.  If, for instance, the red component 
of a color is 255, then there is total saturation of red in the color.  
If instead it is 0, then there is no red in the color at all.  
Numbers in between indicate varying amounts of a color, with 127 
or 128 being the halfway point.  

You specify an RGB color differently than a named color.  To specify 
a RED FILL with a named color:

print #1, "fill red"

An RGB color statement requires a number for red, one for green and 
one for blue.  

print #graphics, "fill red(0-255) green(0-255) blue(0-255)"

To fill with red as an RGB color as it would actually appear in a program:

print #1, "fill 255 0 0 "

The statement above makes the color have a total saturation of red, 
and no green or blue.  To create a "darkred" color, use a half 
saturation of red, like this:

print #1, "fill 128 0 0"

Yellow is a combination of red and green, so setting the 
red and green values both to 255 creates yellow.  The 
following two statements are equivalent:

print #1, "fill 255 255 0"
print #1, "fill yellow"

Cyan is a combination of green and blue with no red.  Pink 
is a combination of red and blue with no green.  (Some 
people refer to this color as magenta.)  If the red, green 
and blue components are equal, the color will be a shade 
of gray, ranging from black to white:

print #1, "color 0 0 0"        'black
print #1, "color 128 128 128"  'darkgray
print #1, "color 192 192 192"  'lightgray
print #1, "color 255 255 255"  'white


BONUS QUESTION!
Can you work out the RGB values for all 16 named Liberty BASIC colors?


CUSTOM COLORS
Custom colors are easily created, so feel free to experiment.

print #1, "fill 255 200 140"       'orange
print #1, "backcolor 95 240 160"   'mint green
print #1, "color 255 240 210"      'beige


Here is a little demo that shows many possible color 
combinations that can be created with RGB colors.  It 
fills the screen with random RGB colors at one second 
intervals using the TIMER.  The red, green and blue 
components are chosen randomly with Liberty BASIC's RND() 
function.  Please look in the helpfile for more on the use 
of the RND() function.  Remember that variables are placed 
outside of quote marks in graphics statements.  The resulting 
values for red, green and blue are variables and are outside 
of the quote marks when used below, and blank spaces are preserved!

nomainwin
open "Random RGB Colors" for graphics_nsb_nf as #1
print #1, "trapclose [quit]"
print #1, "down"

timer 1000, [change]
wait

[quit]
timer 0
close #1:end

[change]
red = int(rnd(0)*255)+1
green = int(rnd(0)*255)+1
blue = int(rnd(0)*255)+1
print #1, "fill ";red;" ";green;" ";blue
wait

---------------------------------------------------------
BITMAP GRAPHICS TUTORIAL (novice level)
  - part three in a series of graphics tutorials
  - by Alyce Watson (copyright 2002)

WHAT IS A BITMAP?
What is a bitmap?  In simplest terms, a bitmap is a rectangular
picture.  Computers recognize things as collections of bits,
so to a computer, a bitmap is a rectangular grid of pixels.

WHAT IS A PIXEL?
"Pixel" is a shortened form of the term "Picture Element".  Your
display is made of pixels.  If your screen resolution is set to
800x600, this means that it is divided into 800 distinct picture
elements across the width, and 600 distinct picture elements
along the height.  Each of the picture elements is colored with
a distinct, single color.  Altogether, they comprise the image
that you see when you look at your computer screen.

Here is a way to think of it.  Imagine that you have a checker
board.  The board consists of 64 squares - 8 squares wide by
8 squares high.  Think of each of these squares as ONE pixel.
Now imagine that you have a palette that contains four colors
of paint - red, green, blue and yellow.  You are told to color
each square in the checker board with one of these colors.  You
must fill each square completely with only one color, and you must 
fill all of the squares with one of the four colors.  Using the
first letters of the color names, you might create a picture
that looks like this:

R R R R R R R R
R G R G B B B B
Y Y Y R R R Y Y
B B B B B Y Y R
R Y Y Y Y B B B
G G G G Y Y Y Y
B B B B B G G G
G G Y Y R R B B 

This is a pretty fair representation of the way your computer
sees images.  A bitmap file on disk consists of information about
the attributes of the bitmap, such as width and height, at the start 
of the file.  After this file header, you will find a map of bit 
values.  These values are like the checker board representation
above.  The computer knows to paint the individual pixels on the
screen according to the information in this map of bit values.

HOW DO WE USE BITMAPS IN LIBERTY BASIC?
Before a bitmap can be used, it must be loaded from the disk into
the computer's memory (RAM).  Once the bitmap is in the computer's
RAM, it can be displayed on the screen.  We load bitmaps into
memory with the LOADBMP command.

LOADBMP
The LoadBmp command is easy to use.  It looks like this:

loadbmp "PicName", "filename.bmp"

"PicName" can be any name that suits your fancy.  After giving
the loaded bitmap this name, you will use it to tell Liberty
BASIC that you want to access this bitmap.  It is best to
give the bitmap a descriptive name, like "RedCar" or "EnemyShip",
but Liberty BASIC doesn't care what you call it!  You can call
it "xxx" or "potato" or any other name.  Just remember that this
name is case sensitive, so "xxx" and "XXX" are two different
bitmap names.

"filename.bmp" is the name of a bitmap file on disk.  If this
file is in the same directory as the Liberty BASIC program, then
the filename alone is enough -- no path information is needed.
You can place your bitmap files in a subfolder of your program
if you'd like.  If your subfolder containing bitmaps is called
"images" then you would load a bitmap from that folder like
this:

loadbmp "PicName", "images\filename.bmp"

You can include all path information if you'd like.  This is called
"hard-coding" a path.

loadbmp "PicName", "c:\mystuff\myprogs\filename.bmp"

The above hard-coded method works fine IF you are the only
one who will use your program, and IF you will not be moving any
of the files.  Attempting to load a bitmap file that cannot be
found by Liberty BASIC will cause a runtime error and the program
will stop running.   It is almost always best to avoid hard-coding
paths to files used by a program.  If you plan to share your program
with someone else, the other person is not likely to have exactly
the same directory setup as you have, so a command like the one 
above will crash the program.

FILEDIALOG
You can allow a program's user to select a bitmap using the
FILEDIALOG command, like this:

filedialog "Open", "*.bmp", bmpfile$
loadbmp "MyPic", bmpfile$

UNLOADBMP
We've explained that you must load a bitmap into the computer's
memory to use it.  It stays in memory until it is unloaded.  If
you fail to unload bitmaps used by a program, the system will
become sluggish and may even fail, due to lack of resources.
People who use your program will not appreciate this deterioration
in their session at the PC, and they certainly won't appreciate
the need to reboot from a program crash!  For this reason, it
is VERY IMPORTANT to use the UNLOADBMP command for every loaded
bitmap in a program.  It looks like this:

unloadbmp "MyPic"

GETBMP
You can load a bitmap into memory from your own Liberty BASIC
graphics that have been drawn in a graphicbox or graphics window.
This method uses the GETBMP command:

print #graphics, "getbmp bmpname x y width height"

"bmpname" will be the name you give to the bitmap, just as you
did when using the LOADBMP command to load a bitmap from disk.
"x" will be the coordinate of the left side of the bitmap you "GET".
"y" will be the coordinate of the top side of the bitmap.  The
width and height paramters will be the desired width and height of 
the bitmap.  The code above will NOT run properly in Liberty BASIC!
The actual values must be placed in the command.  In a program, it
might look like this:

print #graphics, "getbmp MyPic 10 14 200 100"

This command tells Liberty BASIC to load a bitmap into memory that
is taken from the graphics window whose handle is #graphics.  The
upper left corner of the bitmap is at x=10, y=14.  The width is 200
and the height is 100.  The Liberty BASIC name for this loaded
bitmap will be "MyPic".  If you will be using variables in the
command, then place them outside of the quote marks, making sure to
preserve needed spaces in between the values like this:

picname$ = "MyPic"
x = 10
y = 14
w = 200
h = 100

print #graphics, "getbmp ";picname$;" ";x;" ";y;" ";w;" ";h

Be sure to UNLOADBMP for bitmaps loaded with GETBMP.

DRAWBMP
Once a bitmap has been loaded into memory with LOADBMP or GETBMP,
it can be displayed in a graphics window or graphicbox with the
DRAWBMP command.

print #graphics, "drawbmp bmpname x y"

Just as before, you must either include the actual values inside
of the quote marks or place variables outside of the quote marks.
To display a bmp that was loaded with the name "MyPic" at x=10
y=20:

print #graphics, "drawbmp MyPic 10 20"

or

x = 10
y = 20
bmpname$ = "MyPic"
print #graphics "drawbmp ";bmpname$;" ";x;" ";y

BMPSAVE
You can save a bitmap to disk that is loaded into
memory.  Here is the syntax:

bmpsave "bmpname", "filename.bmp"

Just as when opening bitmaps from disk, if no path
is specified, the bitmap will be saved in the same
directory as the running program.  As it might look in
a program:

bmpsave "MyBmp", "test.bmp"

Here are two demos.  The first one draws some graphics
in a graphicbox, uses GETBMP to load the graphics into
memory as a bitmap, then draws that memory bitmap onto
a second graphicbox.  It also saves the graphics as a
bitmap on disk.  The second demo allows the user to choose
a bitmap on disk, loads it into memory with LOADBMP, draws
it in a graphicbox, and saves it to disk with the filename
specified by the user.

'first demo:
nomainwin
WindowWidth=300
WindowHeight=320
graphicbox #1.1, 10,10,102,102
graphicbox #1.2, 120,10,102,102
open "Bitmap Demo" for window_nf as #1
print #1, "trapclose [quit]"

'first draw some graphics:
print #1.1, "down; fill darkblue"
print #1.1, "color pink; backcolor yellow"
print #1.1, "size 4; place 50 50"
print #1.1, "circlefilled 30;flush"

'now use GETBMP to get the bitmap into memory:
print #1.1, "getbmp MyBmp 0 0 100 100"

'draw the bitmap in memory in the second graphicbox:
print #1.2, "down"
print #1.2, "drawbmp MyBmp 0 0;flush"

'save the bitmap to disk with BMPSAVE:
bmpsave "MyBmp", "test.bmp"

'unload the bitmap from memory:
unloadbmp "MyBmp"

wait

[quit]
close #1:end

'second demo:
nomainwin
WindowWidth=600
WindowHeight=420
graphicbox #1.1, 0, 0, 600, 400
open "Bitmap Demo" for window_nf as #1
print #1, "trapclose [quit]"

'allow the user to choose a bitmap file on disk:
filedialog "Open", "*.bmp", bmpfile$
if bmpfile$="" then [quit]

'load the bitmap into memory:
loadbmp "MyBmp", bmpfile$

'draw the bitmap in the graphicbox:
print #1.1, "down"
print #1.1, "drawbmp MyBmp 0 0;flush"

'let user choose a name for saving bitmap to disk:
filedialog "Save As", "*.bmp", savefile$
if savefile$="" then [quit]

'save the bitmap to disk with BMPSAVE:
bmpsave "MyBmp", savefile$

wait

[quit]
'unload the bitmap from memory:
unloadbmp "MyBmp"
close #1:end

---------------------------------------------------------
BITMAP COLOR FORMATS (intermediate level)
	by Alyce Watson (copyright 2002)

All bitmaps are not created equal.  One bitmap can have a
very large file size for an image with certain dimensions,
while another bitmap with the same dimensions can have a much
smaller file size.  Why is this?  The answer lies in the
color format of the bitmap.

You might have heard the term "24-bit bitmap" or "256-color
bitmap" or "1-bit bitmap" or others.  This description tells
us how much storage space is needed to document each single
pixel in the bitmap.

**************
24-BIT BITMAPS
Let's first consider 24-bit bitmaps.  They require 24-bits
of data to document each single pixel in the bitmap.  You can
see how this would lead to large file sizes, particularly for
bitmaps with large dimensions.  What is stored in the 24-bits of
data?  The 24-bits are divided into three 8-bit pieces for each
pixel.  The first 8-bits holds the blue color value, the next
8 bits holds the green color value, and the final 8 bits holds
the red color value.  For more information on red-green-blue
color specifications, see the color graphics tutorial above.

8-bits of data will hold the numbers 0 through 255, for a total
of 256 possible values.  Each color component then can have a
value of 0-255, with 0 being none of that color, and 255 being
total saturation of that color.  Since there are three colors
to consider for each pixel, each pixel then uses 24-bits of data
to document its color.  A 24-bit bitmap on disk consists of a
header, which contains information about the size and format of
the bitmap, followed by the pixel data - 24-bits of data for each
pixel.

Structure of a 24-bit bitmap file:
bitmap header
pixel data requiring 24-bits for each pixel

**************************
8-BIT OR 256-COLOR BITMAPS
As mentioned above, 8-bits can hold 256 possible values, 0-255.
An 8-bit bitmap requires only 8 bits of data storage space to 
document each pixel.  This shorthand is accomplished by
including a palette in the file, which is placed after the header
information, and before the pixel data.  A palette is also often
called a Color Table.

The palette for a 256-color bitmap can hold up to 256 colors.
There is a standard Windows palette of 256-colors, but bitmaps
can also have custom palettes.  It goes something like this:
In the palette, color number 1 has a red-green-blue value.
Each pixel in the bitmap that is to be displayed in color
number 1 will have data equal to "1" in binary numbers.
Color number 113 has a different red-green-blue value, so
every pixel in the bitmap that is to be displayed in color
number 113 has data equal to "113" in binary numbers.  Windows
then must look up the red-gree-blue value of color 113 to
display a pixel in that color. 

For a bitmap with large dimensions, this palette indexing
method of documenting colors creates a huge savings in file
size.  In general, 256-color bitmaps have much smaller file
sizes than a 24-bit bitmap with the same dimensions.

Structure of a 256-color (8-bit) bitmap:
bitmap header
indexed palette information
pixel data requiring 8-bits for each pixel

*************************
4-BIT OR 16-COLOR BITMAPS
The 16 named colors in Liberty BASIC represent the typical
colors of a 4-bit bitmap.  A 4-bit bitmap is constructed in
a similar manner to an 8-bit bitmap.  The difference is that
instead of 256 possible palette colors, there are only 16 
possible colors.  In binary, the number 16 requires 4 bits
of space.

The 16-color bitmap consists of a bitmap header and a palette
of 16 colors.  It is followed by the pixel data.  Each pixel
requires only 4-bits of data to indicate one of the 16 colors
in the palette.

Structure of a 16-color (4-bit) bitmap:
bitmap header
indexed palette information
pixel data requiring 4-bits for each pixel

**************************
1-BIT OR 2-COLOR BITMAPS
In binary numbers, a bit is either set or not set.  If it
is set, there will be a "1" in that spot.  If it is not set,
there will be a zero there.  A plain black and white bitmap
requires only a single bit to document each pixel.  If the bit
is set (equal to 1), the pixel is white, if the bit is not set,
(equal to 0), the pixel is black.  This type of bitmap has a 
very small file size, and doesn't require a palette.

Structure of a 2-color (1-bit) bitmap:
bitmap header
pixel data requiring 1-bit for each pixel


The color formats mentioned are the formats of the bitmap as 
it is saved on disk.  Please refer to Newsletter #62 for an
explanation of reading a bitmap file header to determine the
color format of a bitmap on disk.  A small example is
included here.  The BmpSave command will save the bitmap
to disk with its original color format.  This means that a bitmap
that has been loaded from disk with LOADBMP will be saved in the
same color format as the original bitmap on disk.  If a bitmap that
is loaded with GETBMP is saved, it will be saved to disk with the
color format that matches the current screen color resolution,
because it has been loaded from the screen.

Here is a small demo that determines the color bits of a bitmap
on disk.

FileDialog "Open","*.bmp",bmp$
If bmp$="" Then End

'get bits per pixel of bitmap file on disk
open bmp$ for input as #pic
pic$=input$(#pic,29)
close #pic

BitsPixel=asc(right$(pic$,1))
print "Bitmap Color Format Bits: ";BitsPixel

---------------------------------------------------------
TIPCORNER:  GETTING THE DIMENSIONS OF A BITMAP
	- by Alyce Watson

It is sometimes helpful to know the width and height of a
bitmap.  There are two ways to get this information.  The
first is to open the file and parse the first part of it to
determine the dimensions.  The second way requires that the
bitmap be loaded into memory.  The dimensions can then be
retrieved with an API call.

OPENING FILE:
We can get the dimensions of a bitmap on disk with Liberty
BASIC commands.  We can open the file and read the first part
of it into a string variable, then parse the string variable
to find the width and height of the bitmap.

Here is the simple code to get a bitmap's dimensions.  This
technique is explained in detail in Newsletter #67, so please
refer to that issue for more information on reading file headers.  
The code below can be used just as it is (even if you don't 
understand it!) to get the dimensions of a bitmap on disk.


filedialog "Open Bitmap","*.bmp", picFile$

open picFile$ for input as #pic
    pic$=input$(#pic, 29)
close #pic

bmpwidth = asc(mid$(pic$,19,1)) + (asc(mid$(pic$,20,1)) * 256)
bmpheight = asc(mid$(pic$,23,1)) + (asc(mid$(pic$,24,1)) * 256)

print "Bitmap width is ";bmpwidth
print "Bitmap height is ";bmpheight

****************
USING API CALLS:
We can also get the dimensions of a loaded bitmap with an API
call to GetObjectA.  It requires a handle to the loaded bitmap.
We get the handle with the HBMP() function.  It also requires
a struct to hold the values returned by the function.  After the
function is called, the width and height are contained in the
designated members of the BITMAP struct.  Here is the usage:

'load a bitmap from disk into memory:
loadbmp "MyBmp", bmpfile$

'get the bitmap handle with HBMP()
hBitmap=hbmp("MyBmp")

'create a struct to hold the returned values:
    struct BITMAP,_
    bmType As long,_
    bmWidth As long,_
    bmHeight As long,_
    bmWidthBytes As long,_
    bmPlanes As word,_
    bmBitsPixel As word,_
    bmBits As long

'get the size of the struct:
    nSize=Len(BITMAP.struct)

'make the call to GetObjectA:
    CallDLL #gdi32, "GetObjectA",_
        hBitmap As long,_    'handle of bitmap
        nSize As long,_      'size of struct
        BITMAP As struct,_   'name of struct
        results As long

'retrieve the dimensions of the loaded bitmap:
    BitmapWidth=BITMAP.bmWidth.struct
    BitmapHeight=BITMAP.bmHeight.struct

'unload the bitmap from memory:
    unloadbmp "MyBmp"

---------------------------------------------------------
TIPCORNER - SCAN VS WAIT
	- by Alyce Watson

There is often confusion regarding the use of SCAN and WAIT.
Both commands allow the program to check for user input, but
there is a difference:

SCAN will poll the system for user events, THEN CONTINUE 
PROGRAM EXECUTION

WAIT will poll the system for user events, THEN STOP 
PROGRAM EXECUTION      

"Input aVar$" is exactly equal to WAIT.  The WAIT command was
added because it seemed more descriptive of what was happening,
and is the preferred command to use for that reason.

Here are some snips to illustrate.  In this snip, since SCAN 
is used, the output screen will show both printouts:

'snip 1
print "one"
scan
print "two"

The program prints "one", scans for user events, then continues 
to print "two"  Output in mainwindow will be:

one
two

In the next example, the program prints "one", then stops 
program execution and waits for user events.  (Or perhaps a 
timer event.)  The word "two" is never printed, because program 
exection stops at the WAIT command.   Execution will continue 
later at a branch label associated with a button, menu item, or 
the timer, etc.  Again, the "two" will NEVER be printed:

'snip 2
print "one"
wait
print "two"

The third example is exactly the same as the second.  It simply 
uses "input a$" instead of "WAIT".  The two commands may be used 
interchangeably.  The program NEVER prints "two" because 
execution stops at the "input a$" statement, and will later 
continue at a branch label associated with a control, or perhaps
at a timer event handler.

'snip 3
print "one"
input a$
print "two"

USING SCAN TO CYCLE CONTINUOUSLY
If there is a need for a program to perform repetitive actions,
and check for events constantly at the same time, then SCAN
should be used in the cycling loop.  It might look like this:

[CycleLoop]
    num = int(rnd(0)*2000)
    print  num
    SCAN
    goto [CycleLoop]

The routine above didn't really accomplish much.  It was just
meant to show that actions can be performed continuously in
a loop.  The cycle loop can contain many lines of code that
perform many actions, including GOSUBS, and calls to SUBS and
FUNCTIONS.  To see why SCAN is necessary in the routine above,
remove it and try the snippet again.  You'll find that you 
cannot stop the program from running!  In that instance, press
the "ctrl" key, hold it down and hit the "break" key.

Carl Gundel says, "Scanning is an appropriate technique when you 
want a loop to run as fast as the computer can execute it (using 
WAIT and a timer will run the same speed on all computers as long 
as they are fast enough to run all code up to the WAIT before each 
timer tick)."

Here is the same routine as above, but run on a timer rather
than in a continuous loop.  It will run at approximately the same
speed on all computers, while the continously cycling loop will
run as quickly as a computer can process it -- faster on fast 
computers, and slower on slow computers.

timer 250, [DoRandom]

[DoRandom]
    num = int(rnd(0)*2000)
    print  num
    wait

USE A CONTINUOUS SCAN LOOP WITH CAUTION!
Carl Gundel says, [the program might slow down] "if you stick 
in more than one SCAN per loop, which is sometimes not a good 
idea for various reasons.  SCAN is probably best used at the 
end of a loop.  If you use it at the beginning, this can sometimes 
prevent the contents of the loop from executing.  On the other hand, 
if this is the design intention, then you can do it that way.
The concern is that while your Liberty BASIC program runs 
continuously this will slow down everything else on your system 
that isn't your program."

---------------------------------------------------------
Text Input Boxes - Text and Background Colour
	by Ray Fisher 
		rmfisher@talk21.com OR
		rmfisher@btinternet.com

For some time I have wanted more control over the colour
of the text and the background in text input boxes.
Liberty BASIC allows you to control the background of
text boxes, but limits you to 16 colours. Also you can
set the text colour (16 colours only) but the colour set
then applies to all controls (static text, list boxes etc.).

I wanted to be able to set the text and the background
to any colour for each individual text input control.
By using a rich edit control I was able to do this.

The first step was to load the rich edit library, see
Note 1.

The second step was to create a function which would
get an instance handle of the window which is to
contain the control, see Note 2.

The third step was to create a function that would open
a rich edit control, using parameters to set the size
and position of the control, see Note 3.

The fourth step was to create a function to limit the
# of chars that can be entered so that the rich edit
control can act as a single line TextBox, see Note 4.

Before creating the colour functions it was necessary
to create a function to convert RGB hex values, see
Note 5.

The sixth step was to create a function to set the
background or paper colour of the rich edit control,
see Note 6.

The next step was to create a function to set the fore-
ground or ink colour of the rich edit control, see Note 7.
This function requires a structure which is placed near
the top of the program, see Note 8.

The final step was to create a single function that
would call all these individual functions, so that in
the main part of any program only this function would
need to be called each time a new instance of a
full-colour text input box was to be created, see note 9.

The following is all of the above functions incorporated
into a small demonstration program.

[editor's note:  the demo program, colored_textboxes.bas
is included in the zip file that is attached to this
newsletter to avoid accidental line-wraps that might occur
in an email client.]

---------------------------------------------------------
AN EASY CALENDAR CONTROL (intermediate level)
	by Alyce Watson

Many thanks to Brent Thorn for the demo of the Windows
DateTimePicker control, which is included in the DEMOS section 
of this newsletter.  The following is an in-depth look at both 
the calendar control, and the time-picker implementation
of the control.

We can create controls for windows by using API calls, and
they often work quite well.  These custom controls expand the
usage of Liberty BASIC and can add a very professional look
to our applications.  For more information on creating custom 
controls, try these downloadable electronic books:

Using Liberty BASIC 2
http://iquizme.0catch.com/lb/using/index.html

Mastering Liberty BASIC 3 (an update of the previous ebook)
http://iquizme.0catch.com/lb/lbw3/master.html

The first step in creating any control with API calls is to 
obtain the program window's handle, and use it to get the
instance handle of the window.  This is done with the function
GetWindowLongA, using the window's handle as an argument and the
flag _GWL_HINSTANCE to specify which long window value we want.

  CallDLL #user32, "GetWindowLongA", _
  hWindow As long,_         'window handle
  _GWL_HINSTANCE As long,_  'flag to get instance handle
  InstanceHandle As long    'returns instance handle

The next step is to initialize the Windows DLL that provides
the common controls, of which the DateTimePicker is a part.
For some common controls, it is possible to use the simpler
version of initialization, InitCommonControls, but that won't
work for this control, which requires the InitCommonControlsEx
function.  The function requires a struct that contains the
initialization data:

    struct icex, _
    dwSize As ulong, _
    dwICC As ulong

To fill the struct, specify the size of the struct:

    icex.dwSize.struct = Len(icex.struct)

Next, tell the DLL which control you want to have available:

    icex.dwICC.struct = Hexdec("100") 'ICC_DATE_CLASSES

Once the struct is properly filled, call the function:

    CallDLL #comctl32, "InitCommonControlsEx", _
    icex As struct, r As long

Once the initialization function is called, the specified
control is registered and available for your application's use.

**********************************
THE CALENDAR (DATE PICKER) CONTROL

The calendar control allows a program's user to select a date.
This may not sound too exciting, but the control is quite neat.
It consists of a textbox with an arrow button at the end, which
looks quite a lot like a combobox.  The textbox portion contains
the currently selected date.  When the arrow button is clicked,
a full month calendar drops into view!  It appears below and aligns 
itself with the left side of the textbox.  This calendar notes the
"today" date and has arrow buttons that allow the user to scroll
forward and backward through the months of the year -- a couple of
hundred years in each direction.  Once the user clicks on a date,
the calendar disappears from view, and the selected date appears in
the textbox portion of the control.  The user can also click on any
portion of the date in the textbox and type over it to change the
date.  For instance, the user can type over the month, making it a
12, and when the calendar drops down, it will display the month of
December.  So, the user may choose a date either by typing it into
the textbox portion of the control, or by scrolling through the 
months in the dropdown calendar.

The calendar can be customized by the programmer to show the 
desired date format and display colors.

As with many of the controls we create with API functions, this
one is created with CreateWindowExA.  An extended style isn't
needed for this window, so the first argument may be 0.  The
class argument is "SysDateTimePick32".  You may give the window
a name, but that is optional.  You must also specify the x, y
placement on the window, the width and height, the handle of the
parent window, and the instance handle of the parent window.  The
parameter for the menu handle is set to 0.  The function returns a
handle to the newly created control:

    style = _WS_VISIBLE Or _WS_CHILD 
    CallDLL #user32, "CreateWindowExA", _
    0 As long,_                     'extended style
    "SysDateTimePick32" As ptr, _   'class
    "DateTime" As ptr, _            'name
    style As long,_                 'window style flags
    x As long, y As long,_          'upper left x,y
    w As long, h As long,_          'width and height
    hW As long,_                    'parent window handle
    0 As long,_                     'menu handle
    hInstance As long,_             'instance handle of parent
    0 As long, _                    'not used here - extra data
    ControlHandle As long           'handle of created control
    End Function

We haven't yet mentioned the style flags.  The minimum for any
control are "_WS_VISIBLE Or _WS_CHILD" which make the control visible
and specify that it is a child window.  Here are some additional
style flags that are specific to the DateTime control:

DTS.UPDOWN = 1          'shows updown arrows, no calendar
DTS.RIGHTALIGN = 32     'aligns calendar with right side of control
DTS.SHORTDATEFORMAT = 0 'default short date format:  9/22/02
DTS.LONGDATEFORMAT = 4  'long date format: Sunday, September 22, 2002
DTS.SHORTDATECENTURYFORMAT = 12 '                  9/22/2002
DTS.APPCANPARSE = 16    'double-clicking highlights entire date
                        'default-click highlights only one part of date


The control is quite slick, but useless if we can't read the date
chosen by the user!  We can obtain the displayed date with a call to 
GetWindowTextA.  We'll first want to find out the length of the
text so that we can set up a properly sized buffer:

  CallDLL #user32, "GetWindowTextLengthA",_
    hW As long,_    'handle of date/time control
    tLength As long 'returns length of text

Now we can set up a string buffer and make the call to 
GetWindowTextA.  After the call, the date information will be
contained in Title$

    Title$=Space$(tLength)+Chr$(0)
    l=Len(Title$)
    CallDLL #user32, "GetWindowTextA",_
    hW As long,_    'handle of date/time control
    Title$ As ptr,_ 'buffer to hold text
    l As long,_     'length of buffer
    result As long

    notice trim$(Title$)

The method using GetWindowTextA works fine, but if we want to
separate the date or time components, Windows has provided a
message that allows us to get the date and time chosen by the
user.  We use SendMessageA and send the DTM_GETSYSTEMTIME
message to the control.  This message requires a struct to
hold all of the components of the time and date:  year,
month, day of week, day, hour, minute, second and millisecond.
No struct members need to be filled before calling the function.

    DTM.GETSYSTEMTIME = 4097
    Struct SYSTEMTIME, _
        wYear As word, _
        wMonth As word, _
        wDayOfWeek As word, _ '0 = Sunday, 1 = Monday, etc.
        wDay As word, _
        wHour As word, _
        wMinute As word, _
        wSecond As word, _
        wMilliseconds As word

Now that the struct is defined, call the function SendMessageA:

    CallDLL #user32, "SendMessageA", _
        hW As long, _               'handle of control
        DTM.GETSYSTEMTIME As long,_ 'flag to get chosen date/time
        0 As long, _                'wparam=0
        SYSTEMTIME As struct,_      'name of struct
        ret As long

To retrieve a single value, read the struct member desired.  
Here, we're checking for the month:

  mon=SYSTEMTIME.wMonth.struct

If mon = 12, then the month is December.  If you want to
know the month name, simply set up a string like this:

  m$="JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC"

You could use entire month names, like "January", of course!

To get the month name, knowing the month number, use the
word$() function:

  Month$=word$(m$,mon)

************************
CUSTOMIZING THE CALENDAR
We can customize the calendar by setting style flags when we
create the control.  If we include the flag for DTS.LONGDATEFORMAT
then the date will appear with the weekday spelled out, the month
spelled out, followed by the day and year.  The style flags would
look like this:

    style = _WS_VISIBLE Or _WS_CHILD or DTS.LONGDATEFORMAT

(Note that Liberty BASIC doesn't recognize the date/time Windows
constants, so we must supply these values in our code.)

The other styles are documented above and include DTS.UPDOWN 
DTS.RIGHTALIGN, DTS.SHORTDATEFORMAT, DTS.LONGDATEFORMAT,
DTS.SHORTDATECENTURYFORMAT, and DTS.APPCANPARSE.

If the DTS.UPDOWN style is chosen, then no calendar will drop
down.  In that case, the user can type over the portion of the
date he wishes to alter, or he can use the up-down arrows to 
scroll the currently highlighted portion of the date.  For instance,
if the month is highlighted, then pressing the up arrow will increase
the month value.

******
COLORS
We can change the default display colors to the ones of our choice
by sending the calendar control a message after it is created.
We do this with SendMessageA, and the appropriate arguments.
Here are the arguments from which we may choose:

DTM.SETMCCOLOR=4102     'message flag to set calendar background color

The above value is the message we send to change a color
in the calendar.  The values below are the parts of the calendar
whose color can be changed:

MCSC.BACKGROUND = 0     'Set the background color displayed between months.
MCSC.TEXT = 1           'Set the color used to display Text within a month.
MCSC.TITLEBK = 2        'Set the background color displayed in the calendar's title.
MCSC.TITLETEXT = 3      'Set the color used to display Text within the calendar's title.
MCSC.MONTHBK=4          'Set the background color displayed within the month.
MCSC.TRAILINGTEXT = 5   'Set the color used to display header day and trailing day text.
                        'Header and trailing days are the days from the previous and
                        'following months that appear on the current month calendar.

Here is a small demo that changes the background color of
the displayed calendar:

  DTM.SETMCCOLOR=4102 'message flag to set calendar color
  MCSC.MONTHBK=4      'color to change=month background
  col = 255 + (160*256) + (160*256*256)

  CallDLL #user32, "SendMessageA",_
  hW As long, _               'handle of control
  DTM.SETMCCOLOR As long,_    'set color message
  MCSC.MONTHBK As long,_      'part of control to set color on
  col As long,_               'color desired
  re As long

The formula to create a color is:
  color = red + (green*256) + (blue*256*256)
See the color article above for more on RGB colors.

***********
TIME PICKER
The time picker implementation isn't as fancy.  It
consists of a textbox containing the time,and spinner 
(up-down) arrows that allow the user to change the time
The user can type over the time the textbox or use the
arrows to scroll.  The arrows will scroll the time segment
that is highlighted -- either hours, or minutes, or seconds.
The control must be created with the DTS.TIMEFORMAT style:

  DTS.TIMEFORMAT=hexdec("0x0009")
  style = _WS_VISIBLE Or _WS_CHILD Or DTS.TIMEFORMAT

*************************
SETTING INITIAL DATE/TIME
Setting the initial date or time that is displayed on a
control is similar to retrieving the chosen date or time.

The message to send to the control to set the date 
or time is :

    DTM.SETSYSTEMTIME = 4098

The message requires the SYSTEMTIME struct as before:  

    Struct SYSTEMTIME, _
        wYear As word, _
        wMonth As word, _
        wDayOfWeek As word, _ '0 = Sunday, 1 = Monday, etc.
        wDay As word, _
        wHour As word, _
        wMinute As word, _
        wSecond As word, _
        wMilliseconds As word

Fill the struct members desired before sending the message.
This demo sets the date to February 14, 2003:

        SYSTEMTIME.wMonth.struct=2
        SYSTEMTIME.wDay.struct=14
        SYSTEMTIME.wYear.struct=2003

    DTM.SETSYSTEMTIME = 4098'message flag to set date/time displayed on control

Now, make the API call to send the message to the control:

    CallDLL #user32, "SendMessageA", _
        hwndDTP As long, _          'handle of control
        DTM.SETSYSTEMTIME As long,_ 'flag to set chosen date/time
        0 As long, _                'wparam=0
        SYSTEMTIME As struct,_      'name of struct
        ret As long


*****
DEMOS
Attached are two demos.  Calendar_nl.bas creates a calendar control
with the date format DTS.SHORTDATECENTURYFORMAT, which displays
like this:  9/22/2002.  It includes code to change the month
background color to pink.  It includes both methods of retrieving
the date - the GetWindowTextA method, or the more involved message
for DTM_GETSYSTEMTIME.  It also includes a routine to retrieve
the month name from the chosen date.  It also includes a function
to set the initial date displayed on the control.

Timepick_nl.bas demonstrates the time-picker implementation of
the control.

---------------------------------------------------------
SHAREWARE MARKETING
	by Eldron Gill

Editor's note:  Please see the attached document, 
SharewareMarketing.doc for a beautifully formatted version
of this article on marketing your software.  A plain text version
is also attached, to insure that everyone can read it.  The 
introduction and table of contents are copied below.

Eldron is a successful shareware author with several
programs published.  His "Birthday Keeper" has won
five-star awards from several of the download sites.
He has also published "New Testament in a Year", "Joke a
Day", "Verse a Day", and "Sermon Keeper".  All were written
in Liberty BASIC!

Visit Eldron's website here:
http://www.eaglesoartech.com/

Contact Eldron:
contact@eaglesoartech.com

Before reading this great article, you'll want to study
Brad Moore's article, "The Road to Release" from issue
#99, where he describes all of the steps needed to get
a program ready for distribution, from writing and testing
the code, through packaging and installing it on a 
user's computer.

**********************************
Shareware Marketing by Eldron Gill

Introduction
This document briefly explains and suggests different avenues, 
methods, and techniques available for shareware authors to 
market their software.  The primary focus is online marketing 
but there are some off-line suggestions as well.

Table Of Contents

I.        Introduction
II.       Submit Shareware To Download Sites
III.      Submit To Search Engines And Directories
IV.       Classified Ads
V.        Pop Under Ads
VI.       Pop Up Ads
VII.      Banner Ads
VIII.     Press Releases
IX.       Word of Mouth
X.        Promotional Events
XI.       Adware Options
XII.      Referral Marketing
XIII.     Testimonials 
XIV.      Business Cards
XV.       Affiliate Programs
XVI.      E-mail Marketing
XVII.     Ezine's
XVIII.    Signature's
XIX.      Discussion Lists
XX.       Reviews
XXI.      Web-Site Pressroom
XXII.     Newsletter
---------------------------------------------------------
DEMOS

*********************
DATE/TIME PICKER DEMO 
	by Brent Thorn - lbgui@aol.com

I made this little example of the calendar control that 
comes free with Windows to show it off a little.

NoMainWin
Struct icex, _
    dwSize As ulong, _
    dwICC As ulong
icex.dwSize.struct = Len(icex.struct)
icex.dwICC.struct = HexDec("100") 'ICC_DATE_CLASSES
CallDLL #comctl32, "InitCommonControlsEx", _
    icex As struct, _
    r As long
Open "DateTimePicker" For Window As #1
#1 "TrapClose [Quit]"
h1 = HWnd(#1)
CallDLL #user32, "GetWindowLongA", _
    h1 As long, _
    _GWL_HINSTANCE As long, _
    hInst As long
style = _WS_VISIBLE Or _WS_CHILD
CallDLL #user32, "CreateWindowExA", _
    0 As long, _
    "SysDateTimePick32" As ptr, _
    "DateTime" As ptr, _
    style As long, _
    20 As long, _
    50 As long, _
    120 As long, _
    20 As long, _
    h1 As long, _
    0 As long, _
    hInst As long, _
    0 As long, _
    hwndDTP As long
[Wait]
Wait
[Quit]
Close #1
End

**************
TEXT LINE-WRAP
	- by Bill Jennings

Bill has devised a clever method for breaking lines to
the length desired in a texteditor, using the
stringwidth graphics function.  Thanks for sharing, 
Bill!  See the attachment wrapText.bas included with 
this newsletter.

'   wrapText.bas

'LB3x required.
'Word wrap text in a scrollable LB textEditor
'using 'stringWidth' in a graphicbox to
'find the wrap point.
'Works with TXT files too. See [getFile].
'In addition to wrapping at the nearest space,
'the code will also wrap at hyphens, and replace
'tabs with spaces.
'   Bill Jennings, Aug 2002.


******************
COMBINING COMMANDS
	-by David Conner, mailto:lbdavid26@yahoo.com

David has added to the scripting language from issue #98.
He has made it possible to combine multiple commands on a
line and he has added some new commands.  Thanks for sharing,
David!  To avoid problems with line wraps in our email
clients, the full version of David's demo is included as
an attachement with this newsletter.

'combiningcommands.txt
I wrote this because I added on to Alyce Watson's scripter.bas 
program and made a command called goeast n.  What it does is 
goes east a number of pixels, and I am here to show how to combine 
commands in your programs.  I hope this is clear for you and you 
can understand it. The program I am using to demonstrate this is 
a SCRIPTING LANGUAGE.  To learn about these read Issue #98 of 
the Liberty BASIC Newsletter.

---------------------------------------------------------
---------------------------------------------------------
SUBMISSIONS

The Liberty BASIC Newsletter encourages all LB programmers
to submit articles for publication.  Everyone has something
valuable to say, from beginners to veteran LBers.  Consider
sharing a code routine, with explanation.  Perhaps you can
review a favorite LB website, or program, or coding tool?
Why not submit a list of questions that have been nagging
at you?  How about sharing your favorite algorithm?

---------------------------------------------------------
---------------------------------------------------------
    Comments, requests, submissions or corrections: 
Simply reply to this message, or contact a member of the team!

			The Team:
	Alyce Watson: alycewatson@charter.net
	Brad Moore: brad.moore@weyerhaeuser.com
	Tom Nally:  SteelWeaver52@aol.com
	Carl Gundel: carlg@libertybasic.com
	Bill Jennings: bbjen@bigfoot.com
---------------------------------------------------------
---------------------------------------------------------