Monday, March 5, 2012

Simple Windows API Example

When developing Windows applications one of the most useful things a person can know is how to interact with the Win32 API. By understanding these functions and hooks that Microsoft provides we are able to unleash a vast array of extra capabilities that are not yet built into the VB.NET libraries. This tutorial walks through a simple example of how to call into the Windows API.

The Windows API is a set of code libraries (DLL files) containing numerous functions for working with all aspects of Windows (graphics, the file system, fonts, low-level memory access, etc.). These function libraries are available to programmers coding with any Windows development system (VB, C++, Delphi, etc.).

While using the API is often treated as an "advanced" programming topic (and to be sure, using the API allows you to delve as deep into the depths of Windows programming as you desire), the coding to actually set up and use an API function is relatively straightforward. The basic steps are:

Declare the API sub or function with the Declare statement. The Declare statement must be coded in the general declarations section of a form or module, and can be declared with either Public or Private scope (Private only in forms). If declared as Public, any form or module in your VB.NET application can use the function; if Private, only the form or module in which it is declared can use the function. Declare any variables and constants necessary to be used as parameters with the sub or function. Call the sub or function as you would any other sub or function. (Be advised that there are some differences between calling API functions versus regular VB.NET subs and functions.)

To find the declarations and documentation necessary to use any of the 1000+ Windows API functions available, you can consult any of the numerous API Help websites. Google is of course best for searching.

Sample Program

We will now build a simple program that demonstrates the use of API functions. We will call upon the "GetComputerName" function to access the name of your computer and display it in the console winodw.

Note: On Windows XP, the name of the computer can be found by right-clicking on the My Computer icon and choosing Properties, which then displays the System Properties screen shown below. The second tab, Computer Name, shows your computer name. In this case, the name of the computer is “toshiba-user” (shown circled in red below).

image

Following is the code for the sample console application to display the computer name:

Module Module1 Private Declare Function GetComputerName _Lib "kernel32.dll" Alias "GetComputerNameA" _ ByVal lpBuffer AsString, ByRef nSize AsInteger) AsInteger Sub Main() Dim strBuffer AsString Dim intCharCount AsInteger Dim intRetVal AsInteger Const MAX_COMPUTERNAME_LENGTH AsInteger = 31 Dim strMessage AsString intCharCount = MAX_COMPUTERNAME_LENGTH strBuffer = NewString(Chr(0), intCharCount + 1) intRetVal = GetComputerName(strBuffer, intCharCount) If intRetVal <> 0 Then strMessage = "Your computer name is: " _ & strBuffer.Substring(0, intCharCount) Else strMessage = "Computer name could not be determined." EndIf Console.WriteLine(strMessage) Console.WriteLine("") Console.WriteLine("(Press Enter to close this window.)") Console.ReadLine() EndSubEnd Module

A screen-shot of the run is shown below:

image

We can analyze the code as follows. First, an explanation of the Declare statement. The Declare statement has the following general syntax:

[Public | Private] Declare Function Name Lib LibraryName [Alias AliasName] ([parameter list]) As datatype

- or -

[Public | Private] Declare Sub Name Lib LibraryName [Alias AliasName] ([parameter list])

As discussed above, the Public or Private keyword establishes the scope of the function as it will be used in your program.

As in normal VB Subs and Functions, use the Function keyword (and the corresponding As datatype clause at the end of the declaration) if the API function returns a value (in most cases, the "Function" form will be used, and the return value (datatype) will be Integer). In other cases, where the API function does not return a value, use the Sub keyword and leave off the As datatype clause.

Name specifies the name of the function as it will be used in the VB program. When the internal name of the function within the library (DLL file) is different, use the Alias clause to specify the actual internal name within the DLL.

LibraryName specifies which DLL the function can be found in.

AliasName specifies the actual internal name of the function within the Windows DLL file. The Alias clause needs to be used if the name used for Name is different. The Alias clause is useful when an internal name conflicts with a keyword (but can be used if you simply want to use a different name to call the function).

Parameter list is the comma-separated list of arguments that the function expects.

As datatype specifies the data type returned by the function. In most cases, this is a 32-bit integer specified in VB.NET as Integer. (Note: In previous versions of VB, the Integer data type was a 16-bit integer and the Long was a 32-bit integer. Thus, the return value for API functions was typically specified as Long when declaring APIs in the previous VB versions. In VB.NET, the Integer data type is now a 32-bit integer and the Long is a 64-bit integer, so we must use Integer data type to specify the return value for API functions.)

In this example, our declaration looks like this:

Private Declare Function GetComputerName Lib _"kernel32.dll" Alias "GetComputerNameA" _(ByVal lpBuffer AsString, ByRef nSize AsInteger) AsInteger

This tells the system we are looking for the GetComputerName function located in the kernel32.dll Windows system file. (The Alias clause indicates that the actual name of the function in the dll is GetComputerNameA, however, declaring the function as above, we can refer to the function as GetComputerName in our VB code.)

The arguments to this particular function are lpBuffer, which is a string that will store the computer name, and nSize which is a number (integer) that will store the number of characters contained in the computer name. (Technically, the lpBuffer argument is a “null-terminated string”, which is a string in which the trailing character(s) are the null character (ASCII code 0). The characters up to but not including the first null character represents the value of the string.)

The As Integer specification at the end of our declaration indicates that the function will be returning a Integer value. In the case of many API functions, a 32-bit Integer value will be returned to indicate the success or failure of the call.

The crux of the processing occurs in these three lines. We are setting the variable intCharCount to the value of the constant MAX_COMPUTER_LENGTH, which is set to 31. The next statement pads the variable strBuffer with 32 null characters. The actual call to the API function follows, which causes the computer name to be stored in strBuffer (in our case the result will be the string “TOSHIBA-USER” followed by 20 null characters). This is because the string “TOSHIBA-USER” contains 12 characters, and since the total length of the string is 32 characters, 20 null characters will trail at the end of the string. The function will also store the value 12 in the variable intCharCount, representing the number of characters in the name that was retrieved. The result of the function (the return value) is stored in the variable intRetVal. If the result is non-zero, the function succeeded; if zero, the function failed.

intCharCount = MAX_COMPUTERNAME_LENGTH strBuffer = NewString(Chr(0), intCharCount + 1) intRetVal = GetComputerName(strBuffer, intCharCount)

The code that follows tests the return value. If the return value is non-zero, then the call was successful, and a message containing the computer’s name is stored in the variable strMessage (the Substring method is applied to the strBuffer variable to grab its 12 leftmost characters). Otherwise, we set strMessage to indicate that the function failed. In any case, the message is then displayed on the console.

If intRetVal <> 0 Then strMessage = "Your computer name is: " _ & strBuffer.Substring(0, intCharCount) Else strMessage = "Computer name could not be determined." EndIf  Console.WriteLine(strMessage)

Download the VB Project code for the example above: VB.NET API Example

NOTE : We can use the API functions in VB.NET using the steps covered in this article. However, it must be noted that most of the functionality of Windows API has been encapsulated in Object Oriented Classes of .NET framework and many more will be added to this list of classes and functions. Therefore, it is recommend that before using an API, we must check if the similar functionality is available in .NET classes.

This article was original written by The VB Programmer.


View the original article here

No comments:

Post a Comment