PLEASE REPLACE NEWSLETTER #57 WITH THIS CORRECTED VERSION

---------------------------------------------------------
The Liberty Basic Newsletter - Issue #57 - DEC 99
        1999, Cliff Bros and Alyce Watson
             All Rights Reserved
---------------------------------------------------------
In this issue:

Windows Constants
What are Bits?
Bitwise Operations, by Thomas Watson
Boolean Truth Table, contibuted by Brad Moore
Toggling Bits using Windows Contstants
Window with No Titlebar


In future issues:

Using installers with your Liberty BASIC programs.
---------------------------------------------------------
WINDOWS CONSTANTS:

There is no magic to Windows constants.  In API function
calls, Windows uses numeric values to interpret requests
from programmers.  Our pc does everything with numbers,
but as you surely know, we humans prefer language!  To
make it easy on us, programming languages set values
internally for these constants, giving them a "name" that
is easier for us poor humans to use and remember.

Here is an example.  We use the constant SW_HIDE in calls to
ShowWindow.  It is easy to remember to use _SW_HIDE when we
want to hide a window.  It is easy to remember to use
_SW_SHOW when we want to display a window.  It is not so 
easy to remember to use the numeric literal "0" instead
of _SW_HIDE and "5" instead of _SW_SHOW.  In addition,
these constants are given the same names in all programming
languages, so moving between languages does not require a
programmer to memorize a whole new set of constant names.

Most languages set values for these Windows constants.  In
C, they will be defined in an *.h file that must be included
in the compilation.  In Pow! their values are contained in
Definition Modules, which also must be included in the
compilation.  In Liberty BASIC, the constants are part of
the language, and are invisible to the programmer.  To use 
them, we need only place an underscore in front of the
traditional name for the desired constant.  SW_HIDE becomes
_SW_HIDE in Libery BASIC syntax.

Here is an example API call that will display the window
whose handle is passed into the call.
********************************
USING THE CONSTANT NAME:

