Liberty Basic is develeopped by Carl Gundel
Original Newsletter compiled by Alyce Watson and Brosco
Translation to HTML: Raymond Roumeas

The Liberty Basic Newsletter - Issue #57 - DEC 99

© 1999, Cliff Bros and Alyce Watson All Rights Reserved

In this issue:

  1. Windows Constants
  2. What are Bits?
  3. Bitwise Operations, by Thomas Watson
  4. Boolean Truth Table, contibuted by Brad Moore
  5. Toggling Bits using Windows Contstants
  6. Window with No Titlebar

In future issues:

Using installers with your Liberty BASIC programs.


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

f 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


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

 


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


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

 


5-TOGGLING BITS USING WINDOWS CONSTANTS:

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

 


6-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:brosc-@orac.net.au or mailto:awatso-@wctc.net

---------------------------------------------------------