DOCUMENT:Q145727 11-JAN-2001 [vbwin] TITLE :HOWTO: Call the Unicode Version of an API Function with VB PRODUCT :Microsoft Visual Basic for Windows PROD/VER:WINDOWS:4.0,6.0 OPER/SYS: KEYWORDS:kbAPI kbVBp kbVBp400 kbVBp500 kbVBp600 kbGrpDSVB kbDSupport ====================================================================== ------------------------------------------------------------------------------- The information in this article applies to: - Microsoft Visual Basic Learning Edition for Windows, version 6.0 - Microsoft Visual Basic Professional Edition for Windows, version 6.0 - Microsoft Visual Basic Enterprise Edition for Windows, version 6.0 - Microsoft Visual Basic Standard Edition for Windows, version 4.0 - Microsoft Visual Basic Professional Edition for Windows, version 4.0 - Microsoft Visual Basic Enterprise Edition for Windows, version 4.0 ------------------------------------------------------------------------------- SUMMARY ======= Solely declaring and calling the Unicode versions of 32-bit API functions in the same way that the ANSI versions are used will not work. This article shows one way that the Unicode version of an API function can be used without the need to create a type library. MORE INFORMATION ================ Visual Basic, like Windows NT and Windows 2000, is based internally on the double-byte Unicode standard. However, Visual Basic assumes that the world outside of itself still uses the single-byte ANSI model. Any strings passed as parameters to an external function will be converted by Visual Basic from their internal Unicode representation to an ANSI representation before the call to the function is made. In the same way, all strings that return to Visual Basic from an external function are assumed to be in an ANSI representation, and Visual Basic will attempt to make the conversion to a Unicode representation for internal use. This behavior makes it impossible to call an external function that expects or returns a Unicode string in the same way as a function that deals only with ANSI strings. One way to call a Unicode function is to create a type library referring to the Unicode function to be called, refer to this type library from within Visual Basic, and then make all calls to the Unicode function via the type library. For more information on this approach, see the text file VB4DLL.TXT or VB5DLL.Doc, located in the same directory as your Visual Basic executables. Unicode functions can also be accessed by using Visual Basic ability to create arrays of the new Byte data type. If the string(s) that are passed to and from the external function are represented in Visual Basic as byte arrays, then Visual Basic will not do any conversion when passing or receiving data to or from the outside world. The following code shows how to declare and call both the ANSI (GetWindowsDirectoryA) and Unicode (GetWindowsDirectoryW, for Wide) versions of the GetWindowsDirectory API call: Declare Function GetWindowsDirectoryA Lib "Kernel32" _ (ByVal lpBuffer As String, ByVal nSize As Long) As Long Declare Function GetWindowsDirectoryW Lib "Kernel32" _ (lpBuffer As Any, ByVal nSize As Long) As Long Sub mainA() Dim sBuf As String Dim cSize As Long Dim retval As Long sBuf = String(255, 0) cSize = 255 retval = GetWindowsDirectoryA(sBuf, cSize) sBuf = Left(sBuf, retval) Debug.Print sBuf End Sub Sub mainW() Dim Buf() As Byte, sBuf As String Dim cSize As Long Dim retval As Long ReDim Buf(254) cSize = 255 retval = GetWindowsDirectoryW(Buf(0), cSize) sBuf = Left(Buf, retval) Debug.Print sBuf End Sub The mainA() procedure makes a call to the ANSI version of GetWindowsDirectory, while the mainW() procedure does the same for the Unicode version. Both procedures output the same result, although the method they use to do so differs. The call to the ANSI version is done in the same way that has always existed for passing and returning strings to and from an external DLL. A Visual Basic string is dimensioned and padded with a certain number of spaces, and the function is called with this string and the length of the string as parameters. After the function returns, the extra spaces are stripped off of the returned string and the value is printed out. The ByVal in front of the string in the Declare for GetWindowsDirectoryA indicates that a reference to a null-terminated string should be given to the DLL, not that a copy of the Visual Basic string should be passed. The call to the Unicode version works a bit differently. In addition to dimensioning a string variable, sBuf, we also dimension a dynamic array of bytes. The ReDim statement then sizes the byte array to be 255 bytes large (indexed from 0). When GetWindowsDirectoryW is called, it is passed a reference to the first element of the byte array and the size of the array. The call fills in the Buf array with the Unicode codes for the characters representing the Windows directory and returns the number of bytes it has modified. Remember that, since the function is returning Unicode info, each character will take two bytes to store. For example, if your Windows directory is 'C:\WINNT' then Buf(0) will be 67 and Buf(1) will be 0, Buf(2) will be 58, while Buf(3) is 0, and so on. The values may differ if a non- English code page is used. The line of code immediately following the call to GetWindowsDirectoryW uses Visual Basic byte array-string coercion features to coerce the byte array into a string. When assigning a byte array to a string Visual Basic assumes that the information stored in the byte array is in a Unicode format. From then on, the sBuf variable holds a Visual Basic string representing the current Windows directory and can be manipulated as such. The example above shows how to pass an uninitialized and empty byte array to a function. A byte array initialized with some string can also be passed to an external function. For example, the following code snippet declares, initializes, and passes a byte array to a function called MyPassFunction: Dim bArray() As Byte bArray = "Hello" & vbNullChar MyPassFunction bArray(0) Additional query words: ====================================================================== Keywords : kbAPI kbVBp kbVBp400 kbVBp500 kbVBp600 kbGrpDSVB kbDSupport Technology : kbVBSearch kbAudDeveloper kbZNotKeyword6 kbZNotKeyword2 kbVB600Search kbVBA600 kbVB600 kbVB400Search kbVB400 Version : WINDOWS:4.0,6.0 Issue type : kbhowto ============================================================================= THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY. Copyright Microsoft Corporation 2001.