open "user.dll" for dll as #user
h=HWND(#main)

calldll #user, "ShowWindow",_
h as word,_
_SW_SHOW as ushort,_
result As word

close #user
********************************


We may also use the actual decimal value of the constant,
as long as there is only one constant to be passed:
********************************
USING THE CONSTANT VALUE:

calldll #user, "ShowWindow",_
h as word,_
5 as ushort,_  '5 is the value for _SW_SHOW
result As word
********************************


We may also use a variable to contain the value of the
Windows constant, and pass that into the call:
********************************
SETTING THE VALUE AS A VARIABLE:

flag = _SW_SHOW
calldll #user, "ShowWindow",_
h as word,_
flag as ushort,_
result As word
********************************


We may also refer to the Windows constant by its
hexadecimal value, using the LB HEXDEC function.
This is handy, because many references list
values for Windows constants in hexadecimal format.
Liberty BASIC uses decimal numbers only, but it
has a built-in function that allows you to use
a hexadecimal number, which LB translates to its
decimal equivalent.  Remember that hexadecimal
numbers are represented by values from 0 to F.
When using this function, be sure that the
double quote marks enclose the string for the 
hexadecimal value that is being translated.
Use of the identifier "&H" is optional.
HEXDEC("&HFFD023") produces the same results as
HEXDEC("FFD023"), which is 16764963.
We must set a variable equal to this value if
we want to use the hexadecimal form:
********************************
SETTING THE VALUE AS A HEX NUMBER:

flag  = HEXDEC("&H000005") 
calldll #user, "ShowWindow",_
h as word,_
flag as ushort,_
result As word
********************************


USING MORE THAN ONE CONSTANT!
Sometimes it is necessary to combine Windows constants
for use in API calls.  One example is found in the 
function that creates a StatusBar.  We must set a
Window Style flag that combines multiple constants.
This may be done in several ways.  The way that is
most often used is the BITWISE "OR" operator. 
(See the sections on Bitwise Operations and 
Boolean Truth Table, later in this newsletter.)
We combine the desired constants by listing them 
with the word "OR" in between.  Here is an example:
********************************
MULTIPLE CONSTANTS WITH "OR":

style = _WS_VISIBLE or _WS_CHILD
calldll #cctl, "CreateStatusWindow", _
style as long, _
text$ as ptr, _
hwnd as word, _
id as word, _
stat.hwnd as word
********************************


If we want to use the decimal values, instead of the
constants' names when passing multiple constants as
a single value, we must use an arithmetic operator -
the plus sign "+" or addition operator.  (See the
section on Bitwise Operations for an example.)

The decimal value for _WS_VISIBLE is 268435456
The decimal value for _WS_CHILD is 1073741824

We add these values together in order to pass them
into an API call:

style = 268435456 + 1073741824
********************************
MULTIPLE CONSTANTS AS DECIMAL NUMBERS:

style = 268435456 + 1073741824
calldll #cctl, "CreateStatusWindow", _
style as long, _
text$ as ptr, _
hwnd as word, _
id as word, _
stat.hwnd as word
********************************


We can also pass multiple constants as hexadecimal
numbers, in much the same way.  The hexadecimal
value for _WS_VISIBLE IS hexdec("&H10000000")  and
the hexadecimal value for _WS_CHILD is hexdec("&H40000000")

********************************
MULTIPLE CONSTANTS AS HEXADECIMAL NUMBERS:

style = hexdec("&H10000000") + hexdec("&H40000000")
calldll #cctl, "CreateStatusWindow", _
style as long, _
text$ as ptr, _
hwnd as word, _
id as word, _
stat.hwnd as word
********************************


To assure yourself that the previous three
methods for passing multiple constants are 
indeed identical, run this small, sample program:

********************************
MULTIPLE CONSTANTS THREE WAYS:

style = _WS_VISIBLE or _WS_CHILD
print style

style = hexdec("&H10000000") + hexdec("&H40000000")
print style

style = 268435456 + 1073741824
print style

The output in the mainwindow will be:
1342177280
1342177280
1342177280
********************************


UNDEFINED WINDOWS CONSTANTS:
Liberty BASIC does not have values set for every
possible Windows constant that you might need.
If you try to use a constant that Liberty BASIC
does not know, your compile will be halted with
the message "Undefined Windows Constant."

If you are unsure whether Liberty BASIC has set a
value for a particular constant, just try printing
it.  This one line program

print _SW_SHOW  

will produce output in the mainwindow:

5

If you get the "Undefined Windows Constant" error,
it does not mean that you will be unable to make
the API call.  It just means that you must track
down the value - decimal or hexadecimal - of that
constant.

In our newsletter on StatusBar creation, we found
that Liberty BASIC did not recognize _SB_SETTEXT as
a valid Windows constant.  We discovered that the
actual value for this constant is 1025, so we used
that number in our api call quite successfully:

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

The first place to start your search for the values 
of undefined Windows constants might be in the
win31api.txt file or the win32api.txt file.  Both are
available on Brosco's site:  
http://users.orac.net.au/~brosco/

A search of the win31api.txt file for _WS_CHILD and
_WS_VISIBLE will retrieve this:

' Window Styles
Public Const WS_CHILD = &H40000000&
Public Const WS_VISIBLE = &H10000000&

In Liberty BASIC, we access these like so:
ws.visible = hexdec("&H10000000")
ws.child   = hexdec("&H40000000")

********************************
MULTIPLE CONSTANTS - ANOTHER METHOD:

ws.visible = hexdec("&H10000000")
ws.child   = hexdec("&H40000000")
style = ws.visible + ws.child
calldll #cctl, "CreateStatusWindow", _
style as long, _
text$ as ptr, _
hwnd as word, _
id as word, _
stat.hwnd as word
********************************

If you have access to another programming language,
you may find values for Windows constants in a search 
of the header files.  For instance, they can be found 
in the header files included with the Free C-compiler, 
LCC-Win32.

There are many reference books and software developer's
kits available also.


WARNING...WARNING...WARNING ! ! !
Some Windows constants are actually negative numbers.
Negative numbers cannot be passed directly into API 
function calls, for that will crash the program.
It does seem to be possible to pass these negative
constants directly, without problems.  It is a good
idea to treat any known negative constants as we
treat other negative numbers in API calls.  The
constant that requests a window's instance handle
is _GWW_HINSTANCE, which has a value of -6.  We
set a variable equal to the constant we want, put
together with 0 by the "OR" bitwise operator:

GWW = _GWW_HINSTANCE or 0


This works:
calldll #user, "GetWindowWord", _
    h as word, _
    _GWW_HINSTANCE as word, _
    hInstance as word

But this method might be better:
GWW = _GWW_HINSTANCE or 0
calldll #user, "GetWindowWord", _
    h as word, _
    GWW as word, _
    hInstance as word


ANOTHER WAY TO DEFINE CONSTANTS!!!
The WM_USER constant is used by applications to help 
define private messages. It has a value equal to 1024.
The numbers 0 through WM_USER - 1  (or 0 through 1023) 
are the values for messages reserved for use by Windows.  
WM_USER through 0x7FFF (or 1024 through 32767) indicate 
integer messages for use by private window classes.  
The constant we need to increment the step in a Windows
progress bar is PBM_STEPIT.  Liberty BASIC does not have
a value for this constant, so we can define its value in
terms of the _WM_USER constant.  PBM_STEPIT is actually
equal to _WM_USER + 5.

PBM.STEPIT = _WM_USER + 5 
calldll #user, "SendMessage", _
    hwndPB as word, _
    PBM.STEPIT as word, _
    0 as word, _
    0 as long, _
    re as long

Of course, we could also use the way mentioned earlier:
PBM.STEPIT = 1024 + 5
or PBM.STEPIT = 1029
calldll #user, "SendMessage", _
    hwndPB as word, _
    PBM.STEPIT as word, _
    0 as word, _
    0 as long, _
    re as long

---------------------------------------------------------
WHAT ARE BITS?

The computer uses only binary numbers.  If the pc were to 
speak to us in its native tongue, it might say something
like this:

0100 0010 0101 0010 0100 0001 0100 0100

Each of the ones and zeros represents one BIT of 
information.  The bit is SET or TRUE if its value is
"1".  It is UNSET or FALSE if its value is "0".  We can
alter instructions to the computer by operating on them
with BITWISE OPERATIONS.

In base ten numbers, the first place to the left of the
decimal point is the ones column.  The next place is
the tens column, then the hundreds column and so on.
In a base two, or binary system, the first place on the
right is the ones column.  The next place to the left
of the ones column is the twos column.  The next is
the fours column, followed by the eights column, and
so on.  Each of these 'places' may contain a 1 or a 0.
Bitwise operations consider each of these bits separately,
from two inputs and set bits accordingly in the output.

Liberty BASIC supports the Bitwise Operators:

         AND        OR          XOR

These operators take two inputs and return an output
that is a combination of the input bits.  The AND
operator sets an output bit only if that bit is set in
both inputs.  The OR operator sets a bit in the output
if either of the inputs has that bit set.  The XOR
operator sets a bit in the output if only one of the
inputs has that bit set.

---------------------------------------------------------
BITWISE OPERATIONS BY THOMAS WATSON

'Bitwise AND
'This operation sets a bit only if
'both inputs have the bit set.

print 7 and 11     ' yields 3

'16  8  4  2  1    '
'--------------    '
' 0  0  1  1  1    ' 7 in binary
' 0  1  0  1  1    ' 11 in binary
'                  '
'          ^  ^    ' These are the place values where both numbers are 1.
'                  ' Hence, 2 + 1 = 3





'Bitwise OR
'This operation sets a bit if
'either input has the bit set.

print 7 or 11      ' yields 15

'16  8  4  2  1    '
'--------------    '
' 0  0  1  1  1    ' 7 in binary
' 0  1  0  1  1    ' 11 in binary
'                  '
'    ^  ^  ^  ^    ' These are the place values where either number has a 1.
'                  ' Hence, 8 + 4 + 2 + 1 = 15





'Bitwise XOR
'This operation sets a bit only if
'exactly one of the inputs has the bit set.

print 7 xor 11     ' yields 12

'16  8  4  2  1    '
'--------------    '
' 0  0  1  1  1    ' 7 in binary
' 0  1  0  1  1    ' 11 in binary
'                  '
'    ^  ^          ' These are the place values where exactly one of the
'                  ' numbers has a 1.  Hence, 8 + 4 = 12

---------------------------------------------------------
Boolean Truth Table, contributed by Brad Moore:

Bit:              Bit:           Bit:
Input1     OP     Input2    =    Result
-------           -------        ---------
  0       AND       0              0
  0       AND       1              0
  1       AND       0              0
  1       AND       1              1


  0       OR        0              0
  0       OR        1              1
  1       OR        0              1
  1       OR        1              1


  0       XOR       0              0
  0       XOR       1              1
  1       XOR       0              1
  1       XOR       1              0

---------------------------------------------------------
TOGGLING BITS USING WINDOWS CONTSANTS:

We have used the OR operator to combine Windows constants
to achieve a Window Style.  We can use the XOR operator to 
toggle the values contained in the style of a window also.

In the following program, we want to remove the caption, or
titlebar from a window.  Since we are using a graphics 
window, we must call GetParent, and do our operations on the
parent window, because a graphic window is actually a plain
window containing a graphicbox.  When we use LB's HWND
function, we are getting the handle of the graphicbox.  We
get the handle of the parent window of the graphicbox, 
which is the handle of the entire window.

 hWnd=hWnd(#main) 'window handle is for graphicbox

 calldll #user, "GetParent",_
    hWnd as word,_
    hParent as word 'handle for entire window

Next, we obtain the current style of the window.  This is a
"long" value that is associated with the window.  We get
it with a call to GetWindowLong.  _GWL_STYLE is a negative
number, so we use the method explained earlier:

 Index = _GWL_STYLE or 0

 calldll #user,  "GetWindowLong", _
     hParent as word, _
     Index as word, _
     oldStyle as long

Now the style of the window is contained in the variable
we have called oldStyle.  We want to remove the caption
from the window, leaving the other elements of the window
style in place.  We remove the _WS_CAPTION style by 
combining the current window style with _WS_CAPTION using
the bitwise XOR operator.  In effect, we are subracting
that style constant from the style of the window:

 dwStyle = oldStyle xor _WS_CAPTION

We now have the style we want contained in the dwStyle
variable, so we change the window style with
SetWindowLong:

 calldll #user,  "SetWindowLong", _
     hParent as word, _
     Index as word, _
     dwStyle as long, _
     result as long

To see the change, we must redraw the window:

  calldll #user,"MoveWindow",_
    hParent as word,_
    UpperLeftX as word,_
    UpperLeftY as word,_
    WindowWidth as word,_
    WindowHeight as word,_
    0 as word,_
    re as void

    calldll #user,"ShowWindow",_
    hParent as word,_
    _SW_SHOW as word,_
    re as word

       ! ! ! ! ! WARNING ! ! ! ! ! 
Since we now have no 'close' button on the titlebar, we
must include a way to close the window.  We could set
a timer, if the window is to function as a simple splash
screen.  We can put any controls on the window that we
want, so we can place an EXIT button on the window.
The way it is done in this example, is to trap any
keyboard input, or a click of the right mouse button:

    print #main, "when rightButtonDown [exit]"
    print #main, "when characterInput [exit]"

       ! ! ! ! ! WARNING ! ! ! ! ! 
We must restore the original style to the window before
we end the program.  If we do not, the window's button
will remain on the Win95 taskbar until it is clicked:

[quit]
 calldll #user,  "SetWindowLong", _
     hParent as word, _
     Index as word, _
     oldStyle as long, _
     result as long

close #user
close #main
end

Here is the entire sample program:
---------------------------------------------------------
WINDOW WITH NO TITILEBAR:

' Window with NO titlebar...
'
' contributors:
' Chris Ritchie
' Brad Moore
' Brent Thorn
' Brian Pugh
' Alyce Watson

 open "user" for dll as #user
 NoMainWin


 open "" for graphics_nsb_nf as #main
    print #main, "down;fill red;backcolor red;color green"
    print #main, "place 30 50"
    print #main, "|Right click or hit any key to exit."
    print #main, "flush; setfocus"

    print #main, "when rightButtonDown [exit]"
    print #main, "when characterInput [exit]"

 hWnd=hWnd(#main)
 Index = _GWL_STYLE or 0

 calldll #user, "GetParent",_
    hWnd as word,_
    hParent as word

 calldll #user,  "GetWindowLong", _
     hParent as word, _
     Index as word, _
     oldStyle as long 'keep for exit routine

 dwStyle = oldStyle xor _WS_CAPTION

 calldll #user,  "SetWindowLong", _
     hParent as word, _
     Index as word, _
     dwStyle as long, _
     result as long

 ' set dimensions and placement --
 ' this config will center the window on screen:
 WindowWidth=336  
 WindowHeight=144 
 UpperLeftX=int((DisplayWidth -WindowWidth )/2)
 UpperLeftY=int((DisplayHeight-WindowHeight)/2)

 ' redraw window
  calldll #user,"MoveWindow",_
    hParent as word,_
    UpperLeftX as word,_
    UpperLeftY as word,_
    WindowWidth as word,_
    WindowHeight as word,_
    0 as word,_
    re as void

    calldll #user,"ShowWindow",_
    hParent as word,_
    _SW_SHOW as word,_
    re as word


input r$

[exit]
'ADDED: This gives the window its old style -
'without it, a blank button stays on the task bar.
 calldll #user,  "SetWindowLong", _
     hParent as word, _
     Index as word, _
     oldStyle as long, _
     result as long

close #user
close #main
end

---------------------------------------------------------
Newsletter compiled and edited by: Brosco and Alyce.
Comments, requests or corrections: Hit 'REPLY' now!
mailto:brosco@orac.net.au or mailto:awatson@wctc.net
---------------------------------------------------------
