The ABCs of APIs Lesson 2
Using Multiple Arguments to Move a Window
Review
In Lesson 1 we learned how to make a simple API call, passing a numeric argument and retrieving a value.
Expanding Liberty BASIC
Liberty BASIC has many built-in capabilities. It can move and resize controls with the
LOCATE command. The
LOCATE command looks like this:
#1.button "!locate 200 100 120 50"
#1 "refresh"
The control is given the
LOCATE command and the window receives a
REFRESH command to cause the display to be repainted and show the new location of the control. This only works in a window of type
window. It does not work in a graphics or dialog window.
We can add this feature to other types of windows with the API function
MoveWindow.
Moving a Control by API
A single API call allows us to relocate and resize a control. It looks like this:
hButton = hwnd(#1.move) 'handle of button
calldll #user32, "MoveWindow", hButton as ulong,_
x as long, y as long, w as long, h as long,_
1 as long, result as long
This function requires
multiple arguments. In Lesson 1, we showed how to use a single argument. We can use many arguments in an API call by separating them with commas, as in this example that has 6 arguments.
Before we call the function we need to retrieve the handle of the button with
HWND() just as we described in Lesson 1. Since it is a handle, it must be passed as type
ULONG. The handle is the first argument of the
MoveWindow API call.
In Lesson 1 we said that
CALLDLL requires the statement to be on a single line, but we can break it into multiple lines with the line continuation character. That makes it easier to read and it allows us to add comments. Here is the
MoveWindow function fully commented. You can see that each of the six arguments has a specific purpose. Each argument gives a bit of information to the
MoveWindow function.
hButton = hwnd(#1.move) 'handle of button
calldll #user32, "MoveWindow",_
hButton as ulong,_ 'handle of button
100 as long,_ 'x location of button
100 as long,_ 'y location of button
200 as long,_ 'width of button
100 as long,_ 'height of button
1 as long,_ 'repaint flag, 1=yes,0=no
result as long 'nonzero = success
API Functions Can Perform Actions
In Lesson 1, we used an API call to discover the enabled state of a control. The API call gave us some information, but it did not perform an action. The
MoveWindow API moves the window or control according to the information in the arguments.
Copy the code below and paste it into Liberty BASIC, then run it. When you click the button, you'll see it move. This is done in a graphics window. Liberty BASIC doesn't have a native capability to move a control in a graphics window, so the API function extends the capabilities of Liberty BASIC.
nomainwin
WindowWidth=400:WindowHeight=400
button #1.move, "Move Button API",[moveButton],UL,10,10
open "Moving Test" for graphics_nsb as #1
#1 "down; fill cyan; flush"
#1 "trapclose [quit]"
wait
[quit] close #1:end
[moveButton]
'this code shows how to move a button
'in a graphics type window
'with the MoveWindow API function
hButton = hwnd(#1.move) 'handle of button
calldll #user32, "MoveWindow",_
hButton as ulong,_ 'handle of button
100 as long,_ 'x location of button
100 as long,_ 'y location of button
200 as long,_ 'width of button
100 as long,_ 'height of button
1 as long,_ 'repaint flag, 1=yes,0=no
result as long 'nonzero = success
wait
The x and y locations for the control are relative to the upper left corner of the window's workspace. That work space is the part of the window inside the frame and under the titlebar and menubar if there is one. It is also called the
ClientArea of the window.
The repaint flag updates the appearance of the window to show the new location of the control. If the repaint flag is passed as 0, the button may not appear to move, or it may appear in both the old and new locations, so be sure to specify a repaint flag of 1.
Moving a Window by API
Liberty BASIC allows us to specify a location and size for a window when it is created. We do this by setting
UpperLeftX UpperLeftY WindowWidth WindowHeight.
UpperLeftX = 10
UpperLeftY = 50
WindowWidth = 400
WindowHeight = 200
There is not a way to change the location or size of the window after it has been opened. The same
MoveWindow API function allows us to move a window as easily as we moved the button in the previous example.
When a Window is moved with
MoveWindow the x and y locations are relative to the upper left corner of the screen.
Here is a program that shows how to move a button with the native
LOCATE command and how to move the window with the
MoveWindow API call.
nomainwin
WindowWidth=400:WindowHeight=200
button #1.movewin, "Move Window API",[moveWindow],UL,10,10
button #1.movebtn, "Move Button LB",[moveButtonLB],UL,10,100
open "Moving Test" for window as #1
#1 "trapclose [quit]"
wait
[quit] close #1:end
[moveWindow]
'this code shows how to move the window
'with the MoveWindow API function
hWindow = hwnd(#1) 'handle of window
calldll #user32, "MoveWindow",_
hWindow as ulong,_ 'handle of window
10 as long,_ 'x location of window
10 as long,_ 'y location of window
550 as long,_ 'width of window
350 as long,_ 'height of window
1 as long,_ 'repaint flag, 1=yes,0=no
result as long 'nonzero = success
wait
[moveButtonLB]
'this code shows how to move a control
'with the native LOCATE command
#1.movebtn "!locate 200 100 120 50"
#1 "refresh"
wait
Recap
Some API calls perform actions based on the arguments they receive. Many API calls require
mulitple arguments. Arguments are the instructions for the API function. Arguments are separated by commas.
As we learned in Lesson 1, the last item in the CALLDLL statement is always the value returned by the function. The last item is not an argument. It is the return from the function.
Do it Yourself
Do you think you understand the basics of making API calls? Do you understand how
MoveWindow works? Why not write your own program that demonstrates this function? Move a control other than a button. Move a control in a dialog type window. Relocate a program window. If you can do it properly on your own, you are well on your way to mastering the skill of the API!
The next tutorial in this series will discuss the different numeric types used in API calls.