Get list of supported screen resolutions

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
gecko
Posts: 37
Joined: 13 Nov 2017, 23:19

Get list of supported screen resolutions

Post by gecko » 11 Apr 2021, 23:59

Hi all,

I need to be able to access the list of available screen resolutions so a utility I am writing can display it in the gui. I have worked out how to build the rest of the utility, but I have not figured out how to read a list of screen resolutions supported by the system. In my searches so far I have seen that it is possible to change system resolution using AHK, but I have not found any way of simply reading a list of what resolutions are supported. Is this possible? Thanks for any help,

Dan
Last edited by gecko on 27 Apr 2021, 00:14, edited 2 times in total.
gecko
Posts: 37
Joined: 13 Nov 2017, 23:19

Re: Get list of supported screen resolutions

Post by gecko » 27 Apr 2021, 12:18

Just a bump as this thread was moved from another subforum.
User avatar
Smile_
Posts: 858
Joined: 03 May 2020, 00:51

Re: Get list of supported screen resolutions

Post by Smile_ » 27 Apr 2021, 17:50

Multi-monitoring not supported.

Code: Select all

POINTL := "LONG x;LONG y;"
_devicemodeA := "
(
TCHAR dmDeviceName[" CCHDEVICENAME:=32 "];
WORD dmSpecVersion;
WORD dmDriverVersion;
WORD dmSize;
WORD dmDriverExtra;
DWORD dmFields;
union {
    struct {
        short dmOrientation;
        short dmPaperSize;
        short dmPaperLength;
        short dmPaperWidth;
        short dmScale;
        short dmCopies;
        short dmDefaultSource;
        short dmPrintQuality;
    };
    struct {
        POINTL dmPosition;
        DWORD dmDisplayOrientation;
        DWORD dmDisplayFixedOutput;
    };
};
short dmColor;
short dmDuplex;
short dmYResolution;
short dmTTOption;
short dmCollate;
TCHAR dmFormName[" CCHFORMNAME:=32 "];
WORD dmLogPixels;
DWORD dmBitsPerPel;
DWORD dmPelsWidth;
DWORD dmPelsHeight;
union {
    DWORD dmDisplayFlags;
    DWORD dmNup;
};
DWORD dmDisplayFrequency;
DWORD dmICMMethod;
DWORD dmICMIntent;
DWORD dmMediaType;
DWORD dmDitherType;
DWORD dmReserved1;
DWORD dmReserved2;
DWORD dmPanningWidth;
DWORD dmPanningHeight;
)"

#include sizeof_Struct.ahk

dm := new _Struct(_devicemodeA), Out := ""
Loop
{
    If !DllCall("EnumDisplaySettings", "Ptr", 0, "UInt", Enum_Current_Settings := A_Index, "Ptr", dm[""])
        Break
    CurrSetting := "BitsPerPel:" dm.dmBitsPerPel "|" dm.dmPelsWidth "x" dm.dmPelsHeight "|Flags:" dm.dmDisplayFlags ", Frequency:" dm.dmDisplayFrequency
    (!InStr(Out, CurrSetting)) ? Out .= CurrSetting "`n"
}
MsgBox % (Out != "") ? "Available option(s):`n" Out : "There is no available option(s)"
sizeof.ahk & _Struct.ahk.

Code: Select all

;: Title: sizeof function by HotKeyIt
;

; Function: sizeof
; Description:
;      sizeof() is based on AHK_L Objects and supports both, ANSI and UNICODE version, so to use it you will require <a href=http://www.autohotkey.com/forum/viewtopic.php?t=43049>Lexikos AutoHotkey_L.exe</a> or other versions based on it that supports objects.<br><br>nsizeof is used to calculate the size of structures or data types. <br>Visit <a href=http://www.autohotkey.com/forum/viewtopic.php?t=43049>sizeof at AutoHotkey</a> forum, any feedback is welcome.
; Syntax: size:= sizeof(Structure_Definition or Structure_Object)
; Parameters:
;	   Field types - All AutoHotkey and Windows Data Types are supported<br>AutoHotkey Data Types<br> Int, Uint, Int64, UInt64, Char, UChar, Short, UShort, Fload and Double.<br>Windows Data Types<br> - note, TCHAR UCHAR and CHAR return actual character rather than the value, use Asc() function to find out the value/code<br>Windows Data types: Asc(char)<br>ATOM,BOOL,BOOLEAN,BYTE,CHAR,COLORREF,DWORD,DWORDLONG,DWORD_PTR,<br>DWORD32,DWORD64,FLOAT,HACCEL,HALF_PTR,HANDLE,HBITMAP,HBRUSH,HCOLORSPACE,HCONV,HCONVLIST,HCURSOR,HDC,<br>HDDEDATA,HDESK,HDROP,HDWP,HENHMETAFILE,HFILE,HFONT,HGDIOBJ,HGLOBAL,HHOOK,HICON,HINSTANCE,HKEY,HKL,<br>HLOCAL,HMENU,HMETAFILE,HMODULE,HMONITOR,HPALETTE,HPEN,HRESULT,HRGN,HRSRC,HSZ,HWINSTA,HWND,INT,<br>INT_PTR,INT32,INT64,LANGID,LCID,LCTYPE,LGRPID,LONG,LONGLONG,LONG_PTR,LONG32,LONG64,LPARAM,LPBOOL,<br>LPBYTE,LPCOLORREF,LPCSTR,LPCTSTR,LPCVOID,LPCWSTR,LPDWORD,LPHANDLE,LPINT,LPLONG,LPSTR,LPTSTR,LPVOID,<br>LPWORD,LPWSTR,LRESULT,PBOOL,PBOOLEAN,PBYTE,PCHAR,PCSTR,PCTSTR,PCWSTR,PDWORD,PDWORDLONG,PDWORD_PTR,<br>PDWORD32,PDWORD64,PFLOAT,PHALF_PTR,PHANDLE,PHKEY,PINT,PINT_PTR,PINT32,PINT64,PLCID,PLONG,PLONGLONG,<br>PLONG_PTR,PLONG32,PLONG64,POINTER_32,POINTER_64,POINTER_SIGNED,POINTER_UNSIGNED,PSHORT,PSIZE_T,<br>PSSIZE_T,PSTR,PTBYTE,PTCHAR,PTSTR,PUCHAR,PUHALF_PTR,PUINT,PUINT_PTR,PUINT32,PUINT64,PULONG,PULONGLONG,<br>PULONG_PTR,PULONG32,PULONG64,PUSHORT,PVOID,PWCHAR,PWORD,PWSTR,SC_HANDLE,SC_LOCK,SERVICE_STATUS_HANDLE,<br>SHORT,SIZE_T,SSIZE_T,TBYTE,TCHAR,UCHAR,UHALF_PTR,UINT,UINT_PTR,UINT32,UINT64,ULONG,ULONGLONG,<br>ULONG_PTR,ULONG32,ULONG64,USHORT,USN,WCHAR,WORD,WPARAM
;	   <b>Parameters</b> - <b>Description</b>
;	   size - The size of structure or data type
;	   Structure_Definition - C/C++ syntax or usual definition (must not be multiline) e.g. "Int x,Int y", C/C++ definitions must be multiline.
; Return Value:
;     sizeof returns size of structures or data types
; Remarks:
;		None.
; Related:
; Example:
;		file:

