DllCall problem: convert array of WCHARs to string Topic is solved

Get help with using AutoHotkey and its commands and hotkeys
pneumatic
Posts: 299
Joined: 05 Dec 2016, 01:51

DllCall problem: convert array of WCHARs to string

30 Dec 2018, 09:38

Hello, I am trying to get the description of the monitor which a DllCall returns as an array of WCHARs, but I've no idea how to convert that into a usable string in AHK.

Code: Select all

DllCall("LoadLibrary", "Str", "dxva2.dll", "Ptr")  

;Get handle to primary monitor
hMon := DllCall("MonitorFromPoint"
			, "Int64", 0  ; point x0 y0 on screen
			, "UInt", 1)  ; tells the function to return the primary monitor handle if something went wrong
			
;Get number of physical monitors
DllCall("dxva2.dll\GetNumberOfPhysicalMonitorsFromHMONITOR"
	  , "Ptr", hMon  ; the handle that we got previously
	  , "UIntP", nMons ; the var into which the number of monitors will be put
	  , "UInt")	
	  
;Get handles of physical monitors associated with the primary monitor handle
VarSetCapacity(hPhysMons, ( A_PtrSize + 256) * nMons, 0)   ; create var to contain array of PHYSICAL_MONITOR structures which will contain handles to physical monitors
DllCall("dxva2.dll\GetPhysicalMonitorsFromHMONITOR"
	, "Ptr", hMon  ; the handle that we got previously
	, "UInt", nMons  ; the number of monitors that we got previously
	, "Ptr", &hPhysMons ; the address of the var we created to hold the array of PHYSICAL_MONITOR structures
	, "UInt")


;Get the monitor description of the first monitor, which is stored at a byte offset of A_PtrSize 
monDescription := NumGet(hPhysMons, A_PtrSize )  

However the monitor description is an array of 128 WCHARs inside the PHYSICAL_MONITOR structure:
https://docs.microsoft.com/en-us/window ... al_monitor

How would I go about decoding each character from that array?

Thanks in advance if you can help!
User avatar
nnnik
Posts: 4475
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: DllCall problem: convert array of WCHARs to string

30 Dec 2018, 10:05

You need to use StrGet with a UTF-16 encoding.
Recommends AHK Studio
swagfag
Posts: 4070
Joined: 11 Jan 2017, 17:59

Re: DllCall problem: convert array of WCHARs to string

30 Dec 2018, 10:19

Code: Select all

;Get the monitor description of the first monitor, which is stored at a byte offset of A_PtrSize 
while(char := Chr(NumGet(hPhysMons, A_PtrSize + (A_Index - 1) * 2, "UShort")))
	monDescription .= char

MsgBox % monDescription ; working
MsgBox % StrGet(NumGet(hPhysMons, A_PtrSize), 0, "UTF-16") ; not working
MsgBox % StrGet(hPhysMons, A_PtrSize, "UTF-16") ; not working
how is strget supposed to be used
pneumatic
Posts: 299
Joined: 05 Dec 2016, 01:51

Re: DllCall problem: convert array of WCHARs to string

30 Dec 2018, 10:28

Thank you swagfag! :clap:
Last edited by pneumatic on 31 Dec 2018, 01:31, edited 1 time in total.
User avatar
nnnik
Posts: 4475
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: DllCall problem: convert array of WCHARs to string  Topic is solved

30 Dec 2018, 10:38

swagfag wrote:
30 Dec 2018, 10:19

Code: Select all

;Get the monitor description of the first monitor, which is stored at a byte offset of A_PtrSize 
while(char := Chr(NumGet(hPhysMons, A_PtrSize + (A_Index - 1) * 2, "UShort")))
	monDescription .= char

MsgBox % monDescription ; working
MsgBox % StrGet(NumGet(hPhysMons, A_PtrSize), 0, "UTF-16") ; not working
MsgBox % StrGet(hPhysMons, A_PtrSize, "UTF-16") ; not working
This code will break as soon as the text contains a multicode character or is not null terminated.
(e.g. Russian, Chinese etc.)
swagfag wrote:
30 Dec 2018, 10:19
how is strget supposed to be used
docs wrote:StrGet(Address , Length , Encoding := None)
Address
The address at which the string will be written to/read from.
Length
The maximum number of characters to read/write, including the null-terminator if required.
Encoding
The source encoding for StrGet or target encoding for StrPut; for example, "UTF-8", "UTF-16" or "CP936". If Address and Length are not specified, numeric identifiers must be prefixed with "CP". Specify an empty string or "CP0" to use the system default ANSI code page.
StrGet requires a pointer to the start of the string, the encoding and the maximum length in code points:
In this case the string starts A_PtrSize bytes after the initial pointer - therefore the string starts at &hPhysMons+A_PtrSize.
Its total size is 128 and the encoding is Utf-16:

Code: Select all

StrGet(&hPhysMons + A_PtrSize, 128, "UTF-16")

Code: Select all

DllCall("LoadLibrary", "Str", "dxva2.dll", "Ptr")  

;Get handle to primary monitor
hMon := DllCall("MonitorFromPoint"
			, "Int64", 0  ; point x0 y0 on screen
			, "UInt", 1)  ; tells the function to return the primary monitor handle if something went wrong
			
;Get number of physical monitors
DllCall("dxva2.dll\GetNumberOfPhysicalMonitorsFromHMONITOR"
	  , "Ptr", hMon  ; the handle that we got previously
	  , "UIntP", nMons ; the var into which the number of monitors will be put
	  , "UInt")	
	  
;Get handles of physical monitors associated with the primary monitor handle
VarSetCapacity(hPhysMons, ( A_PtrSize + 256) * nMons, 0)   ; create var to contain array of PHYSICAL_MONITOR structures which will contain handles to physical monitors
DllCall("dxva2.dll\GetPhysicalMonitorsFromHMONITOR"
	, "Ptr", hMon  ; the handle that we got previously
	, "UInt", nMons  ; the number of monitors that we got previously
	, "Ptr", &hPhysMons ; the address of the var we created to hold the array of PHYSICAL_MONITOR structures
	, "UInt")
	
Msgbox % StrGet(&hPhysMons + A_PtrSize, 128, "UTF-16")
Recommends AHK Studio
swagfag
Posts: 4070
Joined: 11 Jan 2017, 17:59

Re: DllCall problem: convert array of WCHARs to string

30 Dec 2018, 14:37

ahhh, i kept thinking the second param was supposed to be an offset, like with numget...
obviously, forgot to pass the address of the thing hPhysMon pointed to, too
pneumatic
Posts: 299
Joined: 05 Dec 2016, 01:51

Re: DllCall problem: convert array of WCHARs to string

31 Dec 2018, 01:28

nnnik wrote:
30 Dec 2018, 10:38

Code: Select all

Msgbox % StrGet(&hPhysMons + A_PtrSize, 128, "UTF-16")
Thanks nnnik!

But why doesn't this work.

Code: Select all

monDescription := NumGet(hPhysMons, A_PtrSize )
msgbox % StrGet(&monDescription, 128, "UTF-16")
User avatar
nnnik
Posts: 4475
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: DllCall problem: convert array of WCHARs to string

31 Dec 2018, 03:37

In this case monDescription in already part of the string - the first 4 or 8 bytes of it (depending on whether you use 32 or 64 bit AHK).
&monDescription return a pointer to the string version of those numbers or if AHK didn't sync the number to the string buffer yet whatever was in there before.
Recommends AHK Studio

Return to “Ask For Help”

Who is online

Users browsing this forum: boiler, Saarthak Kamra, Smoothglobal, TXShooter and 42 guests