# VBForums CodeBank > CodeBank - Visual Basic 6 and earlier >  [VB] Number functions: High/Low Word/Byte, Swap Words/Bytes, Bitshifting

## penagate

A DWord in Windows is 32 bytes, which is equivalent to a Long in Visual Basic. The leftmost 16 bits comprise the low word (an Integer in VB), while the the rightmost 16 bits are the high word.

Most examples use an And operation to get or set the words in a DWord. However, the quickest way to get/set the high and low word of a DWord (Double Word) is to do a direct memory move operation. To do this we need one API declaration:


VB Code:
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
    (ByRef lpvDest As Any, _
     ByRef lpvSrc As Any, _
     ByVal cbLength As Long)

And four one-line functions, made into properties for easy and logical use.

VB Code:
Public Property Get LoWord(ByRef DWord As Long) As Integer
    CopyMemory LoWord, ByVal VarPtr(DWord), 2
End Property
 Public Property Let LoWord(ByRef DWord As Long, ByVal Word As Integer)
    CopyMemory DWord, Word, 2
End Property
 Public Property Get HiWord(ByRef DWord As Long) As Integer
    CopyMemory HiWord, ByVal VarPtr(DWord) + 2, 2
End Property
 Public Property Let HiWord(ByRef DWord As Long, ByVal Word As Integer)
    CopyMemory ByVal VarPtr(DWord) + 2, Word, 2
End Property

Using them is easy, here are some useless examples:

VB Code:
Dim lDWord As Long
Dim iWord As Integer
 ' Set the low word
LoWord(lDWord) = 1
 ' Set the high word
HiWord(lDWord) = 2
 ' Get the low word
iWord = LoWord(lDWord)
 ' Get the high word
iWord = HiWord(lDWord)

Likewise, we can do the same for the high and low bytes of a Word:

VB Code:
Public Property Get LoByte(ByRef Word As Integer) As Byte
    CopyMemory LoByte, ByVal VarPtr(Word), 1
End Property
 Public Property Let LoByte(ByRef Word As Integer, ByVal LowByte As Byte)
    CopyMemory Word, LowByte, 1
End Property
 Public Property Get HiByte(ByRef Word As Integer) As Byte
    CopyMemory HiByte, ByVal VarPtr(Word) + 1, 1
End Property
 Public Property Let HiByte(ByRef Word As Integer, ByVal HighByte As Byte)
    CopyMemory ByVal VarPtr(Word) + 1, HighByte, 1
End Property

Have fun  :Smilie:

----------


## penagate

Couple of functions using the above properties to swap the words or bytes of a DWord or Word, respectively.

VB Code:
Public Function SwapWords(ByRef DWord As Long) As Long
Dim lTWord      As Integer
    lTWord = HiWord(DWord)
    HiWord(DWord) = LoWord(DWord)
    LoWord(DWord) = lTWord
    SwapWords = DWord
End Function
 Public Function SwapBytes(ByRef Word As Integer) As Integer
Dim lTByte      As Byte
    lTByte = HiByte(Word)
    HiByte(Word) = LoByte(Word)
    LoByte(Word) = lTByte
    SwapBytes = Word
End Function

----------


## penagate

Here is a bitshifting function. It is not mine, but a modified version of the one from Bruce McKinney's book Hardcore Visual Basic. If you want to read that book (He says a lot of good things so I suggest you do  :Smilie: ), the link is in my sig.


VB Code:
Public Function BitShiftWord(ByVal Word As Integer, ByVal ShiftBy As Integer) As Integer
    Dim lDWord As Long
    lDWord = Word * 2 ^ ShiftBy
    If (lDWord And &H8000&) Then
        BitShiftWord = CInt(lDWord And &H7FFF&) Or &H8000
      Else
        BitShiftWord = lDWord And &HFFFF&
    End If
End Function

Because of limitations with VB, the biggest size number that that function can handle is a Word (16 bit integer). Hopefully, an API one will follow  :Wink:

----------


## JonSea31

Can the code work with high/low numbers - for the same reason I am still awaiting an answer?

----------


## Merri

Can you clarify that question? I can't follow what you mean.


However, these code snippets by penagate aren't very fast, although not the worst I've seen either. Making API calls isn't as fast as one would think, using them for small purposes doesn't pay back.

Here are slightly different versions that work very fast compiled:

```
Public Property Get HighInteger(ByRef Value As Long) As Integer
    HighInteger = ((Value And &H7FFF0000) \ &H10000) Or (&H8000 And (Value < 0))
End Property

Public Property Let HighInteger(ByRef Value As Long, ByVal NewValue As Integer)
    Value = (Value And &HFFFF&) Or ((NewValue And &H7FFF) * &H10000) Or (&H80000000 And (NewValue < 0))
End Property

Public Property Get LowInteger(ByRef Value As Long) As Integer
    LowInteger = (Value And &H7FFF) Or (&H8000 And ((Value And &H8000&) = &H8000&))
End Property

Public Property Let LowInteger(ByRef Value As Long, ByVal NewValue As Integer)
    Value = (Value And &HFFFF0000) Or (NewValue And &HFFFF&)
End Property
```

Usage is different: these methods manipulate a value directly.

This changes the high integer part in lngValue to be 1:
HighInteger(lngValue) = 1

While this gets the current high integer:
intHigh = HighInteger(lngValue)

The same logic works with LowInteger.

----------


## penagate

Usage looks the same, but I agree (now) RtlMoveMemory is slow for small operations; best reserved for shifting large chunks of data.

----------


## Merri

I guess I somehow managed to read wrong code earlier... I also did a search for a few other ones for reference (and to confirm to myself that some pieces of code never cease to amaze...string operations are over used in wrong places).


Anyways, to continue a bit with real content, I think bitshifting is best done inline. It can with some trial and error be replicated with bitmasking (And) and multiplying, or to do it to other direction by using \ and And. Not as fast as real bitshifting, but faster than trying to replicate it in other ways, and simple enough to be done inline.

----------


## JonSea31

> Can you clarify that question? I can't follow what you mean.


Well, in another thread that I have been awaiting an answer for days but to no avail, I am wondering what command I would use if I were to use higher/lower buttons.

Here are the steps involved:

1. 2 players involved
2. A question is asked involving numbers as answers (whether general knowledge or random numbers).
3. Player guesses the number (say a players guesses "24").
4. The number (in this example, 24) is displayed in an image on that player's side (individual digits "2" then "4").
5. Opponent guesses higher or lower by clicking the corresponding "higher" or "lower" button.
6. The word "Higher" or "Lower" is displayed on that opponent's side.
7. Result is revealed a few seconds later (images of digits are used for registering the numbers and same for the result).

I apologize if it has to do with games, but for the most part it has to do with VB code, so technically this post is in the right forum.

----------


## Ellis Dee

> I apologize if it has to do with games, but for the most part it has to do with VB code, so technically this post is in the right forum.


No it isn't; this forum isn't for questions.

The "high" and "low" being discussed in this thread aren't related to the "higher" and "lower" concepts in your question.

----------

