HiWord, HiByte, MakeLong, etc...

JDT
03-02-2003, 10:36 PM
I have tested the following functions commonly found on the internet:
MakeInt\MakeWord
MakeLong/MakeDWord
HiByte
LoByte
HiWord
LoWord

I have listed which ones work and which ones do not. Some of these I am not sure where I found. Some were from VBSpeed and some were from the ApiGuide. And some others were from wherever.

The test I ran on LoByte, HiByte, and MakeWord/MakeInt was all the possible combinations for the low and high order byte from 0 to 255.

The test I ran on LoWord, HiWord, MakeDWord/MakeLong was all the possible combinations for the low and high order word from -32768 to 32768. The equivalent C++ macros are unsigned and do not work on negative numbers but since some of these do work on negative and positive numbers, I will call those ones good and all others bad.

When I find more I will list the results here.

JDT
03-02-2003, 10:37 PM
Here are all the ones that passed my test:'********************These are all Good**********************************

'--------------------------MakeWord-------------------------------------
Private Type T1Int
iWord As Integer
End Type
Private Type T2Byte
bLoByte As Byte
bHiByte As Byte
End Type
Public Function MakeWord(LoByte As Byte, HiByte As Byte) As Integer
Dim u2Byte As T2Byte
Dim u1Int As T1Int
u2Byte.bLoByte = LoByte
u2Byte.bHiByte = HiByte
LSet u1Int = u2Byte
MakeWord = u1Int.iWord
End Function

'=======================

'API to take two bytes and combine them into a Word
Private Declare Function MakeWord Lib "TLBINF32" Alias "makeword" ( _
ByVal low As Byte, ByVal high As Byte) As Integer

'======================

Public Function MakeWord(LoByte As Byte, HiByte As Byte) As Integer
If HiByte And &H80 Then
MakeWord = ((HiByte * &H100&) + LoByte) Or &HFFFF0000
Else
MakeWord = (HiByte * &H100) + LoByte
End If
End Function

'========================

Public Function MakeWord(LoByte As Byte, HiByte As Byte) As Integer
If HiByte And &H80 Then
MakeWord = ((HiByte * &H100&) Or LoByte) Or &HFFFF0000
Else
MakeWord = (HiByte * &H100) Or LoByte
End If
End Function

'========================

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" ( _
pDst As Any, pSrc As Any, ByVal ByteLen As Long)
Public Function MakeWord(LoByte As Byte, HiByte As Byte) As Integer
CopyMemory MakeWord, LoByte, 1&
CopyMemory ByVal VarPtr(MakeWord) + 1&, HiByte, 1&
End Function

'========================

Public Function MakeWord(ByVal bHi As Byte, ByVal bLo As Byte) As Integer
If bHi And &H80 Then
MakeWord = (((bHi And &H7F) * 256) + bLo) Or &H8000
Else
MakeWord = (bHi * 256) + bLo
End If
End Function

'=======================

Public Function MakeWord(ByVal bLow As Byte, ByVal bHigh As Byte) As Integer
MakeWord = Val("&H" & Right$("00" & Hex$(bHigh), 2) & Right$("00" & Hex$(bLow), 2))
End Function

'=======================

Public Function MakeWord(wLow As Long, wHigh As Long) As Long
MakeWord = LoByte(wLow) Or (&H100& * LoByte(wHigh))
End Function

'--------------------------HiByte-------------------------------------
Public Function HiByte(ByVal Word As Integer) As Byte
HiByte = (Word And &HFF00&) \ &H100
End Function

'=======================

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" ( _
pDst As Any, pSrc As Any, ByVal ByteLen As Long)
Public Function HiByte(ByVal Word As Integer) As Byte
CopyMemory HiByte, ByVal VarPtr(Word) + 1, 1
End Function

'======================

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" ( _
pDst As Any, pSrc As Any, ByVal ByteLen As Long)
Public Function HiByte(dwValue As Long) As Byte
CopyMemory HiByte, ByVal VarPtr(LoWord(dwValue)) + 1, 1
End Function

'=======================

JDT
03-02-2003, 10:38 PM
Here are the rest of the good ones:Public Function HiByte(ByVal wValue As Integer) As Byte
HiByte = Val("&H" & Left$(Right$("0000" & Hex$(wValue), 4), 2))
End Function

'=======================