sizeof(_TYPE_,parent_offset=0,ByRef _align_total_=0){
    ;Windows and AHK Data Types, used to find out the corresponding size
    static _types__:="
    (LTrim Join
    ,ATOM:2,LANGID:2,WCHAR:2,WORD:2,PTR:" A_PtrSize ",UPTR:" A_PtrSize ",SHORT:2,USHORT:2,INT:4,UINT:4,INT64:8,UINT64:8,DOUBLE:8,FLOAT:4,CHAR:1,UCHAR:1,__int64:8
    ,TBYTE:" (A_IsUnicode?2:1) ",TCHAR:" (A_IsUnicode?2:1) ",HALF_PTR:" (A_PtrSize=8?4:2) ",UHALF_PTR:" (A_PtrSize=8?4:2) ",INT32:4,LONG:4,LONG32:4,LONGLONG:8
    ,LONG64:8,USN:8,HFILE:4,HRESULT:4,INT_PTR:" A_PtrSize ",LONG_PTR:" A_PtrSize ",POINTER_64:" A_PtrSize ",POINTER_SIGNED:" A_PtrSize "
    ,BOOL:4,SSIZE_T:" A_PtrSize ",WPARAM:" A_PtrSize ",BOOLEAN:1,BYTE:1,COLORREF:4,DWORD:4,DWORD32:4,LCID:4,LCTYPE:4,LGRPID:4,LRESULT:4,PBOOL:" A_PtrSize "
    ,PBOOLEAN:" A_PtrSize ",PBYTE:" A_PtrSize ",PCHAR:" A_PtrSize ",PCSTR:" A_PtrSize ",PCTSTR:" A_PtrSize ",PCWSTR:" A_PtrSize ",PDWORD:" A_PtrSize "
    ,PDWORDLONG:" A_PtrSize ",PDWORD_PTR:" A_PtrSize ",PDWORD32:" A_PtrSize ",PDWORD64:" A_PtrSize ",PFLOAT:" A_PtrSize ",PHALF_PTR:" A_PtrSize "
    ,UINT32:4,ULONG:4,ULONG32:4,DWORDLONG:8,DWORD64:8,ULONGLONG:8,ULONG64:8,DWORD_PTR:" A_PtrSize ",HACCEL:" A_PtrSize ",HANDLE:" A_PtrSize "
    ,HBITMAP:" A_PtrSize ",HBRUSH:" A_PtrSize ",HCOLORSPACE:" A_PtrSize ",HCONV:" A_PtrSize ",HCONVLIST:" A_PtrSize ",HCURSOR:" A_PtrSize ",HDC:" A_PtrSize "
    ,HDDEDATA:" A_PtrSize ",HDESK:" A_PtrSize ",HDROP:" A_PtrSize ",HDWP:" A_PtrSize ",HENHMETAFILE:" A_PtrSize ",HFONT:" A_PtrSize ",USAGE:" 2 "
        )"
        static _types_:=_types__ "
        (LTrim Join
    ,HGDIOBJ:" A_PtrSize ",HGLOBAL:" A_PtrSize ",HHOOK:" A_PtrSize ",HICON:" A_PtrSize ",HINSTANCE:" A_PtrSize ",HKEY:" A_PtrSize ",HKL:" A_PtrSize "
    ,HLOCAL:" A_PtrSize ",HMENU:" A_PtrSize ",HMETAFILE:" A_PtrSize ",HMODULE:" A_PtrSize ",HMONITOR:" A_PtrSize ",HPALETTE:" A_PtrSize ",HPEN:" A_PtrSize "
    ,HRGN:" A_PtrSize ",HRSRC:" A_PtrSize ",HSZ:" A_PtrSize ",HWINSTA:" A_PtrSize ",HWND:" A_PtrSize ",LPARAM:" A_PtrSize ",LPBOOL:" A_PtrSize ",LPBYTE:" A_PtrSize "
    ,LPCOLORREF:" A_PtrSize ",LPCSTR:" A_PtrSize ",LPCTSTR:" A_PtrSize ",LPCVOID:" A_PtrSize ",LPCWSTR:" A_PtrSize ",LPDWORD:" A_PtrSize ",LPHANDLE:" A_PtrSize "
    ,LPINT:" A_PtrSize ",LPLONG:" A_PtrSize ",LPSTR:" A_PtrSize ",LPTSTR:" A_PtrSize ",LPVOID:" A_PtrSize ",LPWORD:" A_PtrSize ",LPWSTR:" A_PtrSize "
    ,PHANDLE:" A_PtrSize ",PHKEY:" A_PtrSize ",PINT:" A_PtrSize ",PINT_PTR:" A_PtrSize ",PINT32:" A_PtrSize ",PINT64:" A_PtrSize ",PLCID:" A_PtrSize "
    ,PLONG:" A_PtrSize ",PLONGLONG:" A_PtrSize ",PLONG_PTR:" A_PtrSize ",PLONG32:" A_PtrSize ",PLONG64:" A_PtrSize ",POINTER_32:" A_PtrSize "
    ,POINTER_UNSIGNED:" A_PtrSize ",PSHORT:" A_PtrSize ",PSIZE_T:" A_PtrSize ",PSSIZE_T:" A_PtrSize ",PSTR:" A_PtrSize ",PTBYTE:" A_PtrSize "
    ,PTCHAR:" A_PtrSize ",PTSTR:" A_PtrSize ",PUCHAR:" A_PtrSize ",PUHALF_PTR:" A_PtrSize ",PUINT:" A_PtrSize ",PUINT_PTR:" A_PtrSize "
    ,PUINT32:" A_PtrSize ",PUINT64:" A_PtrSize ",PULONG:" A_PtrSize ",PULONGLONG:" A_PtrSize ",PULONG_PTR:" A_PtrSize ",PULONG32:" A_PtrSize "
    ,PULONG64:" A_PtrSize ",PUSHORT:" A_PtrSize ",PVOID:" A_PtrSize ",PWCHAR:" A_PtrSize ",PWORD:" A_PtrSize ",PWSTR:" A_PtrSize ",SC_HANDLE:" A_PtrSize "
    ,SC_LOCK:" A_PtrSize ",SERVICE_STATUS_HANDLE:" A_PtrSize ",SIZE_T:" A_PtrSize ",UINT_PTR:" A_PtrSize ",ULONG_PTR:" A_PtrSize ",VOID:" A_PtrSize "
        )"
        local _:="",_ArrName_:="",_ArrType_:="",_ArrSize_:=0,_defobj_:="",_idx_:=0,_LF_:="",_LF_BKP_:="",_match_:="",_offset_:=0,_padding_:=0,_struct_:=""
        ,_total_union_size_:=0,_uix_:=0,_union_:=0,_union_size_:=0,_in_struct_:=0,_mod_:=0,_max_size_:=0,_struct_align_:=0
        _offset_:=parent_offset ; Init size/offset to 0 or parent_offset

        If IsObject(_TYPE_){ ; If structure object - check for offset in structure and return pointer + last offset + its data size
            return _TYPE_["`a`a"]
        }

        If RegExMatch(_TYPE_,"^[\w\d\._]+$"){ ; structures name was supplied, resolve to global var and run again
            If InStr(_types_,"," _TYPE_ ":")
                Return SubStr(_types_,InStr(_types_,"," _TYPE_ ":") + 2 + StrLen(_TYPE_),1)
            else If InStr(_TYPE_,"."){ ;check for object that holds structure definition
                Loop,Parse,_TYPE_,.
                    If A_Index=1
                    _defobj_:=%A_LoopField%
                else _defobj_:=_defobj_[A_LoopField]
                    Return sizeof(_defobj_,parent_offset)
            } else Return sizeof(%_TYPE_%,parent_offset)
        } else _defobj_:="" 
        If InStr(_TYPE_,"`n") { ; C/C++ style definition, convert
            _offset_:="" ; This will hold new structure
            ,_struct_:=[] ; This will keep track if union is structure
            ,_union_:=0 ; This will keep track of union depth
            Loop,Parse,_TYPE_,`n,`r`t%A_Space%%A_Tab%
            {
                _LF_:=""
                Loop,Parse,A_LoopField,`,`;,`t%A_Space%%A_Tab%
                {
                    If RegExMatch(A_LoopField,"^\s*//") ;break on comments and continue main loop
                        break
                    If (A_LoopField){ ; skip empty lines
                        If (!_LF_ && _ArrType_:=RegExMatch(A_LoopField,"[\w\d_#@]\s+[\w\d_#@]")) ; new line, find out data type and save key in _LF_ Data type will be added later
                            _LF_:=RegExReplace(A_LoopField,"[\w\d_#@]\K\s+.*$")
                        If Instr(A_LoopField,"{"){ ; Union, also check if it is a structure
                            _union_++,_struct_.Insert(_union_,RegExMatch(A_LoopField,"i)^\s*struct\s*\{"))
                        } else If InStr(A_LoopField,"}") ; end of union/struct
                        _offset_.="}"
                        else { ; not starting or ending struct or union so add definitions and apply Data Type.
                            If _union_ ; add { or struct{
                                Loop % _union_
                                _ArrName_.=(_struct_[A_Index]?"struct":"") "{"
                            _offset_.=(_offset_ ? "," : "") _ArrName_ ((_ArrType_ && A_Index!=1)?(_LF_ " "):"") RegExReplace(A_LoopField,"\s+"," ")
                            ,_ArrName_:="",_union_:=0
                        }
                    }
                }
            }
            _TYPE_:=_offset_
            ,_offset_:=parent_offset ; Init size/offset to 0 or parent_offset
        }

        ; Following keep track of union size/offset
        _union_:=[] ; keep track of union level, required to reset offset after union is parsed
        ,_struct_:=[] ; for each union level keep track if it is a structure (because here offset needs to increase
        ,_union_size_:=[] ; keep track of highest member within the union or structure, used to calculate new offset after union
        ,_struct_align_:=[] ; keep track of alignment before structure
        ,_total_union_size_:=0 ; used in combination with above, each loop the total offset is updated if current data size is higher
        ;,_align_total_:=0          ; used to calculate alignment for total size of structure
        ,_in_struct_:=1
        ; Parse given structure definition and calculate size
        ; Structures will be resolved by recrusive calls (a structure must be global)
        Loop,Parse,_TYPE_,`,`; ;,%A_Space%%A_Tab%`n`r
        {
            _in_struct_+=StrLen(A_LoopField)+1
            If ("" = _LF_ := trim(A_LoopField,A_Space A_Tab "`n`r"))
                continue
            _LF_BKP_:=_LF_ ;to check for ending brackets = union,struct
            ; Check for STARTING union and set union helpers
            While (_match_:=RegExMatch(_LF_,"i)^(struct|union)?\s*\{\K"))
                ; correct offset for union/structure, sizeof_maxsize returns max size of union or structure
            _max_size_:=sizeof_maxsize(SubStr(_TYPE_,_in_struct_-StrLen(A_LoopField)-1+(StrLen(_LF_BKP_)-StrLen(_LF_))))
            ,_union_.Insert(_offset_+=(_mod_:=Mod(_offset_,_max_size_))?Mod(_max_size_-_mod_,_max_size_):0)
            ,_union_size_.Insert(0)
            ,_struct_align_.Insert(_align_total_>_max_size_?_align_total_:_max_size_)
            ,_struct_.Insert(RegExMatch(_LF_,"i)^struct\s*\{")?(1,_align_total_:=0):0)
            ,_LF_:=SubStr(_LF_,_match_)
        StringReplace,_LF_,_LF_,},,A

        If InStr(_LF_,"*"){ ; It's a pointer, size will be always A_PtrSize
            _offset_ += (_mod_:=Mod(_offset_ + A_PtrSize,A_PtrSize)?A_PtrSize-_mod_:0) + A_PtrSize
            ,_align_total_:=_align_total_<A_PtrSize?A_PtrSize:_align_total_
        } else {
            ; Split array type and optionally the size of array, e.g. "TCHAR chr[5]"
            RegExMatch(_LF_,"^(?<ArrType_>[\w\d\._#@]+)?\s*(?<ArrName_>[\w\d\._#@]+)?\s*\[?(?<ArrSize_>\d+)?\]?\s*$",_)
            If (!_ArrName_ && !_ArrSize_ && !InStr( _types_ ,"," _ArrType_ ":"))
                _ArrName_:=_ArrType_,_ArrType_:="UInt"
            If InStr(_ArrType_,"."){ ;check for object that holds structure definition
                Loop,Parse,_ArrType_,.
                    If A_Index=1
                    _defobj_:=%A_LoopField%
                else _defobj_:=_defobj_[A_LoopField]
                    ; _ArrType_:=_defobj_                                                                     ;                   ??????????????????????????????????????
            }
            If (_idx_:=InStr( _types_ ,"," _ArrType_ ":")) ; AHK or Windows data type
                _padding_:=SubStr( _types_ , _idx_+StrLen(_ArrType_)+2 , 1 ),_align_total_:=_align_total_<_padding_?_padding_:_align_total_
            else _padding_:= sizeof(_defobj_?_defobj_:%_ArrType_%,0,_align_total_),_max_size_:=sizeof_maxsize(_defobj_?_defobj_:%_ArrType_%)
            if (_max_size_){
                if (_mod_:=Mod(_offset_,_max_size_))
                    _offset_ += Mod(_max_size_-_mod_,_max_size_)
            } else if _mod_:=Mod(_offset_,_padding_)
            _offset_ += Mod(_padding_-_mod_,_padding_)
            _offset_ += (_padding_ * (_ArrSize_?_ArrSize_:1))
            _max_size_:=0
        }
        ; It's a union or struct, check if new member is higher then previous members
        If (_uix_:=_union_.MaxIndex()) && (_max_size_:=_offset_ - _union_[_uix_])>_union_size_[_uix_]
            _union_size_[_uix_]:=_max_size_
        _max_size_:=0
        ; It's a union and not struct
        If (_uix_ && !_struct_[_uix_])
            _offset_:=_union_[_uix_]

        ; Check for ENDING union and reset offset and union helpers
        While (SubStr(_LF_BKP_,0)="}"){
            If !(_uix_:=_union_.MaxIndex()){
                MsgBox,0, Incorrect structure, missing opening braket {`nProgram will exit now `n%_TYPE_%
                ExitApp
            }
            ; reset offset and align because we left a union or structure
            if (_uix_>1 && _struct_[_uix_-1]){
                If (_mod_:=Mod(_offset_,_struct_align_[_uix_]))
                    _offset_+=Mod(_struct_align_[_uix_]-_mod_,_struct_align_[_uix_])
            } else _offset_:=_union_[_uix_]
            ; a member of union/struct is smaller than previous align, restore
            if (_struct_[_uix_] &&_struct_align_[_uix_]>_align_total_)
                _align_total_ := _struct_align_[_uix_]
            ; Increase total size of union/structure if necessary
            _total_union_size_ := _union_size_[_uix_]>_total_union_size_?_union_size_[_uix_]:_total_union_size_
            ,_union_.Remove() ,_struct_.Remove() ,_union_size_.Remove(),_struct_align_.Remove() ; remove latest items
            ,_LF_BKP_:=SubStr(_LF_BKP_,1,StrLen(_LF_BKP_)-1)
            If (_uix_=1){ ; leaving top union, add offset
                if (_mod_:=Mod(_total_union_size_,_align_total_))
                    _total_union_size_ += Mod(_align_total_-_mod_,_align_total_)
                _offset_+=_total_union_size_,_total_union_size_:=0
            }
        }
    }
    _offset_+= Mod(_align_total_ - Mod(_offset_,_align_total_),_align_total_)
    Return _offset_
}
sizeof_maxsize(s){
    static _types__:="
    (LTrim Join
    ,ATOM:2,LANGID:2,WCHAR:2,WORD:2,PTR:" A_PtrSize ",UPTR:" A_PtrSize ",SHORT:2,USHORT:2,INT:4,UINT:4,INT64:8,UINT64:8,DOUBLE:8,FLOAT:4,CHAR:1,UCHAR:1,__int64:8
    ,TBYTE:" (A_IsUnicode?2:1) ",TCHAR:" (A_IsUnicode?2:1) ",HALF_PTR:" (A_PtrSize=8?4:2) ",UHALF_PTR:" (A_PtrSize=8?4:2) ",INT32:4,LONG:4,LONG32:4,LONGLONG:8
    ,LONG64:8,USN:8,HFILE:4,HRESULT:4,INT_PTR:" A_PtrSize ",LONG_PTR:" A_PtrSize ",POINTER_64:" A_PtrSize ",POINTER_SIGNED:" A_PtrSize "
    ,BOOL:4,SSIZE_T:" A_PtrSize ",WPARAM:" A_PtrSize ",BOOLEAN:1,BYTE:1,COLORREF:4,DWORD:4,DWORD32:4,LCID:4,LCTYPE:4,LGRPID:4,LRESULT:4,PBOOL:" A_PtrSize "
    ,PBOOLEAN:" A_PtrSize ",PBYTE:" A_PtrSize ",PCHAR:" A_PtrSize ",PCSTR:" A_PtrSize ",PCTSTR:" A_PtrSize ",PCWSTR:" A_PtrSize ",PDWORD:" A_PtrSize "
    ,PDWORDLONG:" A_PtrSize ",PDWORD_PTR:" A_PtrSize ",PDWORD32:" A_PtrSize ",PDWORD64:" A_PtrSize ",PFLOAT:" A_PtrSize ",PHALF_PTR:" A_PtrSize "
    ,UINT32:4,ULONG:4,ULONG32:4,DWORDLONG:8,DWORD64:8,ULONGLONG:8,ULONG64:8,DWORD_PTR:" A_PtrSize ",HACCEL:" A_PtrSize ",HANDLE:" A_PtrSize "
    ,HBITMAP:" A_PtrSize ",HBRUSH:" A_PtrSize ",HCOLORSPACE:" A_PtrSize ",HCONV:" A_PtrSize ",HCONVLIST:" A_PtrSize ",HCURSOR:" A_PtrSize ",HDC:" A_PtrSize "
    ,HDDEDATA:" A_PtrSize ",HDESK:" A_PtrSize ",HDROP:" A_PtrSize ",HDWP:" A_PtrSize ",HENHMETAFILE:" A_PtrSize ",HFONT:" A_PtrSize ",USAGE:" 2 "
        )"
        static _types_:=_types__ "
        (LTrim Join
    ,HGDIOBJ:" A_PtrSize ",HGLOBAL:" A_PtrSize ",HHOOK:" A_PtrSize ",HICON:" A_PtrSize ",HINSTANCE:" A_PtrSize ",HKEY:" A_PtrSize ",HKL:" A_PtrSize "
    ,HLOCAL:" A_PtrSize ",HMENU:" A_PtrSize ",HMETAFILE:" A_PtrSize ",HMODULE:" A_PtrSize ",HMONITOR:" A_PtrSize ",HPALETTE:" A_PtrSize ",HPEN:" A_PtrSize "
    ,HRGN:" A_PtrSize ",HRSRC:" A_PtrSize ",HSZ:" A_PtrSize ",HWINSTA:" A_PtrSize ",HWND:" A_PtrSize ",LPARAM:" A_PtrSize ",LPBOOL:" A_PtrSize ",LPBYTE:" A_PtrSize "
    ,LPCOLORREF:" A_PtrSize ",LPCSTR:" A_PtrSize ",LPCTSTR:" A_PtrSize ",LPCVOID:" A_PtrSize ",LPCWSTR:" A_PtrSize ",LPDWORD:" A_PtrSize ",LPHANDLE:" A_PtrSize "
    ,LPINT:" A_PtrSize ",LPLONG:" A_PtrSize ",LPSTR:" A_PtrSize ",LPTSTR:" A_PtrSize ",LPVOID:" A_PtrSize ",LPWORD:" A_PtrSize ",LPWSTR:" A_PtrSize "
    ,PHANDLE:" A_PtrSize ",PHKEY:" A_PtrSize ",PINT:" A_PtrSize ",PINT_PTR:" A_PtrSize ",PINT32:" A_PtrSize ",PINT64:" A_PtrSize ",PLCID:" A_PtrSize "
    ,PLONG:" A_PtrSize ",PLONGLONG:" A_PtrSize ",PLONG_PTR:" A_PtrSize ",PLONG32:" A_PtrSize ",PLONG64:" A_PtrSize ",POINTER_32:" A_PtrSize "
    ,POINTER_UNSIGNED:" A_PtrSize ",PSHORT:" A_PtrSize ",PSIZE_T:" A_PtrSize ",PSSIZE_T:" A_PtrSize ",PSTR:" A_PtrSize ",PTBYTE:" A_PtrSize "
    ,PTCHAR:" A_PtrSize ",PTSTR:" A_PtrSize ",PUCHAR:" A_PtrSize ",PUHALF_PTR:" A_PtrSize ",PUINT:" A_PtrSize ",PUINT_PTR:" A_PtrSize "
    ,PUINT32:" A_PtrSize ",PUINT64:" A_PtrSize ",PULONG:" A_PtrSize ",PULONGLONG:" A_PtrSize ",PULONG_PTR:" A_PtrSize ",PULONG32:" A_PtrSize "
    ,PULONG64:" A_PtrSize ",PUSHORT:" A_PtrSize ",PVOID:" A_PtrSize ",PWCHAR:" A_PtrSize ",PWORD:" A_PtrSize ",PWSTR:" A_PtrSize ",SC_HANDLE:" A_PtrSize "
    ,SC_LOCK:" A_PtrSize ",SERVICE_STATUS_HANDLE:" A_PtrSize ",SIZE_T:" A_PtrSize ",UINT_PTR:" A_PtrSize ",ULONG_PTR:" A_PtrSize ",VOID:" A_PtrSize "
        )"
        max:=0,i:=0
        s:=trim(s,"`n`r`t ")
        If InStr(s,"}"){
            Loop,Parse,s
                if (A_LoopField="{")
                i++
            else if (A_LoopField="}"){
                if --i<1{
                    end:=A_Index
                    break
                }
            }
            if end
                s:=SubStr(s,1,end)
        }
        Loop,Parse,s,`n,`r
        {
            _struct_:=(i:=InStr(A_LoopField," //"))?SubStr(A_LoopField,1,i):A_LoopField
            Loop,Parse,_struct_,`;`,{},%A_Space%%A_Tab%
                if A_LoopField&&!InStr(".union.struct.","." A_LoopField ".")
                if (!InStr(A_LoopField,A_Tab)&&!InStr(A_LoopField," "))
                max:=max<4?4:max
            else if (sizeof(A_LoopField,0,size:=0) && max<size)
                max:=size
        }
    return max
}
;: Title: _Struct by HotKeyIt
;

; Function: _Struct
; Description:
;      _Struct is based on AHK_L objects and supports both, ANSI and UNICODE version. To use it you will require <a href=http://www.autohotkey.com/forum/viewtopic.php?t=43049>Lexikos AutoHotkey_L.exe</a> or other versions based on it.<br><br>new _Struct is used to create new structure. A structure must be defined as a global variable or an item of global class (e.g. "MyClass.Struct").<br>_Struct can handle structure in structure as well as Arrays of structures and Vectors.<br>Visit <a href=http://www.autohotkey.com/forum/viewtopic.php?t=43049>_Struct on AutoHotkey</a> forum, any feedback is welcome.
; Syntax: MyStruct:= new _Struct(Structure_Definition,Address,initialization)
; Parameters:
;	   General Design - Class _Struct will create Object(s) that will manage fields of structure(s), for example<br>left,top,right,bottom<br>RC := new _Struct("RECT")<br>will create a RECT structure with fields left,top,right,bottom of type UInt. To pass the structure its pointer to a function, DllCall or SendMessage use RC[""].<br><br>To access fields you can use usual Object syntax: RC.left, RC.right ...<br>To set a field of the structure use RC.top := 100.
;	   Field types - Following AutoHotkey and Windows Data Types are supported:<br><br>AutoHotkey Data Types:<br>Int, Uint, Int64, UInt64, Char, UChar, Short, UShort, Fload and Double.<br><br>Windows Data Types:<br>ATOM,BOOL,BOOLEAN,BYTE,CHAR,COLORREF,DWORD,DWORDLONG,DWORD_PTR,<br>DWORD32,DWORD64,FLOAT,HACCEL,HALF_PTR,HANDLE,HBITMAP,HBRUSH,HCOLORSPACE,HCONV,HCONVLIST,HCURSOR,HDC,<br>HDDEDATA,HDESK,HDROP,HDWP,HENHMETAFILE,HFILE,HFONT,HGDIOBJ,HGLOBAL,HHOOK,HICON,HINSTANCE,HKEY,HKL,<br>HLOCAL,HMENU,HMETAFILE,HMODULE,HMONITOR,HPALETTE,HPEN,HRESULT,HRGN,HRSRC,HSZ,HWINSTA,HWND,INT,<br>INT_PTR,INT32,INT64,LANGID,LCID,LCTYPE,LGRPID,LONG,LONGLONG,LONG_PTR,LONG32,LONG64,LPARAM,LPBOOL,<br>LPBYTE,LPCOLORREF,LPCSTR,LPCTSTR,LPCVOID,LPCWSTR,LPDWORD,LPHANDLE,LPINT,LPLONG,LPSTR,LPTSTR,LPVOID,<br>LPWORD,LPWSTR,LRESULT,PBOOL,PBOOLEAN,PBYTE,PCHAR,PCSTR,PCTSTR,PCWSTR,PDWORD,PDWORDLONG,PDWORD_PTR,<br>PDWORD32,PDWORD64,PFLOAT,PHALF_PTR,PHANDLE,PHKEY,PINT,PINT_PTR,PINT32,PINT64,PLCID,PLONG,PLONGLONG,<br>PLONG_PTR,PLONG32,PLONG64,POINTER_32,POINTER_64,POINTER_SIGNED,POINTER_UNSIGNED,PSHORT,PSIZE_T,<br>PSSIZE_T,PSTR,PTBYTE,PTCHAR,PTSTR,PUCHAR,PUHALF_PTR,PUINT,PUINT_PTR,PUINT32,PUINT64,PULONG,PULONGLONG,<br>PULONG_PTR,PULONG32,PULONG64,PUSHORT,PVOID,PWCHAR,PWORD,PWSTR,SC_HANDLE,SC_LOCK,SERVICE_STATUS_HANDLE,<br>SHORT,SIZE_T,SSIZE_T,TBYTE,TCHAR,UCHAR,UHALF_PTR,UINT,UINT_PTR,UINT32,UINT64,ULONG,ULONGLONG,<br>ULONG_PTR,ULONG32,ULONG64,USHORT,USN,WCHAR,WORD,WPARAM
;	   <b>Structure Definition</b> - <b>Description</b>
;	   User defined - To create a user defined structure you will need to pass a string of predefined types and field names.<br>Default type is UInt, so for example for a RECT structure type can be omited: <b>"left,top,right,left"</b>, which is the same as <b>"Uint left,Uint top,Uint right,Uint bottom"</b><br><br>You can also use structures very similar to C#/C++ syntax, see example.
;	   Global - Global variables can be used to save structures, easily pass name of that variable as first parameter, e.g. new _Struct("MyStruct") where MyStruct must be a global variable with structure definition. Also new _Struct(MyStruct) can be used if variable is accessible.
;	   Array - To create an array of structures include a digit in the end of your string enclosed in squared brackets.<br>For example "RECT[2]" would create an array of 2 structures.<br>This feature can also be used for user defined arrays, for example "Int age,TCHAR name[10]".
;	   Union - Using {} you can create union, for example: <br>_AHKVar:="{Int64 ContentsInt64,Double ContentsDouble,object},...
;	   Struct - Using struct{} you can create structures in union or in structures.
;	   Pointer - To create a pointer you can use *, for example: CHR:="char *str" will hold a pointer to a character. Same way you can have a structure in structure so you can call it recursive, for example Label.NextLabel.NextLabel.NextLabel.JumpToLine
;	   <b>Parameters</b> - <b>Description</b>
;	   MyStruct - This is a variable that will hold the object representing the strucuture which is returned by new _Struct(...).
;	   Structure_Definition - C/C++ syntax or one-line definition e.g. "Int x,Int y".
;	   pointer - Pass a pointer as second parameter to occupy existing strucure.
;	   Initialization - Pass an object to initialize structure, e.g. {left:100,top:20}. If pointer is not used initialization can be specified in second parameter.
;	   <b>Methods</b> - <b>Description</b>
;	   Strct.Type(itm) - Returns type of item or structure
;	   Strct.AhkType(itm) - Returns AHK type of item or structure to be used with NumGet and NumPut as well as DllCall
;	   Strct.Size() - Returns size of structure, same as sizeof(MyStruct)
;	   Strct.SizeT(itm) - Returns size of an item
;	   Strct.Offset(itm) - Returns offset for items
;	   Strct.Encoding(itm) - Returns encoding for items, to be used with StrGet and StrPut
;	   Strct.Alloc(itm,size[,ptrsize]) - Allocates memory in bytes, ptrsize is used to create pointers
;	   Strct.Capacity(itm) - Returns memory capacity for items.
;	   Strct.IsPointer(itm) - Returns whether the item is a pointer (defined using *).
; Return Value:
;     A class object representing your structure
; Remarks:
;		<b>NOTE!!! accessing a field that does not exist will cause recrusive calls and will crash your script, these errors are not catched for performance reasons.<br>TCHAR, UCHAR and CHAR return actual character rather than the value, use Asc() function to find out the value/code.
; Related:
; Example:
;		file:Struct_Example.ahk
;
Class _Struct {
    ; Data Sizes
    static PTR:=A_PtrSize,UPTR:=A_PtrSize,SHORT:=2,USHORT:=2,INT:=4,UINT:=4,__int64:=8,INT64:=8,UINT64:=8,DOUBLE:=8,FLOAT:=4,CHAR:=1,UCHAR:=1,VOID:=A_PtrSize
    ,TBYTE:=A_IsUnicode?2:1,TCHAR:=A_IsUnicode?2:1,HALF_PTR:=A_PtrSize=8?4:2,UHALF_PTR:=A_PtrSize=8?4:2,INT32:=4,LONG:=4,LONG32:=4,LONGLONG:=8
    ,LONG64:=8,USN:=8,HFILE:=4,HRESULT:=4,INT_PTR:=A_PtrSize,LONG_PTR:=A_PtrSize,POINTER_64:=A_PtrSize,POINTER_SIGNED:=A_PtrSize
    ,BOOL:=4,SSIZE_T:=A_PtrSize,WPARAM:=A_PtrSize,BOOLEAN:=1,BYTE:=1,COLORREF:=4,DWORD:=4,DWORD32:=4,LCID:=4,LCTYPE:=4,LGRPID:=4,LRESULT:=4,PBOOL:=4
    ,PBOOLEAN:=A_PtrSize,PBYTE:=A_PtrSize,PCHAR:=A_PtrSize,PCSTR:=A_PtrSize,PCTSTR:=A_PtrSize,PCWSTR:=A_PtrSize,PDWORD:=A_PtrSize,PDWORDLONG:=A_PtrSize
    ,PDWORD_PTR:=A_PtrSize,PDWORD32:=A_PtrSize,PDWORD64:=A_PtrSize,PFLOAT:=A_PtrSize,PHALF_PTR:=A_PtrSize
    ,UINT32:=4,ULONG:=4,ULONG32:=4,DWORDLONG:=8,DWORD64:=8,ULONGLONG:=8,ULONG64:=8,DWORD_PTR:=A_PtrSize,HACCEL:=A_PtrSize,HANDLE:=A_PtrSize
    ,HBITMAP:=A_PtrSize,HBRUSH:=A_PtrSize,HCOLORSPACE:=A_PtrSize,HCONV:=A_PtrSize,HCONVLIST:=A_PtrSize,HCURSOR:=A_PtrSize,HDC:=A_PtrSize
    ,HDDEDATA:=A_PtrSize,HDESK:=A_PtrSize,HDROP:=A_PtrSize,HDWP:=A_PtrSize,HENHMETAFILE:=A_PtrSize,HFONT:=A_PtrSize
    static HGDIOBJ:=A_PtrSize,HGLOBAL:=A_PtrSize,HHOOK:=A_PtrSize,HICON:=A_PtrSize,HINSTANCE:=A_PtrSize,HKEY:=A_PtrSize,HKL:=A_PtrSize
    ,HLOCAL:=A_PtrSize,HMENU:=A_PtrSize,HMETAFILE:=A_PtrSize,HMODULE:=A_PtrSize,HMONITOR:=A_PtrSize,HPALETTE:=A_PtrSize,HPEN:=A_PtrSize
    ,HRGN:=A_PtrSize,HRSRC:=A_PtrSize,HSZ:=A_PtrSize,HWINSTA:=A_PtrSize,HWND:=A_PtrSize,LPARAM:=A_PtrSize,LPBOOL:=A_PtrSize,LPBYTE:=A_PtrSize
    ,LPCOLORREF:=A_PtrSize,LPCSTR:=A_PtrSize,LPCTSTR:=A_PtrSize,LPCVOID:=A_PtrSize,LPCWSTR:=A_PtrSize,LPDWORD:=A_PtrSize,LPHANDLE:=A_PtrSize
    ,LPINT:=A_PtrSize,LPLONG:=A_PtrSize,LPSTR:=A_PtrSize,LPTSTR:=A_PtrSize,LPVOID:=A_PtrSize,LPWORD:=A_PtrSize,LPWSTR:=A_PtrSize,PHANDLE:=A_PtrSize
    ,PHKEY:=A_PtrSize,PINT:=A_PtrSize,PINT_PTR:=A_PtrSize,PINT32:=A_PtrSize,PINT64:=A_PtrSize,PLCID:=A_PtrSize,PLONG:=A_PtrSize,PLONGLONG:=A_PtrSize
    ,PLONG_PTR:=A_PtrSize,PLONG32:=A_PtrSize,PLONG64:=A_PtrSize,POINTER_32:=A_PtrSize,POINTER_UNSIGNED:=A_PtrSize,PSHORT:=A_PtrSize,PSIZE_T:=A_PtrSize
    ,PSSIZE_T:=A_PtrSize,PSTR:=A_PtrSize,PTBYTE:=A_PtrSize,PTCHAR:=A_PtrSize,PTSTR:=A_PtrSize,PUCHAR:=A_PtrSize,PUHALF_PTR:=A_PtrSize,PUINT:=A_PtrSize
    ,PUINT_PTR:=A_PtrSize,PUINT32:=A_PtrSize,PUINT64:=A_PtrSize,PULONG:=A_PtrSize,PULONGLONG:=A_PtrSize,PULONG_PTR:=A_PtrSize,PULONG32:=A_PtrSize
    ,PULONG64:=A_PtrSize,PUSHORT:=A_PtrSize,PVOID:=A_PtrSize,PWCHAR:=A_PtrSize,PWORD:=A_PtrSize,PWSTR:=A_PtrSize,SC_HANDLE:=A_PtrSize
    ,SC_LOCK:=A_PtrSize,SERVICE_STATUS_HANDLE:=A_PtrSize,SIZE_T:=A_PtrSize,UINT_PTR:=A_PtrSize,ULONG_PTR:=A_PtrSize,ATOM:=2,LANGID:=2,WCHAR:=2,WORD:=2,USAGE:=2
    ; Data Types
    static _PTR:="PTR",_UPTR:="UPTR",_SHORT:="Short",_USHORT:="UShort",_INT:="Int",_UINT:="UInt"
    ,_INT64:="Int64",_UINT64:="UInt64",_DOUBLE:="Double",_FLOAT:="Float",_CHAR:="Char",_UCHAR:="UChar"
    ,_VOID:="PTR",_TBYTE:=A_IsUnicode?"USHORT":"UCHAR",_TCHAR:=A_IsUnicode?"USHORT":"UCHAR",_HALF_PTR:=A_PtrSize=8?"INT":"SHORT"
        ,_UHALF_PTR:=A_PtrSize=8?"UINT":"USHORT",_BOOL:="Int",_INT32:="Int",_LONG:="Int",_LONG32:="Int",_LONGLONG:="Int64",_LONG64:="Int64"
        ,_USN:="Int64",_HFILE:="UInt",_HRESULT:="UInt",_INT_PTR:="PTR",_LONG_PTR:="PTR",_POINTER_64:="PTR",_POINTER_SIGNED:="PTR",_SSIZE_T:="PTR"
        ,_WPARAM:="PTR",_BOOLEAN:="UCHAR",_BYTE:="UCHAR",_COLORREF:="UInt",_DWORD:="UInt",_DWORD32:="UInt",_LCID:="UInt",_LCTYPE:="UInt"
        ,_LGRPID:="UInt",_LRESULT:="UInt",_PBOOL:="UPTR",_PBOOLEAN:="UPTR",_PBYTE:="UPTR",_PCHAR:="UPTR",_PCSTR:="UPTR",_PCTSTR:="UPTR"
        ,_PCWSTR:="UPTR",_PDWORD:="UPTR",_PDWORDLONG:="UPTR",_PDWORD_PTR:="UPTR",_PDWORD32:="UPTR",_PDWORD64:="UPTR",_PFLOAT:="UPTR",___int64:="Int64"
        ,_PHALF_PTR:="UPTR",_UINT32:="UInt",_ULONG:="UInt",_ULONG32:="UInt",_DWORDLONG:="UInt64",_DWORD64:="UInt64",_ULONGLONG:="UInt64"
        ,_ULONG64:="UInt64",_DWORD_PTR:="UPTR",_HACCEL:="UPTR",_HANDLE:="UPTR",_HBITMAP:="UPTR",_HBRUSH:="UPTR",_HCOLORSPACE:="UPTR"
        ,_HCONV:="UPTR",_HCONVLIST:="UPTR",_HCURSOR:="UPTR",_HDC:="UPTR",_HDDEDATA:="UPTR",_HDESK:="UPTR",_HDROP:="UPTR",_HDWP:="UPTR"
        static _HENHMETAFILE:="UPTR",_HFONT:="UPTR",_HGDIOBJ:="UPTR",_HGLOBAL:="UPTR",_HHOOK:="UPTR",_HICON:="UPTR",_HINSTANCE:="UPTR",_HKEY:="UPTR"
        ,_HKL:="UPTR",_HLOCAL:="UPTR",_HMENU:="UPTR",_HMETAFILE:="UPTR",_HMODULE:="UPTR",_HMONITOR:="UPTR",_HPALETTE:="UPTR",_HPEN:="UPTR"
        ,_HRGN:="UPTR",_HRSRC:="UPTR",_HSZ:="UPTR",_HWINSTA:="UPTR",_HWND:="UPTR",_LPARAM:="UPTR",_LPBOOL:="UPTR",_LPBYTE:="UPTR",_LPCOLORREF:="UPTR"
        ,_LPCSTR:="UPTR",_LPCTSTR:="UPTR",_LPCVOID:="UPTR",_LPCWSTR:="UPTR",_LPDWORD:="UPTR",_LPHANDLE:="UPTR",_LPINT:="UPTR",_LPLONG:="UPTR"
        ,_LPSTR:="UPTR",_LPTSTR:="UPTR",_LPVOID:="UPTR",_LPWORD:="UPTR",_LPWSTR:="UPTR",_PHANDLE:="UPTR",_PHKEY:="UPTR",_PINT:="UPTR"
        ,_PINT_PTR:="UPTR",_PINT32:="UPTR",_PINT64:="UPTR",_PLCID:="UPTR",_PLONG:="UPTR",_PLONGLONG:="UPTR",_PLONG_PTR:="UPTR",_PLONG32:="UPTR"
        ,_PLONG64:="UPTR",_POINTER_32:="UPTR",_POINTER_UNSIGNED:="UPTR",_PSHORT:="UPTR",_PSIZE_T:="UPTR",_PSSIZE_T:="UPTR",_PSTR:="UPTR"
        ,_PTBYTE:="UPTR",_PTCHAR:="UPTR",_PTSTR:="UPTR",_PUCHAR:="UPTR",_PUHALF_PTR:="UPTR",_PUINT:="UPTR",_PUINT_PTR:="UPTR",_PUINT32:="UPTR"
        ,_PUINT64:="UPTR",_PULONG:="UPTR",_PULONGLONG:="UPTR",_PULONG_PTR:="UPTR",_PULONG32:="UPTR",_PULONG64:="UPTR",_PUSHORT:="UPTR"
        ,_PVOID:="UPTR",_PWCHAR:="UPTR",_PWORD:="UPTR",_PWSTR:="UPTR",_SC_HANDLE:="UPTR",_SC_LOCK:="UPTR",_SERVICE_STATUS_HANDLE:="UPTR"
        static _SIZE_T:="UPTR",_UINT_PTR:="UPTR",_ULONG_PTR:="UPTR",_ATOM:="Ushort",_LANGID:="Ushort",_WCHAR:="Ushort",_WORD:="UShort",_USAGE:="UShort"

        ; Following is used internally only to simplify setting field helpers
        ; the corresponding key can be set to invalid type (for string integer and vice versa) to set default if necessary, e.g. ___InitField(N,"")
        ___InitField(_this,N,offset=" ",encoding=0,AHKType=0,isptr=" ",type=0,arrsize=0,memory=0){ ; N = Name of field
            static _prefixes_:={offset:"`b",isptr:"`r",AHKType:"`n",type:"`t",encoding:"`f",memory:"`v",arrsize:" "}
            ,_testtype_:={offset:"integer",isptr:"integer",AHKType:"string",type:"string",encoding:"string",arrsize:"integer"}
            ,_default_:={offset:0,isptr:0,AHKType:"UInt",type:"UINT",encoding:"CP0",memory:"",arrsize:1}
            for _key_,_value_ in _prefixes_
            {
                _typevalid_:=0
                If (_testtype_[_key_]="Integer"){
                    If %_key_% is integer
                        useDefault:=1,_typevalid_:=1
                    else if !_this.HasKey(_value_ N)
                        useDefault:=1
                } else {
                    If %_key_% is not integer
                        useDefault:=1,_typevalid_:=1
                    else if !_this.HasKey(_value_ N)
                        useDefault:=1
                }
                If (useDefault) ; item does not exist or user supplied a valid type
                    If (_key_="encoding")
                    _this[_value_ N]:=_typevalid_?(InStr(",LPTSTR,LPCTSTR,TCHAR,","," %_key_% ",")?(A_IsUnicode?"UTF-16":"CP0")
                :InStr(",LPWSTR,LPCWSTR,WCHAR,","," %_key_% ",")?"UTF-16":"CP0")
                :_default_[_key_]
                else {
                    _this[_value_ N]:=_typevalid_?%_key_%:_default_[_key_]
                }
            }
        }

        ; Struct Contstructor
        ; Memory, offset and definitions are saved in following character + given key/name
        ;   `a = Allocated Memory
        ;   `b = Byte Offset (related to struct address)
        ;   `f = Format (encoding for string data types)
        ;   `n = New data type (AHK data type)
        ;   `r = Is Pointer (requred for __GET and __SET)
        ;   `t = Type (data type, also when it is name of a Structure it is used to resolve structure pointers dynamically
        ;   `v = Memory used to save string and pointer memory
        __NEW(_TYPE_,_pointer_=0,_init_=0){
            static _base_:={__GET:_Struct.___GET,__SET:_Struct.___SET,__SETPTR:_Struct.___SETPTR,__Clone:_Struct.___Clone,__NEW:_Struct.___NEW
                ,IsPointer:_Struct.IsPointer,Offset:_Struct.Offset,Type:_Struct.Type,AHKType:_Struct.AHKType,Encoding:_Struct.Encoding
            ,Capacity:_Struct.Capacity,Alloc:_Struct.Alloc,Size:_Struct.Size,SizeT:_Struct.SizeT,Print:_Struct.Print,ToObj:_Struct.ToObj}
            local _:="",_ArrType_:="",_ArrName_:="",_ArrSize_:=0,_align_total_:=0,_defobj_:="",_IsPtr_:=0,_key_:="",_LF_:="",_LF_BKP_:="",_match_:="",_offset_:=""
            ,_struct_:="",_StructSize_:=0,_total_union_size_:=0,_union_:=0,_union_size_:=0,_value_:="",_mod_:=0,_max_size_:=0,_in_struct_:=0,_struct_align_:=0

            If (RegExMatch(_TYPE_,"^[\w\d\._]+$") && !_Struct.HasKey(_TYPE_)){ ; structures name was supplied, resolve to global var and run again
                If InStr(_TYPE_,"."){ ;check for object that holds structure definition
                    Loop,Parse,_TYPE_,.
                        If A_Index=1
                        _defobj_:=%A_LoopField%
                    else _defobj_:=_defobj_[A_LoopField]
                        _TYPE_:=_defobj_
                } else _TYPE_:=%_TYPE_%,_defobj_:=""
            } else _defobj_:=""
            ; If a pointer is supplied, save it in key [""] else reserve and zero-fill memory + set pointer in key [""]
            If (_pointer_ && !IsObject(_pointer_))
                this[""] := _pointer_,this["`a"]:=0,this["`a`a"]:=sizeof(_TYPE_)
            else
                this._SetCapacity("`a",_StructSize_:=sizeof(_TYPE_)) ; Set Capacity in key ["`a"]
            ,this[""]:=this._GetAddress("`a") ; Save pointer in key [""]
            ,DllCall("RtlZeroMemory","UPTR",this[""],"UInt",this["`a`a"]:=_StructSize_) ; zero-fill memory
            ; C/C++ style structure definition, convert it
            If InStr(_TYPE_,"`n") {
                _struct_:=[] ; keep track of structures (union is just removed because {} = union, struct{} = struct
                _union_:=0 ; init to 0, used to keep track of union depth
                Loop,Parse,_TYPE_,`n,`r`t%A_Space%%A_Tab% ; Parse each line
                {
                    _LF_:=""
                    Loop,Parse,A_LoopField,`,`;,`t%A_Space%%A_Tab% ; Parse each item
                    {
                        If RegExMatch(A_LoopField,"^\s*//") ;break on comments and continue main loop
                            break
                        If (A_LoopField){ ; skip empty lines
                            If (!_LF_ && _ArrType_:=RegExMatch(A_LoopField,"[\w\d_#@]\s+[\w\d_#@]")) ; new line, find out data type and save key in _LF_ Data type will be added later
                                _LF_:=RegExReplace(A_LoopField,"[\w\d_#@]\K\s+.*$")
                            If Instr(A_LoopField,"{"){ ; Union, also check if it is a structure
                                _union_++,_struct_.Insert(_union_,RegExMatch(A_LoopField,"i)^\s*struct\s*\{"))
                            } else If InStr(A_LoopField,"}") ; end of union/struct
                            _offset_.="}"
                            else { ; not starting or ending struct or union so add definitions and apply Data Type.
                                If _union_ ; add { or struct{
                                    Loop % _union_
                                    _ArrName_.=(_struct_[A_Index]?"struct":"") "{"
                                _offset_.=(_offset_ ? "," : "") _ArrName_ ((_ArrType_ && A_Index!=1)?(_LF_ " "):"") RegExReplace(A_LoopField,"\s+"," ")
                                ,_ArrName_:="",_union_:=0
                            }
                        }
                    }
                }
                _TYPE_:=_offset_
            }

            _offset_:=0 
            ,_union_:=[] ; keep track of union level, required to reset offset after union is parsed
            ,_struct_:=[] ; for each union level keep track if it is a structure (because here offset needs to increase
            ,_union_size_:=[] ; keep track of highest member within the union or structure, used to calculate new offset after union
            ,_struct_align_:=[] ; keep track of alignment before structure
            ,_total_union_size_:=0 ; used in combination with above, each loop the total offset is updated if current data size is higher
            ,_align_total_:=0			; used to calculate alignment for total size of structure
            ,_in_struct_:=1

            ,this["`t"]:=0,this["`r"]:=0 ; will identify a Structure Pointer without members

            ; Parse given structure definition and create struct members
            ; User structures will be resolved by recrusive calls (!!! a structure must be a global variable)
            Loop,Parse,_TYPE_,`,`; ;,%A_Space%%A_Tab%`n`r
            {
                _in_struct_+=StrLen(A_LoopField)+1
                If ("" = _LF_ := trim(A_LoopField,A_Space A_Tab "`n`r"))
                    continue
                _LF_BKP_:=_LF_ ;to check for ending brackets = union,struct
                _IsPtr_:=0
                ; Check for STARTING union and set union helpers
                While (_match_:=RegExMatch(_LF_,"i)^(struct|union)?\s*\{\K"))
                    ; correct offset for union/structure, sizeof_maxsize returns max size of union or structure
                _max_size_:=sizeof_maxsize(SubStr(_TYPE_,_in_struct_-StrLen(A_LoopField)-1+(StrLen(_LF_BKP_)-StrLen(_LF_))))
                ,_union_.Insert(_offset_+=(_mod_:=Mod(_offset_,_max_size_))?Mod(_max_size_-_mod_,_max_size_):0)
                ,_union_size_.Insert(0)
                ,_struct_align_.Insert(_align_total_>_max_size_?_align_total_:_max_size_)
                ,_struct_.Insert(RegExMatch(_LF_,"i)^struct\s*\{")?(1,_align_total_:=0):0)
                ,_LF_:=SubStr(_LF_,_match_)

            StringReplace,_LF_,_LF_,},,A ;remove all closing brackets (these will be checked later)

            ; Check if item is a pointer and remove * for further processing, separate key will store that information
            While % (InStr(_LF_,"*")){
                StringReplace,_LF_,_LF_,*
                _IsPtr_:=A_Index
            }
            ; Split off data type, name and size (only data type is mandatory)
            RegExMatch(_LF_,"^(?<ArrType_>[\w\d\._]+)?\s*(?<ArrName_>[\w\d_]+)?\s*\[?(?<ArrSize_>\d+)?\]?\s*\}*\s*$",_)
            If (!_ArrName_ && !_ArrSize_){
                If RegExMatch(_TYPE_,"^\**" _ArrType_ "\**$"){
                    _Struct.___InitField(this,"",0,_ArrType_,_IsPtr_?"PTR":_Struct.HasKey("_" _ArrType_)?_Struct["_" _ArrType_]:"PTR",_IsPtr_,_ArrType_)
                    this.base:=_base_
                    If (IsObject(_init_)||IsObject(_pointer_)){ ; Initialization of structures members, e.g. _Struct(_RECT,{left:10,right:20})
                        for _key_,_value_ in IsObject(_init_)?_init_:_pointer_
                        {
                            If !this["`r"]{ ; It is not a pointer, assign value
                                If InStr(",LPSTR,LPCSTR,LPTSTR,LPCTSTR,LPWSTR,LPCWSTR,","," this["`t" _key_] ",")
                                    this.Alloc(_key_,StrLen(_value_)*(InStr(".LPWSTR,LPCWSTR,","," this["`t"] ",")||(InStr(",LPTSTR,LPCTSTR,","," this["`t" _key_] ",")&&A_IsUnicode)?2:1))
                                if InStr(",LPSTR,LPCSTR,LPTSTR,LPCTSTR,LPWSTR,LPCWSTR,CHAR,TCHAR,WCHAR,","," this["`t" _key_] ",")
                                    this[_key_]:=_value_
                                else 
                                    this[_key_] := _value_
                            }else if (_value_<>"") ; It is not empty
                            If _value_ is integer ; It is a new pointer
                                this[_key_][""]:=_value_
                        }
                    }
                    Return this ;:= new _Struct(%_ArrType_%,_pointer_)   ;only Data type was supplied, object/structure has got no members/keys
                } else
                _ArrName_:=_ArrType_,_ArrType_:="UInt"
            }
            If InStr(_ArrType_,"."){ ;check for object that holds structure definition
                Loop,Parse,_ArrType_,.
                    If A_Index=1
                    _defobj_:=%A_LoopField%
                else _defobj_:=_defobj_[A_LoopField]
                }
            if (!_IsPtr_ && !_Struct.HasKey(_ArrType_)){ ; _ArrType_ not found resolve to global variable (must contain struct definition)
                if (sizeof(_defobj_?_defobj_:%_ArrType_%,0,_align_total_) && mod:=Mod(_offset_,_align_total_))
                    _offset_+=Mod(_align_total_-_mod_,_align_total_)
                _Struct.___InitField(this,_ArrName_,_offset_,_ArrType_,0,0,_ArrType_,_ArrSize_)
                ; update current union size
                If (_uix_:=_union_.MaxIndex()) && (_max_size_:=_offset_ + sizeof(_defobj_?_defobj_:%_ArrType_%) - _union_[_uix_])>_union_size_[_uix_]
                    _union_size_[_uix_]:=_max_size_
                _max_size:=0
                ; if not a union or a union + structure then offset must be moved (when structure offset will be reset below
                If (!_uix_||_struct_[_struct_.MaxIndex()])
                    _offset_+=this[" " _ArrName_]*sizeof(_defobj_?_defobj_:%_ArrType_%) ; move offset
                ;Continue
            } else {
                If ((_IsPtr_ || _Struct.HasKey(_ArrType_)))
                    _offset_+=(_mod_:=Mod(_offset_,_max_size_:=_IsPtr_?A_PtrSize:_Struct[_ArrType_]))=0?0:(_IsPtr_?A_PtrSize:_Struct[_ArrType_])-_mod_
                ,_align_total_:=_max_size_>_align_total_?_max_size_:_align_total_
                ,_Struct.___InitField(this,_ArrName_,_offset_,_ArrType_,_IsPtr_?"PTR":_Struct.HasKey(_ArrType_)?_Struct["_" _ArrType_]:_ArrType_,_IsPtr_,_ArrType_,_ArrSize_)
                ; update current union size
                If (_uix_:=_union_.MaxIndex()) && (_max_size_:=_offset_ + _Struct[this["`n" _ArrName_]] - _union_[_uix_])>_union_size_[_uix_]
                    _union_size_[_uix_]:=_max_size_
                _max_size_:=0
                ; if not a union or a union + structure then offset must be moved (when structure offset will be reset below
                If (!_uix_||_struct_[_uix_])
                    _offset_+=_IsPtr_?A_PtrSize:(_Struct.HasKey(_ArrType_)?_Struct[_ArrType_]:%_ArrType_%)*this[" " _ArrName_]
            }
            ; Check for ENDING union and reset offset and union helpers
            While (SubStr(_LF_BKP_,0)="}"){
                If (!_uix_:=_union_.MaxIndex()){
                    MsgBox,0, Incorrect structure, missing opening braket {`nProgram will exit now `n%_TYPE_%
                    ExitApp
                } ; Increase total size of union/structure if necessary
                ; reset offset and align because we left a union or structure
                if (_uix_>1 && _struct_[_uix_-1]){
                    if (_mod_:=Mod(_offset_,_struct_align_[_uix_]))
                        _offset_+=Mod(_struct_align_[_uix_]-_mod_,_struct_align_[_uix_])
                } else _offset_:=_union_[_uix_]
                if (_struct_[_uix_]&&_struct_align_[_uix_]>_align_total_)
                    _align_total_ := _struct_align_[_uix_]
                ; Increase total size of union/structure if necessary
                _total_union_size_ := _union_size_[_uix_]>_total_union_size_?_union_size_[_uix_]:_total_union_size_
                ,_union_._Remove(),_struct_._Remove(),_union_size_._Remove(),_struct_align_.Remove(),_LF_BKP_:=SubStr(_LF_BKP_,1,StrLen(_LF_BKP_)-1) ; remove latest items
                If (_uix_=1){ ; leaving top union, add offset
                    if (_mod_:=Mod(_total_union_size_,_align_total_))
                        _total_union_size_ += Mod(_align_total_-_mod_,_align_total_)
                    _offset_+=_total_union_size_,_total_union_size_:=0
                }
            }
        }
        this.base:=_base_ ; apply new base which uses below functions and uses ___GET for __GET and ___SET for __SET
        If (IsObject(_init_)||IsObject(_pointer_)){ ; Initialization of structures members, e.g. _Struct(_RECT,{left:10,right:20})
            for _key_,_value_ in IsObject(_init_)?_init_:_pointer_
            {
                If !this["`r" _key_]{ ; It is not a pointer, assign value
                    If InStr(",LPSTR,LPCSTR,LPTSTR,LPCTSTR,LPWSTR,LPCWSTR,","," this["`t" _key_] ",")
                        this.Alloc(_key_,StrLen(_value_)*(InStr(".LPWSTR,LPCWSTR,","," this["`t"] ",")||(InStr(",LPTSTR,LPCTSTR,","," this["`t" _key_] ",")&&A_IsUnicode)?2:1))
                    if InStr(",LPSTR,LPCSTR,LPTSTR,LPCTSTR,LPWSTR,LPCWSTR,CHAR,TCHAR,WCHAR,","," this["`t" _key_] ",")
                        this[_key_]:=_value_
                    else 
                        this[_key_] := _value_
                }else if (_value_<>"") ; It is not empty
                if _value_ is integer ; It is a new pointer
                    this[_key_][""]:=_value_
            }
        }
    Return this
}
ToObj(struct:=""){
    obj:=[]
    for k,v in struct?struct:struct:=this
        if (Asc(k)=10)
        If IsObject(_VALUE_:=struct[_TYPE_:=SubStr(k,2)])
        obj[_TYPE_]:=this.ToObj(_VALUE_)
    else obj[_TYPE_]:=_VALUE_
    return obj
}
SizeT(_key_=""){
    return sizeof(this["`t" _key_])
}
Size(){
    return sizeof(this)
}
IsPointer(_key_=""){
    return this["`r" _key_] 
}
Type(_key_=""){
    return this["`t" _key_] 
}
AHKType(_key_=""){
    return this["`n" _key_] 
}
Offset(_key_=""){
    return this["`b" _key_] 
}
Encoding(_key_=""){
    return this["`b" _key_] 
}
Capacity(_key_=""){
    return this._GetCapacity("`v" _key_)
}
Alloc(_key_="",size="",ptrsize=0){
    If _key_ is integer
        ptrsize:=size,size:=_key_,_key_:=""
    If size is integer
        SizeIsInt:=1
    If ptrsize {
        If (this._SetCapacity("`v" _key_,!SizeIsInt?A_PtrSize+ptrsize:size + (size//A_PtrSize)*ptrsize)="")
        MsgBox % "Memory for pointer ." _key_ ". of size " (SizeIsInt?size:A_PtrSize) " could not be set!"
        else {
            DllCall("RtlZeroMemory","UPTR",this._GetAddress("`v" _key_),"UInt",this._GetCapacity("`v" _key_))
            If (this[" " _key_]>1){
                ptr:=this[""] + this["`b" _key_]
                If (this["`r" _key_] || InStr(",LPSTR,LPCSTR,LPTSTR,LPCTSTR,LPWSTR,LPCWSTR,","," this["`t" _key_] ","))
                    NumPut(ptrs:=this._GetAddress("`v" _key_),ptr+0,"PTR")
                else if _key_
                    this[_key_,""]:=ptrs:=this._GetAddress("`v" _key_)
                else this[""]:=ptr:=this._GetAddress("`v" _key_),ptrs:=this._GetAddress("`v" _key_)+(SizeIsInt?size:A_PtrSize)
            } else {
                If (this["`r" _key_] || InStr(",LPSTR,LPCSTR,LPTSTR,LPCTSTR,LPWSTR,LPCWSTR,","," this["`t" _key_] ","))
                    NumPut(ptr:=this._GetAddress("`v" _key_),this[""] + this["`b" _key_],"PTR")
                else this[""]:=ptr:=this._GetAddress("`v" _key_)
                    ptrs:=ptr+(size?size:A_PtrSize)
            }
            Loop % SizeIsInt?(size//A_PtrSize):1
            NumPut(ptrs+(A_Index-1)*ptrsize,ptr+(A_Index-1)*A_PtrSize,"PTR")
        }
    } else {
        If (this._SetCapacity("`v" _key_,SizeIsInt?size:A_PtrSize)=""){
            MsgBox % "Memory for pointer ." _key_ ". of size " (SizeIsInt?size:A_PtrSize) " could not be set!"
        } else
        NumPut(ptr:=this._GetAddress("`v" _key_),this[""] + this["`b" _key_],"PTR"),DllCall("RtlZeroMemory","UPTR",ptr,"UInt",SizeIsInt?size:A_PtrSize)
    }
    return ptr
}
___NEW(init*){
    this:=this.base
    newobj := this.__Clone(1) ;clone structure and keep pointer (1), it will be changed below
    If (init.MaxIndex() && !IsObject(init.1))
        newobj[""] := init.1
    else If (init.MaxIndex()>1 && !IsObject(init.2))
        newobj[""] := init.2
    else
        newobj._SetCapacity("`a",_StructSize_:=sizeof(this)) ; Set Capacity in key ["`a"]
    ,newobj[""]:=newobj._GetAddress("`a") ; Save pointer in key [""]
    ,DllCall("RtlZeroMemory","UPTR",newobj[""],"UInt",_StructSize_) ; zero-fill memory
    If (IsObject(init.1)||IsObject(init.2))
        for _key_,_value_ in IsObject(init.1)?init.1:init.2
        newobj[_key_] := _value_
    return newobj
}

; Clone structure and move pointer for new structure
___Clone(offset){
    static _base_:={__GET:_Struct.___GET,__SET:_Struct.___SET,__SETPTR:_Struct.___SETPTR,__Clone:_Struct.___Clone,__NEW:_Struct.___NEW
        ,IsPointer:_Struct.IsPointer,Offset:_Struct.Offset,Type:_Struct.Type,AHKType:_Struct.AHKType,Encoding:_Struct.Encoding
    ,Capacity:_Struct.Capacity,Alloc:_Struct.Alloc,Size:_Struct.Size,SizeT:_Struct.SizeT,Print:_Struct.Print,ToObj:_Struct.ToObj}
    If offset=1
    return this
newobj:={} ; new structure object
for _key_,_value_ in this ; copy all values/objects
    If (_key_!="`a")
    newobj[_key_]:=_value_ ; add key to new object and assign value
newobj._SetCapacity("`a",_StructSize_:=sizeof(this)) ; Set Capacity in key ["`a"]
,newobj[""]:=newobj._GetAddress("`a") ; Save pointer in key [""]
,DllCall("RtlZeroMemory","UPTR",newobj[""],"UInt",_StructSize_) ; zero-fill memory
If this["`r"]{ ; its a pointer so we need too move internal memory
    NumPut(NumGet(this[""],"PTR")+A_PtrSize*(offset-1),newobj[""],"Ptr")
    newobj.base:=_base_ ;assign base of _Struct
} else ; do not use internal memory, simply assign new pointer to new structure
newobj.base:=_base_,newobj[]:=this[""]+sizeof(this)*(offset-1)
return newobj ; return new object
}
___GET(_key_="",p*){
    If (_key_="") ; Key was not given so structure[] has been called, return pointer to structure
    Return this[""]
else if !(idx:=p.MaxIndex())
    _field_:=_key_,opt:="~"
else {
    ObjInsert(p,1,_key_)
    opt:=ObjRemove(p),_field_:=_key_:=ObjRemove(p)
    for key_,value_ in p
        this:=this[value_]
}
If this["`t"] ; structure without keys/members
    _key_:="" ; set _key_ empty so items below will resolve to our structure
If (opt!="~"){
    If (opt=""){
        If _field_ is integer
            return (this["`r"]?NumGet(this[""],"PTR"):this[""])+sizeof(this["`t"])*(_field_-1)
    else return this["`r" _key_]?NumGet(this[""]+this["`b" _key_],"PTR"):this[""]+this["`b" _key_] ;+sizeof(this["`t" _key_])*(_field_-1)
} else If opt is integer
{ ;offset to a item e.g. struct.a[100] ("Uint a[100]")
    ; MsgBox % "ja " 
    If (_Struct.HasKey("_" this["`t" _key_]) && this[" " _key_]>1) {
        If (InStr( ",CHAR,UCHAR,TCHAR,WCHAR," , "," this["`t" _key_] "," )){ ; StrGet 1 character only
            Return StrGet(this[""]+this["`b" _key_]+(opt-1)*sizeof(this["`t" _key_]),1,this["`f" _key_])
        } else if InStr( ",LPSTR,LPCSTR,LPTSTR,LPCTSTR,LPWSTR,LPCWSTR," , "," this["`t" _key_] "," ){ ; StrGet string
            Return StrGet(NumGet(this[""]+this["`b" _key_]+(opt-1)*A_PtrSize,"PTR"),this["`f" _key_])
        } else {
            Return NumGet(this[""]+this["`b" _key_]+(opt-1)*sizeof(this["`t" _key_]),this["`n" _key_])
        }
} else Return new _Struct(this["`t" _key_],this[""]+this["`b" _key_]+(opt-1)*sizeof(this["`t" _key_]))
} else
return this[_key_][opt]
} else If _field_ is integer
{ ; array access (must be listed first because otherwise this["`r" _key_] cannot be resolved
    If (_key_){ ; Offset for item
    return this.__Clone(_field_)
} else if this["`r"] {
    Pointer:=""
    Loop % (this["`r"]-1) ; dip into one step and return a new structure
        pointer.="*"
    If pointer
    Return new _Struct(pointer this["`t"],NumGet(this[""],"PTR")+A_PtrSize*(_field_-1))
else Return new _Struct(pointer this["`t"],NumGet(this[""],"PTR")+sizeof(this["`t"])*(_field_-1)).1
} else if _Struct.HasKey("_" this["`t"]) {
    ; If this[" "]
    ; Return new _Struct(this["`t"],this[""])
    ; else 
    If (InStr( ",CHAR,UCHAR,TCHAR,WCHAR," , "," this["`t"] "," )){ ; StrGet 1 character only
    Return StrGet(this[""]+sizeof(this["`t"])*(_field_-1),1,this["`f"])
} else if InStr(",LPSTR,LPCSTR,LPTSTR,LPCTSTR,LPWSTR,LPCWSTR," , "," this["`t"] "," ){ ; StrGet string
    Return StrGet(NumGet(this[""]+A_PtrSize*(_field_-1),"PTR"),this["`f"])
} else { ; resolve pointer
    Return NumGet(this[""]+sizeof(this["`t"])*(_field_-1),this["`n"])
}
} else {

    ; return this.__Clone(_field_)
    ; listVars
    ; MsgBox % this[""] "+" sizeof(this["`t"])*(_field_-1) "-" this["`t"]
    Return new _Struct(this["`t"],this[""]+sizeof(this["`t"])*(_field_-1))
}
} else If this["`r" _key_] { ;pointer
    Pointer:=""
    Loop % (this["`r" _key_]-1) ; dip into one step and return a new structure
        pointer.="*"
    If (_key_=""){
    return this[1][_field_]
} else {
    Return new _Struct(pointer this["`t" _key_],NumGet(this[""]+this["`b" _key_],"PTR"))
}
} else if _Struct.HasKey("_" this["`t" _key_]) { ; default data type, not pointer
    If (this[" " _key_]>1)
    Return new _Struct(this["`t" _key_],this[""] + this["`b" _key_])
else If (InStr( ",CHAR,UCHAR,TCHAR,WCHAR," , "," this["`t" _key_] "," )){ ; StrGet 1 character only
    Return StrGet(this[""]+this["`b" _key_],1,this["`f" _key_])
} else if InStr( ",LPSTR,LPCSTR,LPTSTR,LPCTSTR,LPWSTR,LPCWSTR," , "," this["`t" _key_] "," ){ ; StrGet string
    Return StrGet(NumGet(this[""]+this["`b" _key_],"PTR"),this["`f" _key_])
} else {
    Return NumGet(this[""]+this["`b" _key_],this["`n" _key_])
}
} else { ; the field is a non pointer structure
    Return new _Struct(this["`t" _key_],this[""]+this["`b" _key_])
}
}
___SET(_key_,p*){ ;="",_value_=-0x8000000000000000 ,opt="~"){
    If !(idx:=p.MaxIndex()) ; Set new Pointer, here a value was assigned e.g. struct[]:=&var
    return this[""] :=_key_,this._SetCapacity("`a",0) ; free internal memory, it will not be used anymore
else if (idx=1)
    _value_:=p.1,opt:="~"
else if (idx>1){
    ObjInsert(p,1,_key_)
    If (p[idx]="")
        opt:=ObjRemove(p),_value_:=ObjRemove(p),_key_:=ObjRemove(p)
    else _value_:=ObjRemove(p),_key_:=ObjRemove(p),opt:="~"
        for key_,value_ in p
        this:=this[value_]
}
If this["`t"] ; structure without members
    _field_:=_key_,_key_:="" ; set _key_ empty so it will resolve to our structure
else _field_:=_key_
If this["`r" _key_] { ; Pointer
    If opt is integer
    return NumPut(opt,this[""] + this["`b" _key_],"PTR")
else if this.HasKey("`t" _key_) {
    Pointer:=""
    Loop % (this["`r" _key_]-1) ; dip into one step and return a new structure
        pointer.="*"
    If _key_
    Return (new _Struct(pointer this["`t" _key_],NumGet(this[""] + this["`b" _key_],"PTR"))).1:=_value_
else Return (new _Struct(pointer this["`t"],NumGet(this[""],"PTR")))[_field_]:=_value_
} else If _field_ is Integer
if (_key_="") ; replace this for the operation
    _this:=this,this:=this.__Clone(_Field_)
If InStr( ",LPSTR,LPCSTR,LPTSTR,LPCTSTR,LPWSTR,LPCWSTR," , "," this["`t" _key_] "," )
    StrPut(_value_,NumGet(NumGet(this[""]+this["`b" _key_],"PTR"),"PTR"),this["`f" _key_]) ; StrPut char to addr+A_PtrSize
else if InStr( ",TCHAR,CHAR,UCHAR,WCHAR," , "," this["`t" _key_] "," ){ ; same as above but for 1 Character only
    StrPut(_value_,NumGet(this[""]+this["`b" _key_],"PTR"),this["`f" _key_]) ; StrPut char to addr
} else
NumPut(_value_,NumGet(this[""]+this["`b" _key_],"PTR"),this["`n" _key_])
If _field_ is integer ; restore this after operation
    this:=_this
} else if (RegExMatch(_field_,"^\d+$") && _key_="") {
    if InStr( ",LPSTR,LPCSTR,LPTSTR,LPCTSTR,LPWSTR,LPCWSTR," , "," this["`t"] "," ){ 
        StrPut(_value_,NumGet(this[""]+A_PtrSize*(_field_-1),"PTR"),this["`f"]) ; StrPut string to addr
    } else if InStr( ",TCHAR,CHAR,UCHAR,WCHAR," , "," this["`t" _key_] "," ){
        StrPut(_value_,this[""] + sizeof(this["`t"])*(_field_-1),this["`f"])
    } else
    NumPut(_value_,this[""] + sizeof(this["`t"])*(_field_-1),this["`n"]) ; NumPut new value to key
} else if opt is integer
{
    return NumPut(opt,this[""] + this["`b" _key_],"PTR")
} else if InStr( ",LPSTR,LPCSTR,LPTSTR,LPCTSTR,LPWSTR,LPCWSTR," , "," this["`t" _key_] "," ){ 
    StrPut(_value_,NumGet(this[""] + this["`b" _key_],"PTR"),this["`f" _key_]) ; StrPut string to addr
} else if InStr( ",TCHAR,CHAR,UCHAR,WCHAR," , "," this["`t" _key_] "," ){
    StrPut(_value_,this[""] + this["`b" _key_],this["`f" _key_]) ; StrPut character key
} else
NumPut(_value_,this[""]+this["`b" _key_],this["`n" _key_]) ; NumPut new value to key
Return _value_
}
}
Edit: Removed duplicated outputs.
Last edited by Smile_ on 28 Apr 2021, 01:42, edited 1 time in total.
gecko
Posts: 37
Joined: 13 Nov 2017, 23:19

Re: Get list of supported screen resolutions

Post by gecko » 28 Apr 2021, 01:00

Wow, thanks! It's going to take me some work to understand all that is going on in there, but I will get there. Thanks a lot!
User avatar
Smile_
Posts: 858
Joined: 03 May 2020, 00:51

Re: Get list of supported screen resolutions

Post by Smile_ » 28 Apr 2021, 02:15

Or just use this executable
ListOfResolutions.zip
ListOfResolutions
(59.01 KiB) Downloaded 31 times
which does the same thing and then put it in same directory with this script for example

Code: Select all

Gui, Add, Listbox, w300 h400 vMyLB +HScroll
RunWait, ListOfResolutions,, Hide
Loop, Parse, % RTrim(Clipboard, "`n"), `n
    GuiControl,, MyLB, % A_LoopField
Gui, Show
Return

GuiClose:
ExitApp
swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: Get list of supported screen resolutions

Post by swagfag » 16 May 2021, 20:05

interesting info
  1. There are multiple display modes that have the same resolution. They may differ in other ways such as color depth, frequency, or interlacing.
  2. The Windows GUI simply never allows you to set resolutions or color depths below a certain amount. With Windows '9x it was 640x480 and 16 colors. Now it is 800x600. This is simply because the Windows UI doesn't work below a certain size. You wouldn't even be able to see the message asking if the resolution worked! Also, the GUI may only return resolutions that match the aspect ratio of your monitor.
EDIT: By "frequency" we mean "refresh rate"
https://stackoverflow.com/questions/24913268/getting-all-supported-screen-resolutions/24913604#24913604
User avatar
SKAN
Posts: 1551
Joined: 29 Sep 2013, 16:58

Re: Get list of supported screen resolutions

Post by SKAN » 16 May 2021, 21:38

Hi @gecko

You may try ScreenResolution_List
https://www.autohotkey.com/boards/viewtopic.php?t=77664
gecko
Posts: 37
Joined: 13 Nov 2017, 23:19

Re: Get list of supported screen resolutions

Post by gecko » 17 May 2021, 00:22

Hadn't been able to get back to this as soon as I thought. These are great and helpful. Looks like I have a number of options to choose from. Thanks everyone for your help!
Post Reply

Return to “Ask for Help (v1)”