Note

You will need latest
AutoHotkey_L or
AutoHotkey_H to use these functions.
Changes and up to date version available on githubStruct alows easy access to the world of structures. Simple to use using object syntax, dynamic structure resolution, pointers support and more.It's now so simple to use structures in AHK like never before.
Struct[""] contains pointer of structure so you can pass it to DllCall and SendMessage functions.
Also
Struct.item[""] will return pointer to that item.
Code:
;Assign new pointer to a pointer item
MyStruct.mystring[""] := &variable
;To set pointer for main structure [] must be used !!!
MyStruct[]:=&memory
Do not forget to include the class

Code:
#include <_Struct>
:!: Please note wrote:
- LPSTR,LPCSTR,LPTSTR,LPCTSTR,LPWSTR,LPCWSTR,CHAR,UCHAR,TCHAR
_Struct get and set methods use StrGet for these data types, so you will need to use MyStruct.string[""] to get or set the pointer
- PSTR,PCSTR,PTSTR,PCTSTR,PWSTR,PCWSTR,PCHAR,PUCHAR,PTCHAR
These are equivalent data types that do not use StrGet so you can get and set the pointer directly.
Enjoy

See also this
threadfor more examples.
Code:
#include <_Struct>
; Simple user defined structure (Use number for characters, so StrGet/StrSet will be used)
;typedef struct {
; TCHAR char[2];
; int code[2];
;} ASCIICharacter;
MyChar := new _Struct("TCHAR char[2],int code[2]") ;create structure, type for code could be omited
MyChar.char.1:="A"
MyChar.char.2:="a"
MyChar.code.1 :=Asc(MyChar.char.1)
MyChar.code.2 :=Asc(MyChar.char.2)
MsgBox % MyChar.char.1 " = " MyChar.code.1 "`n" MyChar.char.2 " = " MyChar.code.2
;_______________________________________________
; Simple array of 26 characters
String:=new _Struct("TCHAR char[26]")
Loop 26
string.char[A_Index]:=Chr(A_Index+64)
Loop 3
MsgBox % String.char[A_Index*2] ;show some characters
MsgBox % StrGet(string[]) ;get complete string
;_______________________________________________
; Array of structures
user:="LPTSTR Id, LPTSTR Name"
users := new _Struct("user[2]") ; array of structs
users.Alloc(4*A_PtrSize,400)
;~ users.Alloc("Name",2*A_PtrSize,80)
users.1.Id := "Id1", users.1.Name := "Name 1"
users.2.Id := "Id2", users.2.Name := "Name 2"
MsgBox % users.1.Id " " users.1.Name "`n" users.2.Id " " users.2.Name
;_______________________________________________
; Vector example
Vector:="a,b,c,d"
v:=new _Struct("Vector[2]") ;create an array of Vertors
v.1.a:=1 ;set some keys
v.2.c:=10 ;set some keys
MsgBox % v.1.a "`n" v.2.c ;show values
VarSetCapacity(newmem,sizeof(v)) ;resevere some memory for new structure
v[]:=&newmem ;set new memory address
MsgBox % v.1.a "`n" v.2.c ;show new structure
v.1.a:=1
v.2.c:=10
MsgBox % v.1.a "`n" v.2.c ;now values are filled
;_______________________________________________
; RECT example
;Example using RECT structure to move a window
Gui,+LastFound
hwnd:=WinExist() ;get window handle
_RECT:="left,top,right,bottom"
RC:=new _Struct(_RECT) ;create structure
Gui,Add,Text,,Press Escape to continue
Gui,Show,w200 h100 ;show window
DllCall("GetWindowRect","Uint",hwnd,"Uint",rc[]) ;get window position
rc.right := rc.right - rc.left ;Set rc.right to be the width
rc.bottom := rc.bottom - rc.top ;Set rc.bottom to be the height
While DllCall("GetCursorPos","Uint",rc[])
&& DllCall("MoveWindow","Uint",hwnd
,"int",rc.left,"int",rc.top,"int",rc.right,"int",rc.bottom,"Int",1)
Sleep, 10
GuiClose:
Escape::
Gui,Destroy
rc:=""
;_______________________________________________
; FindFirstFile && FindNextFile && FileTimeToSystemTime
_FILETIME := "dwLowDateTime,dwHighDateTime"
_SYSTEMTIME := "WORD wYear,WORD wMonth,WORD wDayOfWeek,WORD wDay,WORD wHour,WORD wMinute,WORD wSecond,WORD Milliseconds"
_WIN32_FIND_DATA := "dwFileAttributes,_FILETIME ftCreationTime,_FILETIME ftLastAccessTime,_FILETIME ftLastWriteTime,nFileSizeHigh,nFileSizeLow,dwReserved0,dwReserved1,TCHAR cFileName[260],TCHAR cAlternateFileName[14]"
file:=new _Struct("_WIN32_FIND_DATA[2]")
time:=new _Struct("_SYSTEMTIME")
DllCall("FindFirstFile","Str",A_ScriptFullPath,"Uint",file.1[""])
DllCall("FindFirstFile","Str",A_AhkPath,"UInt",file.2[""])
MsgBox % StrGet(file.1.cFileName[])
MsgBox % "A_ScriptFullPath:`t" StrGet(file.1.cFileName[""]) "`t" StrGet(file.1.cAlternateFileName[""]) "`nA_AhkPath:`t" StrGet(file.2.cFileName[""]) "`t" StrGet(file.2.cAlternateFileName[""])
handle:=DllCall("FindFirstFile","Str","C:\*","Uint",file.2[""])
Loop {
If !DllCall("FindNextFile","Uint",handle,"Uint",file.2[""])
break
DllCall("FileTimeToSystemTime","Uint",file.2.ftLastWriteTime[""],"Uint",time[""])
ToolTip % StrGet(file.2.cFileName[""]) "`n" StrGet(file.2.cAlternateFileName[""]) "`n" file.2.nFileSizeHigh " - " file.2.nFileSizeLow
. "`n" time.wYear . "-" time.wMonth . "-" time.wDay
. "`n" time.wDayOfWeek
. "`n" time.wHour . ":" time.wMinute . ":" time.wSecond . ":" time.Milliseconds
Sleep, 200
}
DllCall("CloseHandle","Uint",handle)
;_______________________________________________
; Predefinition of structures
MyStruct:=new _Struct("a,b,c,d")
MyStruct.a:=1
MsgBox % MyStruct.a
; C/C++ like syntax
NewStruct:="
(
TCHAR char[11]; // Array of 11 characters
TCHAR char2[11]; // Another array of 11 characters
LPTSTR string; // String pointer
Int integer; // Integer
PTR pointer; // Pointer
)"
MyStruct:=new _Struct(NewStruct)
MyStruct.Alloc("string",A_PtrSize,100)
MyStruct.char.1:="A" ;set first char
MyStruct.char2.1:="ABC" ;here all 3 characters will be writter to the array char2
MyStruct.string := "New String"
MyStruct.integer := 100
MyStruct.pointer := &MyStruct
MsgBox % MyStruct.char.1 "`n"
. StrGet(MyStruct.char2[""]) "`n"
. MyStruct.String "`n"
. MyStruct.integer "`n"
. MyStruct.pointer "`n"
;_______________________________________________
;Pointer example
;Create a variable containing a string
var:="AutoHotKey"
;Create a pointer that will point to the variable/string
VarSetCapacity(v,4),NumPut(&var,v)
s:=new _Struct("*Uint p",&v)
MsgBox % StrGet(s.p[])
;assign another pointer
anothervar:="AutoHotkey_L"
s.p[""]:=&anothervar
MsgBox % StrGet(s.p[])
;Using LPTSTR you can assign a string directly
s:=new _Struct("LPTSTR p"),s.Alloc("p",A_PtrSize,100)
s.p:="String"
MsgBox % s.p
NumPut(&var,s.p[""],0,"PTR") ; change address in p
MsgBox % s.p
;_______________________________________________
; AHK Structures Example, requires AutoHotkey_H
_AHKDerefType := "LPTSTR marker,{_AHKVar *var,_AHKFunc *func},BYTE is_function,BYTE param_count,WORD length"
_AHKExprTokenType := "{__int64 value_int64,double value_double,struct{{PTR *object,_AHKDerefType *deref,_AHKVar *var,LPTSTR marker},{LPTSTR buf,size_t marker_length}}},UINT symbol,{_AHKExprTokenType *circuit_token,LPTSTR mem_to_free}"
_AHKArgStruct := "BYTE type,BYTE is_expression,WORD length,LPTSTR text,_AHKDerefType *deref,_AHKExprTokenType *postfix"
_AHKLine := "BYTE ActionType,BYTE Argc,WORD FileIndex,UINT LineNumber,_AHKArgStruct *Arg,PTR *Attribute,*_AHKLine PrevLine,*_AHKLine NextLine,*_AHKLine RelatedLine,*_AHKLine ParentLine"
_AHKLabel := "LPTSTR name,*_AHKLine JumpToLine,*_AHKLabel PrevLabel,*_AHKLabel NextLabel"
_AHKFuncParam := "*_AHKVar var,UShort is_byref,UShort default_type,{default_str,Int64 default_int64,Double default_double}"
If (A_PtrSize = 8)
_AHKRCCallbackFunc := "UINT64 data1,UINT64 data2,PTR stub,UINT_PTR callfuncptr,BYTE actual_param_count,BYTE create_new_thread,event_info,*_AHKFunc func"
else
_AHKRCCallbackFunc := "ULONG data1,ULONG data2,ULONG data3,PTR stub,UINT_PTR callfuncptr,ULONG data4,ULONG data5,BYTE actual_param_count,BYTE create_new_thread,event_info,*_AHKFunc func"
_AHKFunc := "PTR vTable,LPTSTR name,{PTR BIF,*_AHKLine JumpToLine},*_AHKFuncParam Param,Int ParamCount,Int MinParams,*_AHKVar var,*_AHKVar LazyVar,Int VarCount,Int VarCountMax,Int LazyVarCount,Int Instances,*_AHKFunc NextFunc,BYTE DefaultVarType,BYTE IsBuiltIn"
_AHKVar := "{Int64 ContentsInt64,Double ContentsDouble,PTR object},{char *mByteContents,LPTSTR CharContents},{UINT_PTR Length,_AHKVar *AliasFor},{UINT_PTR Capacity,UINT_PTR BIV},BYTE HowAllocated,BYTE Attrib,BYTE IsLocal,BYTE Type,LPTSTR Name"
func(a,b=""){
}
variable:="1", var:=new _Struct(_AHKVAR,getVar(variable))
MsgBox % "Name:`t" var.name . "`nContent:`t" var.CharContents . "`nType:`t" Asc(var.type)
func:=new _Struct(_AHKFunc,FindFunc("func"))
MsgBox % "Is " func.name " BuildIn? " Asc(func.IsBuiltIn)
. "`nMinParams: " func.MinParams
. "`nParamCount: " func.ParamCount
;_______________________________________________
; Show original name of variables in a function, requires LowLevel or AutoHotkey_H
a:=1
b:=2
c:=3
MsgBox % ShowVars(a,b,c)
ShowVars(ByRef _1="",ByRef _2="",ByRef _3="",ByRef _4="",ByRef _5="",ByRef _6="",ByRef _7="",ByRef _8="",ByRef _9="",ByRef _10=""){
func:=new _Struct("_AHKFunc",FindFunc(A_ThisFunc))
param:=new _Struct("_AHKFuncparam[10]",func.param[""])
Loop 10
if param[A_Index].var.type=0 && var:=new _Struct("_AHKVar",param[A_Index].var.AliasFor[""]) ;alias
str .= "`n" var.name "=" _%A_Index%
Return SubStr(str, 2)
}
;_______________________________________________
; PROCESSENTRY32
MAX_PATH:=260
_PROCESSENTRY32:="
(
DWORD dwSize;
DWORD cntUsage;
DWORD th32ProcessID;
ULONG_PTR th32DefaultHeapID;
DWORD th32ModuleID;
DWORD cntThreads;
DWORD th32ParentProcessID;
LONG pcPriClassBase;
DWORD dwFlags;
TCHAR szExeFile[" MAX_PATH "];
)"
VarSetCapacity(string,260)
pEntry:= new _Struct(_PROCESSENTRY32)
pEntry.dwSize := sizeof(_PROCESSENTRY32)
hSnapshot:=DllCall("CreateToolhelp32Snapshot","UInt",TH32CS_SNAPALL:=0x0000001F,"PTR",0)
DllCall("Process32First" (A_IsUnicode?"W":""),"PTR",hSnapshot,"PTR",pEntry[""])
While % (A_Index=1 || DllCall("Process32Next" (A_IsUnicode?"W":""),"PTR",hSnapshot,"PTR",pEntry[""])) {
ToolTip % pEntry.cntUsage "`n" pEntry.th32ProcessID
. "`n" pEntry.th32DefaultHeapID "`n" pEntry.th32ModuleID
. "`n" pEntry.cntThreads "`n" pEntry.th32ParentProcessID
. "`n" pEntry.pcPriClassBase "`n" pEntry.dwFlags "`n" StrGet(pEntry.szExeFile[""])
Sleep, 200
}
;_______________________________________________
; MODULEENTRY32
MAX_PATH:=260
MAX_MODULE_NAME32:=255
_MODULEENTRY32:="
(
DWORD dwSize;
DWORD th32ModuleID;
DWORD th32ProcessID;
DWORD GlblcntUsage;
DWORD ProccntUsage;
BYTE *modBaseAddr;
DWORD modBaseSize;
HMODULE hModule;
TCHAR szModule[" MAX_MODULE_NAME32 + 1 "];
TCHAR szExePath[" MAX_PATH "];
)"
ListProcessModules(DllCall("GetCurrentProcessId"))
ExitApp
ListProcessModules(dwPID)
{
global _Struct
static TH32CS_SNAPMODULE:=0x00000008,INVALID_HANDLE_VALUE:=-1
hModuleSnap := new _Struct("HANDLE")
me32 := new _Struct("_MODULEENTRY32")
; Take a snapshot of all modules in the specified process.
hModuleSnap := DllCall("CreateToolhelp32Snapshot","UInt", TH32CS_SNAPMODULE,"PTR", dwPID )
if( hModuleSnap = INVALID_HANDLE_VALUE )
{
MsgBox % "CreateToolhelp32Snapshot (of modules)"
return FALSE
}
; Set the size of the structure before using it.
me32.dwSize := sizeof("_MODULEENTRY32")
; Retrieve information about the first module,
; and exit if unsuccessful
if( !DllCall("Module32First" (A_IsUnicode?"W":""),"PTR", hModuleSnap,"PTR", me32[""] ) )
{
MsgBox % "Module32First" ; // Show cause of failure
DllCall("CloseHandle","PTR", hModuleSnap ) ; // Must clean up the snapshot object!
return FALSE
}
;// Now walk the module list of the process,
;// and display information about each module
while(A_Index=1 || DllCall("Module32Next" (A_IsUnicode?"W":""),"PTR",hModuleSnap,"PTR", me32[""] ) )
{
ToolTip % "`tMODULE NAME`t=`t" StrGet(me32.szModule[""])
. "`n`texecutable`t=`t" StrGet(me32.szExePath[""])
. "`n`tprocess ID`t=`t" me32.th32ProcessID
. "`n`tref count (g)`t=`t" me32.GlblcntUsage
. "`n`tref count (p)`t=`t" me32.ProccntUsage
. "`n`tbase address`t=`t" me32.modBaseAddr[""]
. "`n`tbase size`t=`t" me32.modBaseSize
Sleep, 200
}
;// Do not forget to clean up the snapshot object.
DllCall("CloseHandle","PTR",hModuleSnap)
return TRUE
}
Update
Latest changes available on github
01.04.2012
- small fix in sizeof() when calculating offset.
18.02.2012
- _Struct works now fully dynamically (no objects in objects)
- - for this reason no automatic string allocation is done.
- - you will need to use Alloc to allocate memory or assign a pointer.
- Added several methods, Type(),AhkType(),IsPointer,Size(),SizeT(),Alloc(),Capacity(),Offset() see docs.
- Released AHKv2 version.
10.08.2011
- Fixed StrPut for CHAR,TCHAR,UCHAR.
05.08.2011
- Rewritten _Struct and redesigned to class
- now initialization of items is possible
13.11.2010
- Fixed pointer offset
06.112010
- Struct was completely revised
- Struct constructor
04.08.2010 - Fix - Structure in Structure
- New - instead struct[""] you can use struct[] as well
04.08.2010 - Fix - structure parameters containing _ were not working
02.08.2010 - Fix - Structure memory is filled with 'null character'
- Fix - Offset for Structure in Structure
20.07.2010 - Fixed creating array of structures, e.g. vector example was not working correct.
01.07.2010- Implemented Global variable structure definition and named structure definition
- Implemented Union, see AHKStructures example
- Implemented Pointer in Pointer and Structure in Structure, see pointer and AHKStructures example
27.06.201025.06.2010 - Struct("definition",pointer) will use existing structure
- Fixed memory issue (thanks Lexikos)