'API to extract the high byte out of a 2 byte value
Private Declare Function HiByte Lib "TLBINF32" Alias "hibyte" ( _
ByVal Word As Integer) As Byte


'--------------------------LoByte-------------------------------------
'API to extract the low byte out of a 2 byte value
Private Declare Function LoByte Lib "TLBINF32" Alias "lobyte" ( _
ByVal Word As Integer) As Byte

'=======================

Function LoByte(w As Integer) As Byte
LoByte = w And &HFF
End Function

'=======================

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" ( _
pDst As Any, pSrc As Any, ByVal ByteLen As Long)
Public Function LoByte(ByVal Word As Integer) As Byte
CopyMemory LoByte, Word, 1
End Function

'=======================
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" ( _
pDst As Any, pSrc As Any, ByVal ByteLen As Long)
Public Function LoByte(dwValue As Long) As Byte
CopyMemory LoByte, LoWord(dwValue), 1
End Function

'=======================

Public Function LoByte(ByVal wValue As Integer) As Byte
LoByte = Val("&H" & Right$("00" & Hex$(wValue), 2))
End Function

'--------------------------HiWord-------------------------------------
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" ( _
pDst As Any, pSrc As Any, ByVal ByteLen As Long)
Public Function HiWord(dwValue As Long) As Integer
CopyMemory HiWord, ByVal VarPtr(dwValue) + 2, 2
End Function

'=======================

Public Function HiWord(lDWord As Long) As Integer
HiWord = (lDWord And &HFFFF0000) \ &H10000
End Function

'=======================

'API to extract the high word in a double word - This passed the test
'but I swear I had it fail on me before. I guess I'm crazy...
Private Declare Function HiWord Lib "TLBINF32" (ByVal DWord _
As Long) As Integer

'--------------------------LoWord------------------------------------

Public Function LoWord(lDWord As Long) As Integer
If lDWord And &H8000& Then
LoWord = lDWord Or &HFFFF0000
Else
LoWord = lDWord And &HFFFF&
End If
End Function

'=======================

'API to extract the low word in a double word
Private Declare Function LoWord Lib "TLBINF32" Alias "loword" ( _
ByVal DWord As Long) As Integer

'=======================

Function LoWord(dw As Long) As Integer
If dw And &H8000& Then
LoWord = &H8000 Or (dw And &H7FFF&)
Else
LoWord = dw And &HFFFF&
End If
End Function

'=======================
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" ( _
pDst As Any, pSrc As Any, ByVal ByteLen As Long)
Public Function LoWord(dwValue As Long) As Integer
CopyMemory LoWord, dwValue, 2
End Function

'--------------------------MakeDWord/MakeLong------------------------------------

'API to take two words and combine them into a 4 byte double word
Private Declare Function MakeLong Lib "TLBINF32" Alias "makelong" ( _
ByVal low As Integer, ByVal high As Integer) As Long

'=======================

Public Function MakeDWord(ByVal LoWord As Integer, ByVal HiWord As Integer) As Long
MakeDWord = (HiWord * &H10000) Or (LoWord And &HFFFF&)
End Function

'********************************************************************* *

JDT
03-02-2003, 10:39 PM
The rest of these all failed my test. I would not use any of them:'*************************These are all bad************************************

'Fails at low byte 0 and high byte 128
Public Function MakeInt(ByVal LByte As Byte, ByVal hByte As Byte) As Integer
MakeInt = ((hByte * &H100) + LByte)
End Function

'I found this one on the MSDN web site (I think)
'I starts to fail with low byte 128 and high byte 255
Function HiByte(ByVal w As Integer) As Byte
If w And &H8000 Then
HiByte = &H80 Or ((w And &H7FFF) \ &HFF)
Else
HiByte = w \ 256
End If
End Function

'Starts to fail at low byte 0 and high byte 128
Public Function HiByte(ByVal Word As Integer)
HiByte = Word \ &H100
End Function

'Starts to fail at low byte 1 and high byte 128
Public Function HiByte(ByVal Word As Integer)
HiByte = Word \ &H100& And &HFF&
End Function

'Fails at low word -32768 high word - 32768
Function HiWord(dw As Long) As Long
If dw And &H80000000 Then
HiWord = (dw \ 65535) - 1
Else
HiWord = dw \ 65535
End If
End Function

