2/22/12

Using The Win32 API Visual Basic 6 (VB6)

Ads b Google VB6 Code MSDN for VB6 API SmartCard VB6

Vis al Basic 6 (VB6)
Home Tutorials

Search

Using The Win32 API
Don't let yourself be intimidated by tales of horrific crashes and wildly complex code when faced with using the Win32 API in your Visual Basic applications. It's an easy to use and exceptionally powerful way to extend your VB projects. The API has hundreds of available functions that perform all manner of services. In most cases it's easy to use if you follow a few simple rules. It's already installed on every computer your app will run on. The only cost is a little bit of coding. I'll repeat the last point again: T . Part of the allure of Visual Basic for many beginning programmers is the nature of VB. You can quickly and easily create simple applications by drawing controls on forms and binding them together with simple tidbits of code here and there. Because of VB's visual nature, many beginners are intimidated when faced with actually having to sit down and write code. The reality of the situation, however, is that any non-trivial application will require a considerable amount of coding to make it work. There's no reason to feel overwhelmed when faced with the need to do some coding. Any API function that can be used from VB can be setup and called with a handful of lines of code. Taken in small chunks it's easy to understand and a great way to extend the features of your application as well as your programming skills. Level:

Contents
Introduction What is the API and why should I use it? Declaring API Functions A little C goes a long way with the API. Calling API Functions Many, if not most, API procedures require you to prepare the variables provided before you make the actual call. Rules for API Programming The API is not without its hazards, but if you follow a few simple guidelines you can safely use VB's greatest addon. Summary

Introduction
The Win32 Application Programming Interface (API) is probably the most powerful add-on component available for Visual Basic. Hundreds of functions are available to perform a wide variety of tasks. Unfortunately, many Visual Basic programmers do not take advantage of these powerful functions - often because of tales they may have heard of complexity, general protection faults, and other nasty but unfounded problems.

What is the API?
The API, quite simply, is the programming interface for Windows. Applications written for Windows call API functions
www.vb6.us/tutorials/using-win32-api 1/10

2/22/12

Using The Win32 API Visual Basic 6 (VB6)

to perform common windows tasks, such as creating and destroying windows, controls, and menus; accessing system services such as the display, keyboard and mouse input, and printing; and many other functions. Functions in the API are provided in several files known as Dynamic Link Libraries (DLLs). The DLLs in the Win32 API export, or make public, many of their functions which can then be called by any Windows application.

Tools for API Programming
Armed with some information, an API reference, and a few simple rules to follow, you can put the Win32 API to work for you in your Visual Basic applications. Here's what you'll need: The Win32 SDK The Win32 Software Development Kit (SDK) is a comprehensive reference to the functions available in the Win32 API. If you have VB4 or VB5 Professional or Enterprise Edition, the SDK information can be found in the MSDN version that ships with Visual Basic. MSDN (Microsoft Developer's Network) is also on the web at http://www.microsoft.com/msdn/. N :Y ' MSDN VB. The API Viewer Applet The API Viewer applet that ships with Visual Basic will provide the Declare statements you need to include in your modules before you can call API functions. An Understanding of C and Hungarion Notation While the API viewer applet will supply Declare statements that you can cut and paste into your modules, an understanding of how the functions work and the data types they use is helpful. The Declaring API Functions section will provide more information on C and Hungarian notation. A Bit of Courage and Common Sense Fear not the API, but save your work often and follow the rules. W 32,

Declaring API Functions
Calling a function in the API is a two-step process. Before making the function call from within your Visual Basic code, you must write a Declare statement so that Visual Basic knows how to call the external function. The Declare statement is comprised of several parts and looks much like a VB procedure declaration. The syntax for the Declare statement is show below. Declare template for Sub procedures: [ bi P lc Piae DcaeSbnm Lb"inm"[la "lanm" [[rls]] ] el ae i lbae Ai aisae] (agit)

Declare template for Function procedures: [ bi P lc Piae DcaeFn innm Lb"inm"[la "lanm" [[rls]][ tp] ] el c o ae i lbae Ai aisae] (agit) A e

Let's look at each of the components of these statements. Pbi o Piae lc r This is a standard VB scope modifier. Declare statements must be placed in the declarations section of a module (they cannot appear within a procedure), and the Public or Private keyword determines if the procedure is available throughout the application or only within the module in which it is declared. N R API D DcaeSbo DcaeFn in el r el c o This indicates whether or not the procedure returns a value.
www.vb6.us/tutorials/using-win32-api 2/10

: API P , API. Y . P .O P . P VB " "

2/22/12

Using The Win32 API Visual Basic 6 (VB6)

N

:Y V V B )I B

