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

Post your working scripts, libraries and tools for AHK v1.1 and older
User avatar
megnatar
Posts: 92
Joined: 27 Oct 2014, 20:49
Location: The Netherlands
Contact:

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

20 Mar 2019, 11:08

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 126 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"
Last edited by megnatar on 20 Mar 2019, 20:50, edited 6 times in total.
DRocks
Posts: 565
Joined: 08 May 2018, 10:20

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

20 Mar 2019, 18:11

Very nice... This has been a mystery for me and this is really helpful. Thank you
User avatar
megnatar
Posts: 92
Joined: 27 Oct 2014, 20:49
Location: The Netherlands
Contact:

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

20 Mar 2019, 19:36

Your welcome :)
just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

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

21 Mar 2019, 03:58

  • 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))
}
DRocks
Posts: 565
Joined: 08 May 2018, 10:20

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

21 Mar 2019, 05:29

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?
wolf_II
Posts: 2688
Joined: 08 Feb 2015, 20:55

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

21 Mar 2019, 08:22

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.
???
wolf_II
Posts: 2688
Joined: 08 Feb 2015, 20:55

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

21 Mar 2019, 17:36

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)))
}
just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

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

22 Mar 2019, 04:48

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.
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

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

22 Mar 2019, 05:10

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);
}
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
User avatar
lmstearn
Posts: 688
Joined: 11 Aug 2016, 02:32
Contact:

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

02 Dec 2021, 04:02

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.
:arrow: itros "ylbbub eht tuO kaerB" a ni kcuts m'I pleH

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: gwarble and 117 guests