'Fails at low word -32768 high word - 32768.
'It does not return negative values
Public Function HiWord(ByVal dwValue As Long) As Long
Dim hexstr As String
hexstr = Right("00000000" & Hex(dwValue), 8)
HiWord = CLng("&H" & Left(hexstr, 4))
End Function

'Fails at low word -32768 high word - 32768.
'It does not return negative values
Public Function LoWord(ByVal dwValue As Long) As Long
Dim hexstr As String
hexstr = Right$("00000000" & Hex$(dwValue), 8)
LoWord = CLng("&H" & Right$(hexstr, 4))
End Function

'Fails at low word -32768 high word -32768 also fails at low word 0 high word 1
Public Function MakeDWord(ByVal LWord As Integer, ByVal HWord As Integer) As Long
MakeDWord = (HWord * &H80) Or (LWord And &H7F&)
End Function

'Starts to fail at low word -32768 high word 0
Function MakeDWord(ByVal wLo As Integer, ByVal wHi As Integer) As Long
If wHi And &H8000& Then
MakeDWord = (((wHi And &H7FFF&) * 65536) Or (wLo And &HFFFF&)) Or &H80000000
Else
MakeDWord = (wHi * 65535) + wLo
End If
End Function

'Fails at low word -32768 high word -32768
'I suspect it just does not work on negative numbers
Public Function MakeLong(wLow As Long, wHigh As Long) As Long
MakeLong = LoWord(wLow) Or (&H10000 * LoWord(wHigh))
End Function

'Fails at low word -32768 and high word -32768
'It does work on some negative numbers and possibly all positives
Public Function MakeLong(ByVal LoWord As Integer, ByVal HiWord As Integer) As Long
MakeLong = ((HiWord * &H10000) + LoWord)
End Function
'*****************************************************************

If anybody finds any errors with what I have posted here please let me know and I will correct it. If you have any to add, good or bad, please PM me so I can include them.

Merrion
03-03-2003, 02:39 AM
Rather than deriving the HiByte/Lobyte stuff from mathematical functions, why not directly peek the value at the memory address and put it into the appropriate return type e.g.:


'\\ Declarations:

Private Declare Sub CopyMemoryByte Lib "kernel32" Alias "RtlMoveMemory" (Destination As Byte, ByVal Source As Long, ByVal Length As Long)
Private Declare Sub CopyMemoryWord Lib "kernel32" Alias "RtlMoveMemory" (Destination As Integer, ByVal Source As Long, ByVal Length As Long)


'\\ --[LoByte]---------------------------------------------------------
'\\ Returns the low byte component of an integer value
'\\ Parameters:
'\\ w - The integer of which we need the loWord
'\\
'\\ -------------------------------------------------------------------
Public Function LoByte(w As Integer) As Byte

Call CopyMemoryByte(LoByte, VarPtr(w), 1)

End Function

'\\ --[LoWord]--------------------------------------------------------
'\\ Returns the low word component of a long value
'\\ Parameters:
'\\ dw - The long of which we need the LoWord
'\\
'\\-------------------------------------------------------------------
Public Function LoWord(dw As Long) As Integer

Call CopyMemoryWord(LoWord, VarPtr(dw), 2)

End Function


'\\ --[HiByte]--------------------------------------------------------
'\\ Returns the high byte component of an integer
'\\ Parameters:
'\\ w - The integer of which we need the HiByte
'\\
'\\-------------------------------------------------------------------
Public Function hiByte(ByVal w As Integer) As Byte

Call CopyMemoryByte(hiByte, VarPtr(w) + 1, 1)

End Function

'\\ --[HiWord]-------------------------------------------------------
'\\ Returns the high word component of a long value
'\\ Parameters:
'\\ dw - The long of which we need the HiWord
'\\
'\\ ------------------------------------------------------------------
Public Function HiWord(dw As Long) As Integer

Call CopyMemoryWord(HiWord, VarPtr(dw) + 2, 2)

End Function

OnErr0r
03-07-2003, 09:54 PM
Rather than deriving the HiByte/Lobyte stuff from mathematical functions, why not directly peek the value at the memory address and put it into the appropriate return type

Mainly because function calls are slower. In a vbSpeed comparison, RtlMoveMemory took over ten times as long as bitmasking to get the HighWord. Personally, I would lean towards any of the working calls JDT has posted that use bitmasking and no string manipulation.

EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum