Page 1 of 1

Function lib: FormatDword.ahk - HIWORD(), LOWORD(), MAKELONG()

Posted: 20 Mar 2019, 11:08
by megnatar
These functions do exactly the same as the macros found on the MSDN links below.
They can be used with OnMessage() to format something like coordinates from LParam.
Ore format any other 32Bit integer structured as low high bit order.

HIWORD:
LOWORD:
MAKELONG:

EXAMPLE:
Return Highword as hexadecimal.
HIWORD(0x3200258,1)

Return Low Word as integer.
LOWORD(0x3200258)

Return Dword as hexadecimal. The LOWORD and HIWORD parameters
need to be 16bit Integers!
MAKELONG(600,800, 1)

This table might help to make some sense from all of this.
._________________________________________.
|_1_______8|9______16|17_____24|25______32||
|11 00 10 00.00 00 00 00.10 01 01 10.00 00 10 00|| = 32 bits.
|31_8bit___|_8bit_____|_8bit_____|_8bit____ 0|| -> Bit 0-31.
| __msb___+_next_msb|_next_lsb_+_lsb_______|| Most and Least Significant Bit.
| __BYTE4_+_BYTE3___+_BYTE2___+_BYTE1____|| = 4 Byte / 4x8 bit.
| _____HIWORD_______|_____LOWORD________|| = 2 Word / 2x16 bit
| ________________DWORD__________________|| = 1 Dword = 2 Word = 4 Byte = 1x32 bit.
.

Download below:
FormatDword.ahk
FormatDword Function library
(1.67 KiB) Downloaded 131 times
.

Code: Select all

; Return the first two bytes in a 32 bit integer. MSB
HIWORD(Dword,Hex=0){
    BITS:=0x10,WORD:=0xFFFF
    return (!Hex)?((Dword>>BITS)&WORD):Format("{1:#x}",((Dword>>BITS)&WORD))
}

; Return the second two bytes in a 32bit Integer. LSB
LOWORD(Dword,Hex=0){
    WORD:=0xFFFF
    Return (!Hex)?(Dword&WORD):Format("{1:#x}",(Dword&WORD))
}

; Combine two WORD, to make one DWORD.
MAKELONG(LOWORD,HIWORD,Hex=0){
    BITS:=0x10,WORD:=0xFFFF
    return (!Hex)?((HIWORD<<BITS)|(LOWORD&WORD)):Format("{1:#x}",((HIWORD<<BITS)|(LOWORD&WORD)))
}