, .

.

nm ae This is the name of the function N :S .H . Lb"inm" i lbae The Lib is the name of the library (DLL) where the function is located. N :T D .T . , . . API ,(

API

Ai "lanm" la aisae The Alias is the name N :L

(rls) agit This is a standard Visual Basic argument list. It indicates what parameters are expected by the procedure, the data types of the parameters, and whether they are passed ByVal or ByRef. N G T W VB .W . A tp e Used only for functions, this specifies the data type of the return value. This may be a little easier to illustrate with an example. The following is the Declare statement for the FindWindow function. FindWindow returns a window handle given the window's title bar text or classname. PiaeDcaeFnto FnWno Lb"sr2 Ais"ididw"(_ rvt elr ucin ididw i ue3" la FnWnoA BVllCasaeA Srn,_ ya plsNm s tig BVllWnoNm A Srn)A Ln ya pidwae s tig s og Let's look at each component of this declare: Private The function is declared as Private to the module. This is because a wrapper function for the API call is provided elsewhere in the module, so the Private Declare statement ensures that only the wrapper will be called directly. Function FindWindow This procedure returns a value (a window handle). Lib "user32" Alias "FindWindowA" The procedure is exported from the user32 library, where it can be found as FindWindowA. N :T W 32 API ANSI , ANSI U "A" . .F VB, . API , , As An A A VB : GPF .

ByVal lpClassName As String, ByVal lpWindowName As String The function takes two parameters, both ByVal strings. As Long The function returns a long integer value. The FindWindow function also illustrates another common API feature: redundant parameters. FindWindow will accept a window title and a window classname, but either by itself is enough to get a window handle returned (assuming of course that such a window exists). However, to avoid needing to provide two separate functions that serve essentially the same purpose, the API has constructed the function so that either or both values can be supplied. If you only want to supply one of them (and in most cases you will), simply pass a binary zero for the other
www.vb6.us/tutorials/using-win32-api 3/10

2/22/12

Using The Win32 API Visual Basic 6 (VB6)

parameter. To pass binary zero (a null in C lingo, but not to be confused with a VB Null which is something else entirely), you can either enter ByVal 0& as the parameter value or use the intrinsic constant vbNullString.

Using the API Viewer Applet
There are hundreds of functions, constants, and structures (user defined types in VB) in the API, but it's not necessary for you to know them all. VB ships with the API Viewer applet, which can be used to cut and paste the Declare statements, constants, and type definitions for the API code you need to use into your VB modules. Using the API Viewer couldn't be easier. Simply load the appropriate library (normally win32api.txt or win32api.mdb), select either Constants, Declares, or Types from the combo box, and start typing the name you're searching for. When you find the desired code, click Add to move it to the Selected Items list and when you're done click Copy to put the code on the clipboard, ready for pasting into your VB module. N :W 32 HKEY_CURRENT_USER\S 32 . 32 . .Y F 32 . \VB . , .I API V ' VBA P S .U , \API V ,I \F ' . L \ .A

Roll Your Own Declares
The API Viewer, while convenient, is not always complete and in some cases may not be correct. Additionally, you may at times need to work with functions exported from DLLs where there is no library available to load into the API viewer. However, if you understand a little bit of the Hungarian notation used by the Win32 SDK in documenting its functions, you can easily convert most of them yourself. Converting the function name itself is fairly straightforward. If the function takes a ByVal string as one or more of it's parameters, append an "A" to the name, otherwise use the name as it appears in the SDK. This is admittedly something of a guess, but in most cases will be correct. Converting the parameter list can be a bit more difficult. However, keep in mind that nearly all API procedures are going to be expecting 32-bit long integer values for asking yourself: "How can this be?" First, with the move to 32-bit windows, nearly all parameters that were 16-bit values have been changed to 32bit values (VB long integers). Second, VB performs a little behind the scenes wizardry with string parameters. The API doesn't work with strings in the same manner as Visual Basic. API functions expect (in nearly all cases) to recieve null-terminated C strings instead of VB strings. However, you don't pass a string value to the API directly through the parameter list. Instead, you pass the address of a null-terminated string. VB handles all of this for you if you declare a parameter as a ByVal string. Rather than passing the actual string value "by value", it converts it to a nullterminated string and passes the address of that converted string. This address is, not surprisinly, a 32-bit long integer value. The API will be expecting to receive one of two things in its parameters: a value it can work with or the address of a variable containing a value it can work with. The key to knowing if the API expects a value or an address can often be found in the Hungarian notation for the parameter name in the function template listed in the SDK. If the parameter name is prefixed with "lp", it's likely that the API is going to be expecting an address. In C Hungarian notation, "lp" is shorthand for a long pointer - in other words an address in memory. The most common use is probably "lpsz" which is a long pointer to a null terminated string (a VB ByVal As String declaration), but you may also need to pass pointers to longs or user-defined types. If you need to pass an "lp" to the API for anything but a string, pass ByRef to send the address of your variable to the API. In nearly all cases, however, you will be passing values to the API - not addresses or pointers. There are a few exceptions to this: As noted above, strings are nearly always passed to the API using ByVal As String, which sends the address of a
www.vb6.us/tutorials/using-win32-api 4/10

parameter - including those listed as strings. You may be

2/22/12

Using The Win32 API Visual Basic 6 (VB6)

null-terminated string to the API. Any variable which will be modified by the function is passed ByRef. Structures (VB types) are always passed as addresses. D ' API .Y ' , ). , , .A API ( ' - ' , .I API V ' ,

Calling API Functions
Declaring the API functions you need is only half the battle, and in most cases is the easy half. Calling API functions can range from being as easy as a straight VB procedure call to requiring several or even dozens of lines of pre-call and post-call work to extract the data you need. Most calls are fairly straightforward, but there is one exceptionally common setup and teardown sequence of steps that need to happen in a large number of API calls dealing with strings. Because the API is dealing with C strings (basically just arrays of bytes or integers and nearly always terminated with a binary zero), the API will expect a few things of you before you call a function that will provide a string as part of the data it returns. Unlike VB functions, API functions will never return string values directly. If a procedure needs to return a string, it will expect you to provide a string in the parameter list and extract your result from the string variable you provided. The function itself will typically return either a status code or the length of the returned string. In all cases, the API will also expect you to make the string you supply large enough to handle the value to be returned. This is easiest to illustrate with a simple example. The following is the Declare statement for the Win32 GetComputerName function. This function will return the machine name of the computer via a string parameter. PiaeDcaeFnto GtoptraeLb"enl2 Ais"eCmueNmA (_ rvt elr ucin eCmueNm i kre3" la Gtoptrae" BVllBfe A Srn,_ ya pufr s tig nieA Ln)A Ln Sz s og s og GetComputerName takes two parameters: lpBuffer and nSize. The lpBuffer parameter is a ByVal string that will receive the computer name from the API. The nSize parameter is used to supply the API with the size of the lpBuffer string when the function is called and also receives the size of the result placed in lpBuffer by the function. If the function succeeds, it returns a non-zero value and if it fails it returns zero. Note that both parameters are being passed as pointers: the first as an "lpsz" and the second as a pointer to the long integer nSize. The following code fragment shows what a typical call to GetComputerName might look like: DmleutA Ln i Rsl s og DmsufrA Srn i Bfe s tig DmlieA Ln i Sz s og 'mk ro frtersl ae om o h eut '26sol b mr ta aeut fralpafrs 5 hud e oe hn dqae o l ltom lie=26 Sz 5 sufr=Saelie Bfe pc(Sz) 'mk tecl ae h al leut=Gtoptraesufr nie Rsl eCmueNm(Bfe, Sz) 'ts tersl et h eut I leut< 0Te f Rsl > hn 'sces ucs 'sufrcnan tenm Bfe otis h ae 'niecnan telnt o tenm ls tenl Sz otis h egh f h ae es h ul sufr=Lf$sufr nie Bfe et(Bfe, Sz)
www.vb6.us/tutorials/using-win32-api 5/10

2/22/12

Using The Win32 API Visual Basic 6 (VB6)

Es le 'tefnto fie,hnl i hr h ucin ald ade t ee EdI n f Prior to calling the function, 256 is assigned to nSize and the sBuffer string is assigned 256 spaces. (As far as I know, 256 is way more than enough characters for a legal computer name on any windows platform. The heavily padded buffer may be slightly sloppy coding, but for this purpose we're not worried about wasting a few dozen bytes in a local procedure. Once the parameters have been setup, the API function is called and the result is tested. If the value of lResult is non-zero (indicating success), then two things will be true: 1. The computer name will have been placed into the sBuffer string. 2. The nSize variable will contain the length of the computer name in sBuffer, not including the null terminator. At this point, it's a simple matter of using the Left$() function to extract everything to the left of the terminating null. Functions that return a size in the parameter list in this manner will nearly always return the required size if the buffer was too small to hold the result. You can use this information to test for a large enough buffer by comparing the value returned to the original value you provided. You can also use the "double-calling" technique, where you call once with a buffer that's known to be too small, the using the return values to allocate a buffer that's just large enough to hold the required result. Unless the procedure is in the middle of a tight loop, there's rarely a measurable performance penalty for using the double-calling method. Similarly, many functions will return string sizes as the function return value. Again, these functions will typically provide the required size if the buffer was too small to hold the result. Finally, some API functions are just plain lazy and tell you nothing at all about the size of the returned string. In these cases, you can use the InStr() function to search for the position of the first null character (use vbNullChar) and then use Left$() to extract everything to the left of the null.

Wa ning
DON'T MISMATCH THE SIZE YOU SEND AS PARAMETER WITH THE ACTUAL SIZE OF THE BUFFER! Yes, I'm shouting, and for good reason. The Win32 API expects you to do what you said you're going to do. If you tell it you provided a buffer of a given size, it will write up to that number of characters at the address provided. Consider what would happen if you did this: DmsufrA Srn i Bfe s tig DmnieA Ln i Sz s og DmleutA Ln i Rsl s og nie=24 Sz 08 sufr=Sae28 Bfe pc(4) leut=Gtoptraesufr nie Rsl eCmueNm(Bfe, Sz) If we assume for the moment that this function could return a string as long as the value of nSize, we would be in for some serious trouble. We've told the function that we're supplying a 2048 byte buffer, but in fact only allocated 248 bytes. If the function found 2048 bytes of characters to return, it would write over whatever happened to be in memory following the first 248 bytes of the string we sent. This could be other program data, program code, anything at all. If you're really, really lucky, Windows will abruptly terminate your application with a General Protection Fault. Unfortunately, it may well be the case that your application will run merrily along, having corrupted it's own code or data in some random location. This may manifest itself as strange behavior or data elsewhere, random crashes at unrelated locations, and all other sorts of nearly impossible to debug problems.
www.vb6.us/tutorials/using-win32-api 6/10

2/22/12

Using The Win32 API Visual Basic 6 (VB6)

Rules for API Programming
If you don't already have it and you plan to do much work with the Win32 API, find yourself a copy of Dan Appleman's V B P ' G W 32 API. This book is the bible of API programming, and among the things it provides is Applman's Ten Commandments for programming the API. I won't repeat them here because 1) that would be plagiarism and 2) you should buy his book anyway. However, I'll offer my own version of API programming rules, but without Appleman's more colorful Old Testament styling. 1. Save your work often. 2. Study the SDK documentation and know what you're calling before you call it. 3. Use ByVal and ByRef correctly. 4. Match sizes of string buffers and structures to the associated size parameters. 5. Save, save, save. 6. Build a VB wrapper function around any API call that requires even a single line of setup code so that you don't forget to do the setup somewhere in your app. 7. Save your work more often. You should expect to get a few crashes while debugging anything but the most trivial of API code, so don't blame me if you lose an hours work because you crashed VB and hadn't saved your code. 8. Don't confuse VB strings with C strings. 9. Don't confuse VB Nulls with C nulls. 10. Study the documentation again. Know what each parameter means, what it expects for data, and whether it is passed ByVal or ByRef. 11. Test return values explicitly. 12. Don't confuse C's TRUE and FALSE with VB's True and False. In the API, if a function states it will return TRUE if successful, test for a non-zero result. Don't compare the result to VB's True keyword. 13. Did I mention you should save your work often?

Summar
This page, like nearly every other I've ever seen on programming the API, has a few scare tactics in it. Before you shy away from the API, however, keep in mind that it's not nearly as difficult as it looks and in most cases is no harder than coding straight VB functions. The API is a powerful tool, but is intended for use by grown-ups. By this I don't mean veteran programmers, just programmers that are thorough and accurate in their coding. If you have sloppy programming habits, doing things like naming your variables "Jane" and "Spot", ignoring return values to save the line of code it takes to test them, not paying attention to ByVal or ByRef passing, then you should clean up your act before you inflict total instability on your users by adding API programming (compared to the near total instability you'll have using those habits without the API). If, however, you're willing to write a little bit of simple code and use a little bit of good judgement, the API can be the greatest add-on component available to you - and it's available for the cost of just a few lines of code. By Joe Garrick

