Using strings in API calls from Visual Basic
Introduction
This page shows how to use strings with API calls from Visual Basic.
Example code
The example below reads the title bar text of a window.
- Using strings in API calls:
' API to make the process sleep for some milliseconds
Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)' To get and set the window caption
Private Declare Function GetWindowText Lib "user32" _ Alias "GetWindowTextA" (ByVal hWnd As Long, _ ByVal lpString As String, _ ByVal cch As Long) As Long Private Declare Function SetWindowText Lib "user32" _ Alias "SetWindowTextA" (ByVal hWnd As Long, _ ByVal lpString As String) As Long Private Declare Function GetWindowTextLength Lib "user32" _ Alias "GetWindowTextLengthA" (ByVal hWnd As Long) As Long' Get the class name
Private Declare Function GetClassName Lib "user32" _ Alias "GetClassNameA" (ByVal hWnd As Long, _ ByVal lpClassName As String, _ ByVal nMaxCount As Long) As Long' Validate the window handle
Private Declare Function IsWindow Lib "user32" _ (ByVal hWnd As Long) As Long'------------------------------------------------------------------
' Class name
Public Function GetWindowClassName(hWnd As Long) As String Dim ClsName As String Dim ClsLen As String If IsWindow(hWnd) = 0 Then Error 5 ClsLen = 128 ClsName = Space(ClsLen) ClsLen = GetClassName(hWnd, ClsName, ClsLen) GetWindowClassName = Left(ClsName, ClsLen) End Function'------------------------------------------------------------------
' Caption Property
Public Property Get WindowCaption(hWnd As Long) As String Dim CapLen As Long Dim CapBuf As String If IsWindow(hWnd) = 0 Then Error 5 CapLen = GetWindowTextLength(hWnd) + 1 CapBuf = Space(CapLen) CapLen = GetWindowText(hWnd, CapBuf, CapLen) WindowCaption = Left(CapBuf, CapLen) End Property Public Property Let WindowCaption(hWnd As Long, NewValue As String) If SetWindowText(hWnd, NewValue) = 0 Then Error 5 End Property'------------------------------------------------------------------
' Main
Public Sub Main()' This is just a sample what you can do with
' the previous functions, not a complete listing
Dim Handle As Long Dim I As Long Form1.Show Handle = Form1.hWnd DoEvents' Let Form1 draw correctly first
Debug.Print "The caption text of form1 is: " & WindowCaption(Handle) Debug.Print "The window class name is: " & GetWindowClassName(Handle) WindowCaption(Handle) = "The Caption Changes" Debug.Print "The caption text of form1 is: " & WindowCaption(Handle) For I = 1 To 3 Sleep 500 WindowCaption(Handle) = WindowCaption(Handle) & "." Next End Sub
Each windows has a unique identifier, also called the "window handle". To read the caption from a window, the GetWindowName() API needs to know the window handle in question. This value is provided with the hWnd argument.
The next next two arguments of the GetWindowName() API provide the location and size of your buffer. Unlike the previous data structures example, strings are passed by value using the ByVal keyword. Using ByVal causes Visual Basic to supply the actual value of your variable to the API function, instead of it's memory location.
The String conversion
It's interesting to note that the Windows API uses an entirely different format to store text/Strings. Visual Basic uses a so called "UNICODE BSTR" to store the text. This data-type has knowledge of the string size.
Software written in C has a different representation of a string. Often, an simple array of characters is used. The character array is terminated with a final ASCII-zero character; a CHR(0) in Visual Basic.
- Just to let you know...
The appearance of a CHR(0) character indicates a string has ended. This character is added at the end of each string (character array). Because of this extra character, buffer lengths always need to be one character longer then the actual string you like to store or receive.
Fortunately, the conversion between these data types is done automatically. If you create a string buffer, and pass it as ByVal something As String, Visual Basic converts the string to the correct type. Right before Visul Basic resumes execution, the (modified) string is copied back automatically to your string buffer.
Because the C-style string type has no real knowledge of it's length, you often need to provide the length of your string in an additional argument. This is also done to make the Windows API accessable by a lot of different higher-level programming languages. Both the GetWindowText() and GetClassName() API return the size of the actual text in the buffer. Use that size to chop off the remaining part of the string buffer.
Strings and structures
To store a String type in a structure, there are a few options. Which option you can use depends on the declaration of the structure.
- Convert it with StrConv() first.
- Create an array of Bytes, and store each character in an cell of the array. Don't forget to add a ASCII null character to the end of the string!
- Use StrPtr() to find a location of the string, and store that value as long in the structure.
blog comments powered by Disqus