Alyce Alyce Feb 24, 2007 - "updated text and fixed formatting"

=The ABCs of APIs Lesson 1= [[toc]] This is the first in a series of tutorials for using API calls. It covers the most fundamental information.information. Later tutorials will go into more depth. =What is an API Call?= An API call is a **function** contained in a library file, called a **Dynamic Link Library** or **DLL**. These files have an extension of "*.DLL". **DLL**. These files have an extension of "*.DLL". HereHere is an example of an API call. We can use it to determine if a window or control is enabled or disabled.disabled. [[code format="vbnet"]] CallDLL #user32, "IsWindowEnabled",_ hButton as uLong,_ 'handle of window or control result As Boolean 'nonzero = enabled [[code]] Liberty BASIC allows us to enable or disable a window or control, but there is no Liberty BASIC functionfunction to discover if a window or control is currently enabled or disabled. We can get around that limitationlimitation with this handy API function. Here is a Liberty BASIC program that makes use of the "IsWindowEnabled""IsWindowEnabled" API function. Copy it and paste it into Liberty BASIC, then run it to see how it works.works. [[code format="vbnet"]] nomainwin 'open a program window button #1.enable, "Enable/Disable",[doEnable],UL,10,10 button #1.quit, "Quit", [quit], UL, 10, 60 open "API Demo" for window as #1 #1 "trapclose [quit]" 'get the handle of the quit button hButton = HWND(#1.quit) wait [doEnable] 'The IsWindowEnabled function determines whether the 'specified window or control is enabled 'for mouse and keyboard input CallDLL #user32, "IsWindowEnabled",_ hButton as uLong,_ 'handle of window or control result As Boolean 'nonzero = enabled 'a result of 0 means that the window is NOT enabled 'a nonzero result means that the window IS enabled if result = 0 then 'if button was disabled, enable it #1.quit "!enable" else 'if bitton was enabled, disable it #1.quit "!disable" end if wait [quit] close #1 : end [[code]] =Functions= What is a function? It is a block of code that takes in an argument or a list of arguments and returns a value. That sounds a little complicated, doesn't it? It's kind of like my bread machine. I put a list of ingredients into my bread machine, including flour, yeast and water. My bread machine takes these ingredients and manipulates them, then returns a loaf of fresh-baked bread to me. a value. That sounds a little complicated, doesn't it? It's kindThe list of likeingredients can change. If I put in white flour, my bread machine.machine returns white bread. If I put a list use rye flour, it returns rye bread. If I use whole wheat flour, it returns wheat bread. ofA function accepts a list of ingredients into my bread machine, including flour, yeast and water. My bread machine takesthat we call arguments. (They can also be called parameters.) It manipulates these arguments and returns a value. Liberty BASIC has many built-in functions. Some examples of native Liberty BASIC functions are **MAX()**, **MIN()**, **INT()**, **LEFT$()**, **MID$()** and **VAL()**. ingredients and manipulates them, then returns a loaf of fresh-baked bread to me. The list of ingredients can change. If I put in white flour, my bread machine returns white bread. If I use rye flour, it returns rye bread. If I use whole wheat flour, it returns wheat bread. A function accepts a list of ingredients that we call arguments. (They can also be called parameters.) It manipulates these arguments and returns a value. Liberty BASIC has many built-in functions. Some examples of native Liberty BASIC functions are **MAX()**, **MIN()**, **INT()**, **LEFT$()**, **MID$()** and **VAL()**. APIAPI calls are functions. We give the API function a list of arguments and it returns a value, which we storestore in a variable. API functions are similar to Liberty BASIC's built-in functions, but the syntax is aa little different. API functions are accessed with the **CALLDLL** statement. =CALLDLL= The parts of the CALLDLL statement are separated by commas. We'll discuss the parts of CALLDLL in order. The first part of CALLDLL refers to the DLL to be used. Windows contains many DLLs that can be accessed in Liberty BASIC programs. order. The first part of CALLDLL refers to the DLL to be used. Windows contains many DLLs that can be accessed in Liberty BASIC programs. TheThe **CALLDLL** statement first needs to know which DLL is to be used. Many of the DLLs in Windows are recognizedrecognized by Liberty BASIC without a need to open them. We refer to them by their handles. A very commoncommon and useful DLL is called "user32.DLL". Liberty BASIC gives us a handle for this DLL. It is "#user32"."#user32". The first part of an API call to user32.dll looks like this: [[code format="vbnet"]] CALLDLL #user32, [[code]] Take note that **CALLDLL** statements must be on a single line. We often split them into multiple lines toto make them easier to read. We do this by using the underscore line continuation character as we did inin the demonstration program above. It allows us to write a statement of code on multiple lines so that wewe can add comments and avoid the need to read long lines of code, but Liberty BASIC still sees the statementstatement as a single line of code. Here is an API call on one line of code: [[code format="vbnet"]] CallDLL #user32, "IsWindowEnabled", hButton as uLong, result As Boolean [[code]] Here is the same API call broken into several lines with the underscore line continuation character. ThisThis allows us to add comments to each argument. [[code format="vbnet"]] CallDLL #user32, "IsWindowEnabled",_ hButton as uLong,_ 'handle of window or control result As Boolean 'nonzero = enabled [[code]] =API Function Names= The next part of the **CALLDLL** statement is the name of the API function. It is a text string and it mustmust be enclosed in quotation marks. The name is case sensitive, so "FunctionName" is not the same as "FUNCTIONNAME"."FUNCTIONNAME". Be sure to copy the capitalization properly. A generic CALLDLL statement looks like this:this: [[code format="vbnet"]] calldll #dll, "FunctionName",... [[code]] An actual API function called "IsWindowEnabled" looks like this: [[code format="vbnet"]] CallDLL #user32, "IsWindowEnabled",... [[code]] =API Arguments= Each API call has a set list of arguments separated by commas. Each of these arguments gives the API functionfunction some information. The function evaluates this information. It performs actions and it returns aa value based on the information in these arguments. Arguments can be literal numbers or strings, or theythey can be numeric or string variables. They **cannot** be array elements or expressions. Arguments are passed "as type". You can read more about types later in this tutorial. Acceptable arguments that use literal numbers or strings, or numeric or string variables: [[code format="vbnet"]] calldll #dll, "FunctionName", argument1 as type1,... calldll #dll, "FunctionName", 23 as type2,... calldll #dll, "FunctionName", "Some Text" as type3,... var$ = "A bit of text." calldll #dll, "FunctionName", var$ as type4,... [[code]] Some unacceptable arguments that include expressions and array elements: [[code format="vbnet"]] calldll #dll, "FunctionName", array(1) as type1,... calldll #dll, "FunctionName", 23 + 16 as type2,... calldll #dll, "FunctionName", "Some Text" + "More Text" as type3,... var$ = "A bit of text." calldll #dll, "FunctionName", var$ + "hello" as type4,... [[code]] Some API functions require many arguments. Arguements are separated by commas. A function with three argumentsarguments looks like this: [[code format="vbnet"]] calldll #dll, "FunctionName", argument1 as type1, argument2 as type2, argument3 as type3,... [[code]] In the demo for this tutorial, there is only one argument. The next tutorial will discuss API functions thatthat require multiple arguments. =Handles= Many API calls require the **Windows handle** of a program window or control as one of the arguments.Thisarguments.This Windows handle is a number of type ULONG. It is not the same as the "#handle" Liberty BASICBASIC handle. We retrieve the Windows handle with the **HWND()** function and store it in a variable. InIn this example, the variable is called "hButton". [[code format="vbnet"]] button #1.quit, "Quit", [quit], UL, 10, 60 open "API Demo" for window as #1 'get the handle of the quit button hButton = HWND(#1.quit) [[code]] =Types= API functions need to know the **type** of each argument. Arguments can be numbers, strings or structs. We will talk about numeric arguments in this tutorial. We will talk about numeric arguments in this tutorial. TheThe most common numeric types are these. Types that hold numbers that are 4 bytes in size include ulong andand long. Types that hold numbers that are 2 bytes in size include short, ushort, word and boolean. ThereThere are other types, but we won't discuss them in this tutorial. A CALLDLL statement looks like this with actual types used in the arguments: [[code format="vbnet"]] calldll #dll, "FunctionName", argument1 as ulong, argument2 as word, argument3 as long,... [[code]] =Handle Types= In Liberty BASIC, Windows handles must always be passed as either "ulong" type or "word" type. In the demonstrationdemonstration program at the start of this tutorial, the "hButton" handle is passed "as ulong". =Return Values= API functions return a value, and we must include the "as type" for that value, just as we did for the listlist of arguments. The numeric return types include ulong, long, short, word, ushort and boolean. Here is a generic call that includes the return value. The returned value is always the last part of theHere is a generic call that includes the return value. The returned value is always the last part of the **CALLDLL** statement and it is separated from the list of arguments by a comma. [[code format="vbnet"]] calldll #dll, "FunctionName", argument1 as ulong, argument2 as word, result as boolean [[code]] Note that you cannot use a variable name for the return type that is called "return" because that is a Liberty BASIC statement. Variable names cannot be the same as statement or function names in the Liberty BASIC language. Liberty BASIC programmers often use a variable name of "result" to contain the value returned by the API function. Liberty BASIC statement. Variable names cannot be the same as statement or function names in the Liberty BASIC language. Liberty BASIC programmers often use a variable name of "result" to contain the value returned by the API function. OurOur programs might need to know the value returned by the function so that they can perform the proper actions.actions. Use "if/then" to manage program flow after an API call has been made, as we've done in the demonstrationdemonstration program below. =Demo= Here again is the demonstration program. It opens a Liberty BASIC window that contains two buttons. It retrievesretrieves the handle of the Quit button with the **HWND()** function. It passes that handle into a user32.dlluser32.dll function called "IsWindowEnabled". The IsWindowEnabled function returns a value telling the programprogram whether the window or control is enabled at the time the function is called. The handle is passed as type "ulong". The return type is "boolean". A boolean value is either nonzero (meaning it is true) or zero (meaning it is false.) If IsWindowEnabled returns a value of 0, the window is not enabled. If it returns any other value than 0, the window is enabled when the function is called.The handle is passed as type "ulong". The return type is "boolean". A boolean value is either nonzero (meaning it is true) or zero (meaning it is false.) If IsWindowEnabled returns a value of 0, the window is not enabled. If it returns any other value than 0, the window is enabled when the function is called. If the quit button is enabled, the program disables it. If it is disabled, the program enables it. [[code format="vbnet"]] nomainwin 'open a program window button #1.enable, "Enable/Disable",[doEnable],UL,10,10 button #1.quit, "Quit", [quit], UL, 10, 60 open "API Demo" for window as #1 #1 "trapclose [quit]" 'get the handle of the quit button hButton = HWND(#1.quit) wait [doEnable] 'The IsWindowEnabled function determines whether the 'specified window or control is enabled 'for mouse and keyboard input CallDLL #user32, "IsWindowEnabled",_ hButton as uLong,_ 'handle of window or control result As Boolean 'nonzero = enabled 'a result of 0 means that the window is NOT enabled 'a nonzero result means that the window IS enabled if result = 0 then 'if button was disabled, enable it #1.quit "!enable" else 'if bitton was enabled, disable it #1.quit "!disable" end if wait [quit] close #1 : end [[code]] ---- ((ABCs of APIs 2|The next tutorial)) in this series will demonstrate how to use multiple arguments in anan API call to do something we can't do in Liberty BASIC. [[toc]]