www.vb6.us/tutorials/using-win32-api

7/10

2/22/12

Using The Win32 API Visual Basic 6 (VB6)

PDF Wri er for VB www.s nactis.com Create, displa , print, edit, merge Ro alt -free distribution. Tr now!

Similar links
Subclassing in VB6 ActiveX Tutorial Understanding the Windows API in VB Rectangular and Circular Collision Detection Using the FlashWindow API to get the users attention Creating Advanced PDF documents in VB Creating PDF files in Visual Basic Convert C Strings to VB Strings Activate Any Window With API Access Security Using Jet Data Access Objects 31342 reads

Error in code listing
wrong: lResult = GetComputerName(sBuffer, nSi e) ... sBuffer = Left$(sBuffer, nSi e) Should be: lResult = GetComputerName(sBuffer, lSi e) ... sBuffer = Left$(sBuffer, lSi e) reply

Sun, 08/28/2011 - 07:10 — Anonymous_C oward (not verified)

There is an error in the GetComputerName code. it uses "nSize" where in fact "lSize" is necessary. These lines are

Using The Win32 API to get computername
I hope a simple sample.

Wed, 01/19/2011 - 23:25 — labq.ballz

www.vb6.us/tutorials/using-win32-api

8/10

2/22/12

Using The Win32 API Visual Basic 6 (VB6)

thks. reply

Post new comment
Your name: Anonymous E-mail:
The conte nt of this fie ld is k e pt private and will not be shown publicly.

Homepage:

Subject:

Comment: *

Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> Lines and paragraphs break automatically.

More information about formatting options

Preview

Unless otherwise noted, all content on this site and in the source samples is Copyrighted © 2011 by the owner of vb6.us. All rights reserved - Contact Information
www.vb6.us/tutorials/using-win32-api 9/10

2/22/12

Using The Win32 API Visual Basic 6 (VB6)

www.vb6.us/tutorials/using-win32-api

10/10

Sign up to vote on this title
UsefulNot useful