Emulating C Macro Functions

Level:
Level1

HiWord, LoWord, HiByte, LoByte for Microsoft Visual Basic

Many returned values from Win32 API function calls are returned as packed Longs or packed Integers. While programmers in c and Delphi have functions readily available that will unpack a long into a pair of integers or an integer into a pair of bytes, Visual Basic programmers aren't quite so fortunate. In fact, it wasn't until recently that the BYTE data type was even available to Visual Basic programmers, which forced the use of much slower string functions or the use of external libraries to handle the unpacking these values.

Below you will find four functions that will take care of the unpacking process for you. I choose to use functions since I prefer not to use temporary variables to store results. They should easily convert to subroutines if you prefer returning both HI/LO values at once.

In case you aren't up to speed on bytes and words and how they relate to integers and longs, I have included the table below to help clarify the relationships:

VB Data Type AKA Contains
Byte Byte Smallest variable type, with values ranging from 0 to 255.
Integer Word 2 bytes.
Long Double-word
(often denoted in API declarations as dwVar)
2 words, or 4 bytes.

Just because a data type has the length of a word, doesn't mean that it is a VB integer. Visual Basic only supports signed integers, which provides both negative and positive values. Other languages support unsigned integers, which support only positive numbers. Word and byte are best used when describing the amount of memory used by a particular variable. Integer and Long describe precisely what a given word or double-word contain.

Public Function LoByte(ByVal IntegerVal As Integer) As Byte
    
    LoByte = IntegerVal And &HFF&

End Function

Public Function HiByte(ByVal IntegerVal As Integer) As Byte
    If IntegerVal = 0 Then
        highbyte = 0
        Exit Function
    End If
    HiByte = IntegerVal \ &H100 And &HFF&
End Function


Public Function LoWord(ByVal LongVal As Long) As Integer
    LoWord = LongVal And &HFFFF&
End Function

Public Function HiWord(ByVal LongVal As Long) As Integer
    If LongVal = 0 Then
        HiWord = 0
        Exit Function
    End If
    HiWord = LongVal \ &H10000 And &HFFFF&
End Function

This source is, for the most part, converted directly from a Microsoft example contained in Knowledge Base article #Q160215. The code Microsoft provided is flawed, failing to account for division by 0 errors, which this code traps. The Microsoft example is implemented as a pair of subroutines, so it will be worth examining if you want to convert this example into a subroutine but aren't quite sure about where to start.

Hopefully, future versions of Visual Basic will have functions built-in that will unpack packed integers and words. The Professional Edition of BASIC (BASCOM) spanned 8 versions, and VB was at version 4 before support for a byte data type was added. Now that the base data types exists, it should just be a matter of time before they add functions to actually use them.

If you enjoyed this post, subscribe for updates (it's free)