|
|
![]() |
|
|
Introduction to Win32 API Programming with VARPG by Shannon O'Donnell [The code for this article is available for download.]
Visual Basic and Visual C++ programmers have known for years that to get the most functionality out of their applications, sometimes they had to dip down into the bare metal and access the Microsoft Windows APIs that make up the core operating system. As you develop more and more applications with VisualAge for RPG, you may also discover that there are certain features that you need that can only be obtained by going to the metal. The Win32 API Everything that happens in any application that runs under Microsoft Windows (in any version), including Windows itself, ultimately uses one or more Windows-32 application programming interfaces, or APIs, to perform its function. The Win32 APIs are a group of thousands of functions that allow your application total access to every aspect of the Windows environment. Win32 API functions are typically grouped together into larger objects known as Dynamic Link Libraries, or DLLs. A DLL file, in this context, is a compiled binary object that contains one or more Win32 API functions. Your VARPG application can link to the various Win32 DLL files to gain access to those lower-level APIs. What Can You Do with Win32? The following is a very short list of just some of the functionality you can achieve by accessing the Win32 APIs:
And this doesn't even begin to scratch the surface! Most of the Win32 APIs are combined in just a few common DLL files that are included as part of the Windows operating system. The following descriptions are taken from Dan Appleman's Visual Basic Programmer's Guide to the Win32 API, by Dan Appleman:
All of these APIs can be found in the Windows\System directory on Windows 95/98/ME PCs, and in the WINNT\SYSTEM32 directory on Windows NT/2000/XP systems. A VARPG Example I could write volumes about what the Win32 API is and how to understand and use it. But I'll save that for future articles. For now, let's take a look at how to use a Win32 API by looking at a simple example. In this example, we'll create a simple VARPG application that displays a VARPG Window with canvas part and a push button part and allows the user to execute the notepad.exe application from within the running VARPG application. To run the notepad.exe application, the VARPG application will link to the SHELLEXECUTE API. This Win32 API is used to execute PC commands, such as running executable files or opening Windows Explorer. To begin, create a new VARPG project and ad a Window with canvas part and a push button part. Name the Window with canvas part WIN1. Name the push button part PSBRUN and give it a label of NOTEPAD.EXE. Add a "press" event to the push button part. Next, copy the source code into your VARPG source file. The Code Let's take a look at the important pieces of the source code in a bit more detail. The first thing you'll notice is that I've defined a prototype to the SHELLEXECUTE API. Notice that the name used here is SHELLEXECUTEA. Most Win32 APIs that you'll be using have this same naming convention. Creating a prototype to the Win32 API in your VARPG application is critical to making the API work. If your prototype is incorrect, then nothing will work correctly. So the secret, then, is making sure that you use the correct API parameters and that your parameters are of the data type expected by the API. So immediately you realize that you have two problems: How do you know what the correct parameters are for a particular API, and how do you know what data type from the Win32 API maps to what VARPG data type? Actually, the solution to both answers is pretty simple. To determine the correct parameter list, go to Microsoft's Web site, at www.microsoft.com, search on that API name (or equivalent), and you'll be taken to the Microsoft Software Developers Network (MSDN) Web site, where you can find a complete description of the API in question, as well as its parameter list. Once you've found that parameter list, you can find out what data types the API is expecting for each parameter. You'll notice right off that the data types the API is expecting look nothing like the data types you've come to know in RPG. For example, you may see data types such as DWORD, TCHAR, or LONG. What the heck is that, you ask? Where are the Packed, Zoned and Character data types found in RPG? How do you know what to convert the API data type to? The solution to that is also pretty simple because I've given you table of the complete data type conversion. Simply map the API datatype to the VARPG equivalent within your VARPG prototype, and you're all set. So let's see how this works. The parameter list for the SHELLEXECUTEA API is as follows:
The keyword ByVal indicates that you will be passing data to the API by value, rather than by reference. Passing data by value means that the API gets a "copy" of the data, so the data cannot be modified. "By reference" means that the API gets an address of where the data actually resides in memory, and that the API can then modify that data, should it so desire. You will almost always pass parameters "By Value" to Win32 APIs. To indicate that a parameter is to be passed "ByVal" in your VARPG prototype, add the keyword VALUE to the parameter definition. The first thing we must do is define the API name, which is SHELLEXECUTEA in this example. Next, add a line to tell VARPG the name of the DLL file where that API can be found. In this case, the API is found in SHELL32.DLL. Finally, add a line to tell VARPG how to link to the DLL file. You'll almost always use the value *StdCall in the Linkage parameter. OK. Using our conversion table, we discover that long data types are defined as "10 0" in VARPG. In addition, we see that the hWND, which is a Hungarian notation (see, there's no end to the education process when you program in Windows!) for a Windows "handle," which is defined as an unsigned integer. In VARPG, that means that you define the parameter using the U data type. The Windows handle is a special data type in Windows that allows your application to know what window or form the current operation is for. Actually, it's a bit more complex than that, but that definition will suffice for now. The rest of the parameters are defined as STRING data types. And you can pass strings (VARPG alpha-numeric characters) to the API. However, notice that the Hungarian notation for each parameter in the API declaration is lp followed by the parameter name. This indicates to the programmer that this parameter can also be passed as a pointer data type. In general, if you can pass a pointer to a Win32 API, then do so. It will prevent problems that are hard to debug. Since the rest of the API parameters are defined as pointers, we can simply define the parameter in the APIs using an asterisk (*) in the VARPG data type field. That's it. If you've entered your code like that in the code example, you've completed defining the API prototype. The next step is to define variables for each of the prototype parameters. That's the next section of the code, which begins with the variable named hWnd. Again, you'll need to ensure that the data type for the variables matches the data type in the prototype. Define one variable for each prototype parameter. In addition, to define a pointer variable, you'll need to define a single String variable of any length, and then a pointer variable with the address pointing to the String variable. See the code for an example of how this works. Notice that the sample code initializes the lpOperation parameter to "open." This tells the SHELLEXECUTEA API to launch the default application associated with the file extension. For example, if the file extension is .exe, the Windows RUNDLL32.exe application will be automatically called to run the chosen application. If the extension of the file you want to open is .htm, the default Web browser defined for your system will open the file. Our final variable is the command that we'll execute--in this case, the notepad.exe application. On my Windows 2000 PC, that executable is found in the C:\WINNT\ directory. It may be in a different directory on your PC. Running the Application When you compile and run the application, you'll see a screen similar to the one shown in Figure 1. When you click the Notepad.exe button, the press event for that button will be fired, which will then call the ShellCmd subroutine. In this subroutine, the window handle (variable hWnd) will be set to the current VARPG window with canvas named WIN1. The CommandString work variable will have a NULL terminator attached to it, and, finally, the ShellExecute API will be called, which will open the file/program named in the CommandString variable. If the call is successful, the variable ulRc will contain a zero. If it's not successful, ulRc will contain something else and you can take appropriate action.
As you can see, when it comes time to use the Win32 API, things get pretty simple. But all the prep work that goes into finding, understanding, and defining the API can get very involved. Stick with it, and don't give up. By using the Win32 APIs, you can greatly extend the functionality of the VARPG tool and build professional and commercial-level applications.
|
Editors
Contact the Editors |
|
Last Updated: 9/26/02 Copyright © 1996-2008 Guild Companies, Inc. All Rights Reserved. |