/* <-- Remove ore comment out this line, then run the script to test it!

Dword := 0x3200258
MsgBox % "Integer`t`t`tHexadecimal`n"
. "-----------------------------------------`n"
. "" HIWORD(Dword)  "`t`t`t" HIWORD(Dword, 1) "`n"
. "" LOWORD(Dword)  "`t`t`t" LOWORD(Dword, 1) "`n"
. "" MAKELONG(LOWORD(Dword), HIWORD(Dword))   "`t`t`t" MAKELONG(LOWORD(Dword), HIWORD(Dword) , 1)  "`n`n"
. "X = " HIWORD(Dword) "`n"
. "Y = " LOWORD(Dword) "`n"

Re: Function lib: FormatDword.ahk - HIWORD(), LOWORD(), MAKELONG()

Posted: 20 Mar 2019, 18:11
by DRocks
Very nice... This has been a mystery for me and this is really helpful. Thank you

Re: Function lib: FormatDword.ahk - HIWORD(), LOWORD(), MAKELONG()

Posted: 20 Mar 2019, 19:36
by megnatar
Your welcome :)

Re: Function lib: FormatDword.ahk - HIWORD(), LOWORD(), MAKELONG()

Posted: 21 Mar 2019, 03:58
by just me
  • minwindef.h wrote:

    Code: Select all

    #define MAKELONG(a, b)      ((LONG)(((WORD)(((DWORD_PTR)(a)) & 0xffff)) | ((DWORD)((WORD)(((DWORD_PTR)(b)) & 0xffff))) << 16))
  • Windows Data Types wrote:

    Code: Select all

    LONG			A 32-bit signed integer. The range is -2147483648 through 2147483647 decimal.
  • AHK stores all integer values as signed 64-bit integers.

My suggestion:

Code: Select all

MAKELONG(LOWORD, HIWORD, Hex := False) {
   ; WORD = 2 bytes = 16 bits
   LONG := (LOWORD & 0xFFFF) | ((HIWORD & 0xFFFF) << 16)
   Sign := (LONG & 0x80000000) ? (Hex ? "-" : -1) : (Hex ? "" : 1)
   Return (Hex ? Format(Sign . "0x{:08X}", LONG) : (LONG * Sign))
}

Re: Function lib: FormatDword.ahk - HIWORD(), LOWORD(), MAKELONG()

Posted: 21 Mar 2019, 05:29
by DRocks
Im sorry but I am not advanced enough to follow but really need to understand Dword LoWord and Hiword.

What does the suggestion you proposed imply just me, please? What does it mean?

Re: Function lib: FormatDword.ahk - HIWORD(), LOWORD(), MAKELONG()

Posted: 21 Mar 2019, 08:22
by wolf_II
I am sorry to sqeeze in. I am also struggling with the same question.
This is where I found the difference: (after rewriting so I can follow what the algorithm is doing.)

modified:

Code: Select all

MsgBox, % myLong32 := makeLONG(12, -42, True)
MsgBox, % LOWORD(myLong32)



;-------------------------------------------------------------------------------
makeLONG(LOWORD, HIWORD, Hex := False) { ; return DWORD (32 bits)
;-------------------------------------------------------------------------------
    ; LOWORD, HIWORD: each has 2 bytes = 16 bits

    local Long := (LOWORD & 0xFFFF) | (HIWORD & 0xFFFF) << 16
    local Sign := (Long & 0x80000000) ? (Hex ? "-" : -1) : (Hex ? "" : 1)
    return Hex ? Format(Sign "0x{:08X}", Long) : (Sign * Long)
}



;-------------------------------------------------------------------------------
HIWORD(DWORD_32, Hex := False) { ; return first 16 bits of a 32-bit integer
;-------------------------------------------------------------------------------
    local Result := (DWORD_32 >> 16) & 0xFFFF
    return Hex ? Format("0x{:04X}", Result) : Result
}



;-------------------------------------------------------------------------------
LOWORD(DWORD_32, Hex := False) { ; return second 16 bits of a 32-bit integer
;-------------------------------------------------------------------------------
    local Result := DWORD_32 & 0xFFFF
    return Hex ? Format("0x{:04X}", Result) : Result
}
Result: 65524 (-12 in hex with 16 digits)

original:

Code: Select all

MsgBox, % myLong32 := makeLONG(12, -42, True)
MsgBox, % LOWORD(myLong32)



; Return the first two bytes in a 32 bit integer. MSB
HIWORD(Dword,Hex=0){
    BITS:=0x10,WORD:=0xFFFF
    return (!Hex)?((Dword>>BITS)&WORD):Format("{1:#x}",((Dword>>BITS)&WORD))
}

; Return the second two bytes in a 32bit Integer. LSB
LOWORD(Dword,Hex=0){
    WORD:=0xFFFF
    Return (!Hex)?(Dword&WORD):Format("{1:#x}",(Dword&WORD))
}

; Combine two WORD, to make one DWORD.
MAKELONG(LOWORD,HIWORD,Hex=0){
    BITS:=0x10,WORD:=0xFFFF
    return (!Hex)?((HIWORD<<BITS)|(LOWORD&WORD)):Format("{1:#x}",((HIWORD<<BITS)|(LOWORD&WORD)))
}
Result: 65535 (-1 in hex with 16 digits)

The original code returns -1 => wrong.
Just me's mod returns -12 => also wrong.
???

Re: Function lib: FormatDword.ahk - HIWORD(), LOWORD(), MAKELONG()

Posted: 21 Mar 2019, 17:36
by wolf_II
my previous attempt was wrong.
2nd attempt: a modification without sign ???

Code: Select all

MsgBox, % myLong32 := makeLONG(12, -42) ; 0xFFD6000C
MsgBox, % LOWORD(myLong32, 0)           ; 12
MsgBox, % HIWORD(myLong32, 0)           ; 65494



; LOWORD, HIWORD: each has 2 bytes = WORD = 16 bits
; makeLONG => LONG = DWORD = 32 bits



;-------------------------------------------------------------------------------
makeLONG(LOWORD, HIWORD, Hex := True) { ; return DWORD (32 bits)
;-------------------------------------------------------------------------------
    local LONG := (HIWORD & 0xFFFF) << 16 | (LOWORD & 0xFFFF)
    return Hex ? Format("0x{:08X}", LONG) : LONG
}



;-------------------------------------------------------------------------------
HIWORD(DWORD, Hex := True) { ; return first 16 bits of a 32-bit integer (MSB)
;-------------------------------------------------------------------------------
    local HIWORD := (DWORD >> 16) & 0xFFFF
    return Hex ? Format("0x{:04X}", HIWORD) : HIWORD
}



;-------------------------------------------------------------------------------
LOWORD(DWORD, Hex := True) { ; return second 16 bits of a 32-bit integer (LSB)
;-------------------------------------------------------------------------------
    local LOWORD := DWORD & 0xFFFF
    return Hex ? Format("0x{:04X}", LOWORD) : LOWORD
}
same test with orig code:

Code: Select all

MsgBox, % myLong32 := makeLONG(12, -42, 1)  ; 0xFFFFFFFFFFD6000C
MsgBox, % LOWORD(myLong32)                  ; 65535
MsgBox, % HIWORD(myLong32)                  ; 65535



; Return the first two bytes in a 32 bit integer. MSB
HIWORD(Dword,Hex=0){
    BITS:=0x10,WORD:=0xFFFF
    return (!Hex)?((Dword>>BITS)&WORD):Format("{1:#x}",((Dword>>BITS)&WORD))
}

; Return the second two bytes in a 32bit Integer. LSB
LOWORD(Dword,Hex=0){
    WORD:=0xFFFF
    Return (!Hex)?(Dword&WORD):Format("{1:#x}",(Dword&WORD))
}

; Combine two WORD, to make one DWORD.
MAKELONG(LOWORD,HIWORD,Hex=0){
    BITS:=0x10,WORD:=0xFFFF
    return (!Hex)?((HIWORD<<BITS)|(LOWORD&WORD)):Format("{1:#x}",((HIWORD<<BITS)|(LOWORD&WORD)))
}

Re: Function lib: FormatDword.ahk - HIWORD(), LOWORD(), MAKELONG()

Posted: 22 Mar 2019, 04:48
by just me
Hi,

you have to consider the used Windows Data Types:

  • #define MAKELONG(a, b) ((LONG)(((WORD)(((DWORD_PTR)(a)) & 0xffff)) | ((DWORD)((WORD)(((DWORD_PTR)(b)) & 0xffff))) << 16))
    Returns a LONG - A 32-bit signed integer.
  • #define LOWORD(l) ((WORD)(((DWORD_PTR)(l)) & 0xffff))
    Returns a WORD - A 16-bit unsigned integer.
  • #define HIWORD(l) ((WORD)((((DWORD_PTR)(l)) >> 16) & 0xffff))
    Returns a WORD - A 16-bit unsigned integer.

Re: Function lib: FormatDword.ahk - HIWORD(), LOWORD(), MAKELONG()

Posted: 22 Mar 2019, 05:10
by jNizM
An old example I found for HIBYTE / LOBYTE / HIWORD / LOWORD

Code: Select all

GetVersion()
{
	return { 1 : LOBYTE(LOWORD(DllCall("GetVersion")))
		   , 2 : HIBYTE(LOWORD(DllCall("GetVersion")))
		   , 3 : HIWORD(DllCall("GetVersion")) }
}
LOWORD(l)
{
	return l & 0xffff
}
HIWORD(l)
{
	return (l >> 16) & 0xffff
}
LOBYTE(w)
{
	return w & 0xff
}
HIBYTE(w)
{
	return (w >> 8) & 0xff
}
; ===============================================================================================================================

GetVersion := GetVersion()
MsgBox % "Major:`t"     GetVersion[1]   "`n"
	   . "Minor:`t"     GetVersion[2]   "`n"
	   . "Build:`t"     GetVersion[3]

Code: Select all

DWORD WINAPI GetVersion(void);


void main()
{
	DWORD dwVersion = 0;
	DWORD dwMajorVersion = 0;
	DWORD dwMinorVersion = 0;
	DWORD dwBuild = 0;

	dwVersion = GetVersion();

	// Get the Windows version.
	dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
	dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion)));

	// Get the build number.
	if (dwVersion < 0x80000000)
		dwBuild = (DWORD)(HIWORD(dwVersion));

	printf("Version is %d.%d (%d)\n", dwMajorVersion, dwMinorVersion, dwBuild);
}

Re: Function lib: FormatDword.ahk - HIWORD(), LOWORD(), MAKELONG()

Posted: 02 Dec 2021, 04:02
by lmstearn
Interesting, thanks.
The 0XFFFF mask can be "safely" ignored. The effect of the endianness can be seen in this C demo of structs and unions for a DWORD.