* What is an API?
* Why to call APIs
from Visual Basic?
* How to call an
API from Visual Basic?
* How to declare an
API in Visual Basic?
* What are the data
types used in API and their counterparts in Visual Basic?
* How to send a
string to an API?
* How to use API
Viewer to get Type declarations and API declarations?
* Sample
application using APIs
* How to work with
TabStrip control?
What is an API?
API (Application Program Interface) is a
function in DLL (Dynamic link library). Windows operating system is based on a
couple of DLLs, such as Kernel32, User32, and GDI32. These APIs form the core part of Windows operating system. A
DLL is a collection of functions (APIs). DLL is loaded into memory when any of
the function is referred by an application. And once a DLL is loaded in to memory DLL remains in
memory and functions in DLL are dynamically bound to applications. That means when an application calls a function
in a DLL, the code of the function is not inserted into application (if it is
done, it is called as static linking) and instead at run time the code of
function is made available to application from DLL.
Dynamic linking is especially very
efficient in Windows operating system, as a collection of application can run
at the same time and may also use the same set of functions. So instead of
placing one copy of each function in each application, it is better to provide
one copy of functions and let all applications dynamically bind to functions.
Why to call APIs from Visual Basic?
Well, APIs are functions in DLLs and these
APIs are what applications use indirectly or directly to get the job done in
Windows OS. For instance, to show a window (a form in Visual Basic), to resize
a window or to add an item to list box Windows use APIs. All that is fine. But why should a Visual
Basic programmer worry about all this? Because you say, I add an item using AddItem method of List box and show a
form using Show method and so on.
Accepted. But that is not the entire programming.
There are tasks (as you will see later)
that you cannot accomplish just with commands of Visual Basic. You need to go
beyond Visual Basic and access these APIs to get the job done. In most of the cases a command in Visual Basic ends up calling
one of the APIs. But in some cases you do not find any command in Visual Basic
that does the job for you. In this case you need to call APIs for VB
application.
However, to call an API you need to know
everything about API. First of all you should know whether there is any API
that does the job that Visual Basic cannot do for you. Then you must know the number of parameters,
type of each parameter and the type of return value. The following are the details you should have
before you call an API.
¨
The name of API
¨
Details of Parameters such as
number of parameters and type of each parameter
¨
The library (DLL) in which API
is available
¨
What type of value the API
returns?
How to call an API from Visual Basic?
In order to call an API from VB, you have
to take two steps, they are :
¨
Declaring API using Declare Function or Declare Sub statement.
¨
Calling API just like how you
call a Visual Basic function or procedure.
Declaring an API
The first thing that you have to do to call
an API is declare it in your project. This is generally done in code module.
However, it can be done in General/Declarations of any module.
Here is the complete syntax of Declare
statement.
Declare {Function|Sub} FunctionName Lib “LibraryName”
[Alias
“Aliasname”] (Argument list)
[As Returntype]
The following sections will explain how to
use each part of the syntax.
Function or Sub
Specifies whether API returns a value or
not. If API returns a value then it is to be declared as a Function otherwise
as a Subroutine. (Sub)
FunctionName
This is the name that you want to use to
call API in your program. This name may be different from the actual name of
the API. In this case, you also have to specify Alias and give actual name as the alias.
Lib “LibraryName”
Specifies the name of the library (DLL) in
which the declared API is existing. This
indicates to Visual Basic where to look for API. The library should be
available for Visual Basic. If it is not a standard library such as Kernel32,
User32 or GDI32 then it is better you specify the complete path.
Note: Suffix 32 for a library name denotes 32-bit library. If you are
using 16-bit library, i.e. for windows 3.x then you just have to give Kernel
and not Kernel32.
Alias “AliasName”
Specifies the actual name of API when FuctionName is different from actual
name. This enables you to change the name of API in your program so that name
is more easier to call or more meaningful.
Argument List
Specifies the list of arguments (also
called as parameters). For each argument you have to specify how argument is
passed – by value or by reference, the name of argument and type of argument.
An argument is passed either by value or by
reference. When a value is passed by value, its value is passed to function and
changes made to the argument that corresponds to the parameter will not effect
the value passed. That means, for example,
if you pass variable X to a function by value then changes made by
function argument will not effect the
value of variable X. On the other hand,
if an argument is passed by reference, the reference(address) of the variable
is passed to function and as the result any changes made to argument in
function will effect the value of variable that is passed to function.
Keyword
ByVal is used to specify pass by
value and ByRef is used to specify pass by reference.
Passing Strings
For strings, ByVal means
convert a Visual Basic string to C string. It doesn’t mean that the string is
passed by value. String is always passed by reference as its address is passed
and not the value.
Also note, that when you pass a string, you
have to create required amount of space in Visual Basic string before it is
passed to an API. Because APIs use C string convention, which assumes that the
string points the location that is allocated to it.
Here
is an example:
‘ declare
a string of 255 locations
Dim st as
string * 255
‘ call
API and pass string to it
V =
APIFunction(st)
The above example can also be rewritten in
this way:
‘ Declare a normal Visual Basic string
Dim st as string
St = space (255) ‘ create space for 255 spaces
V = APIFunction (st)
Data Types used in API calls
When we deal with APIs we deal with C data
types. So we have to convert Visual Basic data types to C data types. The following table lists out the C data
types and corresponding Visual Basic data types.
C
Data Type
|
Size
|
Visual Basic Data Type |
BOOL
|
32
|
Boolean
|
BYTE
|
8
|
Byte
|
Char
|
8
|
String * 1
|
Double
|
64
|
Double
|
DWORD
|
32
|
Long
|
Float
|
32
|
Single
|
HANDLE
|
32
|
Long
|
Int
|
32
|
Long
|
Long
|
32
|
Long
|
LPTSTR
|
32
|
No equivalent
|
LPCTSTR
|
32
|
No equivalent
|
Short
|
16
|
Integer
|
UINT
|
32
|
Long
|
ULONG
|
32
|
Long
|
USHORT
|
16
|
Integer
|
UCHAR
|
8
|
String * 1
|
WORD
|
16
|
Integer
|
Table
14.1: C data types and their equivalent data types
in Visual Basic.
What is a Handle?
As long as you use Visual Basic command you
live under cover. You do not know what is really happening outside Visual
Basic. But the moment you decide to call an API, you need to understand what is
happening under the hood. Handle is one of them. VB allows you to access object
using object oriented syntax. But what’s really happening in Windows is
concealed.
Every window is assigned and identified by
a handle, which is a 32 bit number ( long integer). Windows OS identifies
windows using handle. Remember each control, such as Text box, Command button,
is also a window. These windows are called as control windows. So each control
and form has a handle using which Windows OS identifies the controls and forms.
If you ever have to take the handle of a
control or a form in Visual Basic, use hWnd
property of the form or control. This property returns the handle of the form
or control that is assigned by Windows OS.
Getting API declaration from WIN32API.TXT
When you want to get declarations of
standard APIs, you can use WIN32API.TXT text file. It contains Visual Basic
declarations for all standard APIs, constants, and Types.
Use program API Text View to load the text
file and get required declarations. API Text Viewer is an Add-in. So it is to
be first added to VBIDE.
You can run it using the following steps:
1.
Select Add-Ins menu and choose Add-In
Manager option.
2.
Visual Basic displays Add-In Manager
3.
Double click on VB 6 API Viewer to load it into VBIDE.
4.
Then click on Ok to close
Add-In Manager window. This adds API Viewer to Add-Ins menu.
5.
Now again select Add-Ins menu and select API Viewer option.
6.
API Viewer starts. It doesn’t
display anything initially.
7.
Select File-> Load Text File… option and select WIN32API.TXT file.
8.
API Viewer displays all the
function declarations form WIN32API.TXT
Sample Application
We will develop an application to display
information regarding the following in different tabs.
¨
Windows Operating system
¨
Processor and Memory
¨
Selected Disk
Each tab displays information regarding one
of the above mentioned topics. We will use TabStrip
control to displays multiple tabs.
What is TabStrip Control?
TabStrip control is used to display
multiple pages of information in one page by displaying one page at a time.
Each page is called as a tab. Each tab is like a mini-form. Each tab contains a
title. When user clicks on the title of the tab, the page that corresponds to
the tab will be displayed.
To
load TabStrip control into project:
1.
Select Project -> Components
2.
In Components dialog box, check
Microsoft Windows Common Controls 6.0.
3.
Click on OK.
When a TabStrip control is placed on the
form, it has only one tab. You need to create additional tabs, if you want,
using the following procedure.
To
create tabs in TabStrip control:
1.
Invoke property pages of
TabStrip control by selecting Properties
option in Context menu.
2.
Select Tabs tab in Property Pages.
3.
Click on Insert Tab button to add a new tab. Repeat the process for each
tab.
Note: TabStrip is not a container control. You have to use other
containers such as Frame control to place controls on Tabs of TabStrip control.
We will understand more about TabStrip
control, as we will proceed.
Designing User Interface
As I have already mentioned in this
application user interface is consisting of TabStrip control with three
different tabs. First we will create three tabs using the procedure explained
above, and then change Caption
property of first tab to "Windows
Information", second tab to "System Information" and third tab
to "Disk Information".
How
these three tabs appear at runtime, what is the information displayed in each
of these tabs and how controls are arranged.
Follow the steps given below to create
required controls:
Create a Frame and change the following
properties
Name Frames
Caption ""
(Null string)
Index 1
Index property is used to create a control array. Control array concept
explained in chapter 8. A control array is a collection of controls that have
the same name but different values for Index
property. For all controls in a control array there is only one event procedure
for each event.
Place second frame and change the following
properties.
Name Frames
Index 2
Caption ""
(Null string)
Place one more frame (third frame) and
change the following properties.
Name Frames
Index 3
Caption ""
(Null string)
Adding Control to Frames
After frames are added, place required
controls on each frame.Layout of the
controls, Most of the controls are Labels. We set BorderStyle property to
1-Fixed Single for labels that display the values.
However, in third frame (Disk information),
we have to place a DriveListbox control,
which allows user to select the drive for which the user wants to get details.
Adding a module to contain API declarations
Generally we place all API declarations in
a code module. Now we add a code module to the project using Project -> Add Module.
Add the Type declarations shown in table
14.2 using API Viewer.
To
get the Type declaration from API Viewer, do the following:
1.
Load Win32Api.txt using File-> Load Text File…
2.
Select Types in API Types dropdown list box.
3.
Select one type at a time and
click on Add button to add the Type
declaration to Selected Items.
4.
Repeat the process until all
types listed in table 14.2 are added.
At the end of the above process all three
Type declarations should be copied to General/Declarations of the code module,
as shown in listing 14.1.
Here is the list of Types taken from API
Viewer and what they contain.
Type
|
Meaning |
MEMORYSTATUS
|
Contains
fields that return the information regarding total physical memory, available
memory etc.
|
SYSTEM_INFO
|
Contains
fields that return information regarding number of processors, type of
processor etc.
|
OSVERSIONINFO
|
Contains
fields that return information regarding platform id, major and minor version
etc.
|
Table
14.2: Type declarations required for sample
application.
Add API declarations for the APIs listed in
table 14.3 using API Viewer.
To
add API declarations, do the following:
1.
Select Declares in API Type
dropdown list box.
2.
Select each function listed in
table 14.3 and click on Add button
to send its declaration to Selected Items.
To
transfer selected items to code module in Visual Basic project:
1.
Once all Types and Declarations
are copied to Selected Items, click on Copy
button to copy selected items to clipboard.
2.
Then activate code module
in Visual Basic project and select General/Declarations.
3.
Choose Edit->Paste in VB IDE to paste Type declarations and API
declarations that are copied into clipboard, into code module.
Public Type MEMORYSTATUS
dwLength As Long
dwMemoryLoad As Long
dwTotalPhys As Long
dwAvailPhys As Long
dwTotalPageFile As Long
dwAvailPageFile As Long
dwTotalVirtual As Long
dwAvailVirtual As Long
End Type
Public
Type SYSTEM_INFO
dwOemID As Long
dwPageSize As Long
lpMinimumApplicationAddress As Long
lpMaximumApplicationAddress As Long
dwActiveProcessorMask As Long
dwNumberOrfProcessors As Long
dwProcessorType As Long
dwAllocationGranularity As Long
dwReserved As Long
End Type
Public
Type OSVERSIONINFO
dwOSVersionInfoSize As Long
dwMajorVersion As Long
dwMinorVersion As Long
dwBuildNumber As Long
dwPlatformId As Long
szCSDVersion As String * 128 'Maintenance string for PSS usage
End Type
Public Declare Function GetWindowsDirectory Lib "kernel32" Alias "GetWindowsDirectoryA" (ByVal
lpBuffer As String, ByVal nSize As Long) As Long
Public Declare Function GetTempPath Lib "kernel32" Alias "GetTempPathA"
(ByVal nBufferLength As Long, ByVal lpBuffer As String) As Long
Public Declare Sub GetSystemInfo Lib
"kernel32" (lpSystemInfo As SYSTEM_INFO)
Public Declare Function GetUserName Lib "advapi32.dll" Alias
"GetUserNameA" (ByVal lpBuffer As String, nSize As Long) As Long
Public Declare Function GetComputerName Lib "kernel32" Alias
"GetComputerNameA" (ByVal lpBuffer As String, nSize As Long) As Long
Public Declare Function GetDiskFreeSpace Lib "kernel32" Alias
"GetDiskFreeSpaceA" (ByVal lpRootPathName As String,
lpSectorsPerCluster As Long, lpBytesPerSector As Long, lpNumberOfFreeClusters
As Long, lpTotalNumberOfClusters As Long) As Long
Public Declare Function GetVersionEx Lib "kernel32" Alias
"GetVersionExA" (lpVersionInformation As OSVERSIONINFO) As Long
Public Declare Function GetVolumeInformation Lib "kernel32" Alias
"GetVolumeInformationA" (ByVal lpRootPathName As String, ByVal
lpVolumeNameBuffer As String, ByVal nVolumeNameSize As Long,
lpVolumeSerialNumber As Long, lpMaximumComponentLength As Long,
lpFileSystemFlags As Long, ByVal lpFileSystemNameBuffer As String, ByVal
nFileSystemNameSize As Long) As Long
Public Declare Sub GlobalMemoryStatus Lib "kernel32" (lpBuffer As
MEMORYSTATUS)
Public Declare
Function GetDriveType Lib
"kernel32" Alias "GetDriveTypeA" (ByVal nDrive As String)
As Long
Listing 14.1: Type
declarations and API declarations.
Here is the
list of functions used in the sample application and what they do?
API
|
Meaning |
GetWindowsDirectory
|
Returns the
name of the directory into which Windows OS is installed.
|
GetTempPath
|
Returns path
for temporary directory (temp).
|
GetSystemInfo
|
Returns
information regarding system into a variable of SYSTEM_INFO type.
|
GetUserName
|
Returns the
name of the current user.
|
GetComputerName
|
Returns the
name of the computer.
|
GetDiskFreeSpace
|
Returns the
space details of the given disk.
|
GetVersionEx
|
Returns
details regarding windows version into a variable of type OSVERSIONINFO.
|
GetVolumeInformation
|
Returns the
details of the specified volume.
|
GlobalMemoryStatus
|
Returns
memory statistics into a variable of type MEMORYSTATUS.
|
GetDriveType
|
Returns the
type of the specified drive.
|
Table 14.3: APIs used in
the sample application.
Writing code to get required information
Write three
user-defined functions, GetSystemInformation,
GetDiskInformation, and GetWindowsInformation. These user-defined functions call APIs and
get the required information. These functions also populate corresponding
labels with the required information. Listing 14.2 shows the code for these
three user-defined functions.
Public
Sub GetWindowsInformation()
Dim winfo
As OSVERSIONINFO
Dim wdir As String * 255
Dim wlen As Long
' get
windows platform
wlen =
GetWindowsDirectory(wdir, 255)
lblwindir.Caption = Left(wdir, wlen)
wlen =
GetTempPath(255, wdir)
' get
lbltemppath.Caption = Left(wdir, wlen)
winfo.dwOSVersionInfoSize = Len(winfo)
wlen =
GetVersionEx(winfo)
With
winfo
If
.dwPlatformId = 0 Then
lblwinplatform.Caption = "Windows 3.X"
ElseIf .dwPlatformId = 1 Then
lblwinplatform.Caption = "Windows 95"
ElseIf .dwPlatformId = 2 Then
lblwinplatform.Caption = "Windows NT"
Else
lblwinplatform.Caption = "Unknown"
End
If
lblversion.Caption = .dwMajorVersion & "." &
.dwMinorVersion
End
With
End Sub
Public
Sub GetSystemInformation()
Dim sinfo As SYSTEM_INFO
Dim minfo As MEMORYSTATUS
Dim slen
As Long
Dim cname As String * 100
Dim rcode As Long
'
call API to get information
GetSystemInfo sinfo
With
sinfo
lblprocessor.Caption = .dwProcessorType
End
With
' get
memory information
minfo.dwLength = Len(minfo)
GlobalMemoryStatus minfo
With
minfo
lbltotalmemory.Caption = .dwTotalPhys
lblfreememory.Caption = .dwAvailPhys
lblutilization.Caption = .dwMemoryLoad
End
With
' get
computer name
slen
= 100
rcode
= GetComputerName(cname, slen)
lblcomputername.Caption = Left(cname, slen)
' get
current user name
slen
= 100
rcode
= GetUserName(cname, slen)
lblcuruser.Caption = Left(cname, slen)
End Sub
Private
Sub Drive1_Change()
GetDiskInformation Left(Drive1.drive, 1) & ":\"
End Sub
Private
Sub Form_Load()
x =
TabStrip1.Left + 40
Y =
TabStrip1.Top + 300
For
i = 1 To 3
frames(i).Visible = False
frames(i).Move x, Y, TabStrip1.Width, TabStrip1.Height - 300
Next
frames(1).Visible = True
'
get the information
GetWindowsInformation
GetSystemInformation
'
get current drives information
GetDiskInformation Left(CurDir, 3)
End Sub
Private
Sub TabStrip1_Click()
'
make all frames invisible
For
i = 1 To 3
frames(i).Visible = False
Next
'
make the selected frame visible
frames(TabStrip1.SelectedItem.Index).Visible = True
End Sub
Public
Sub GetDiskInformation(drive As String)
Dim vname As String * 100
Dim vserial As Long
Dim mcl As Long
Dim vfsys As Long
Dim vfsysname As String * 100
Dim x As Long
Dim dtype As Long
Dim dt As String
' get
volume information
x =
GetVolumeInformation(drive, vname, 100, vserial, mcl, _
vfsys, vfsysname,
100)
lblvolume.Caption = vname
lblserial.Caption = vserial
lblFilesystem.Caption = vfsysname
'
get disk information
x =
GetDiskFreeSpace(drive, nspc, bps, fc, tnc)
lblsectors.Caption = nspc
lblbytespersector.Caption = bps
lblfreeclusters.Caption = fc
lblclusters.Caption = tnc
'
get drive type
dtype = GetDriveType(drive)
Select Case dtype
Case 0
dt = "Unknown"
Case 1
dt = "Not Available"
Case 2
dt = "Removable"
Case 3
dt = "Fixed"
Case 4
dt = "Remote"
Case 5
dt = "CDROM"
Case 6
dt = "RAM Disk"
End
Select
lbldrivetype.Caption = dt
End
Sub
Listing 14.2: Code for
Sample application.
When you run the project, you will see the first
tab (Windows Information) as we have shown that in Load event of the form. Whenever user clicks on any other tab, Click event of TabStrip control occurs.
We take Index of the selected
item tab and use that index to display the frame that has the same index. See
the code for Click event of TabStrip1 (see listing 14.1) for complete code.
Whenever user selects a different drive
letter in DriveListBox of Disk Information tab, we invoke GetDiskInformation
by sending the name of the selected drive.
The ability to call an API from Visual
Basic application is a very important facility. In several cases you find that
what you want, cannot be done in Visual Basic and you need to call an API. What
we have seen in our sample application is a tiny list of APIs. There are
thousands of APIs. Try to understand as many APIs as possible. Because, using
APIs you can push limits.
No comments:
Post a Comment