Note :!: You will need latest AutoHotkey_L or AutoHotkey_H to use these functions.
_Struct Documentation - Download _Struct.ahk - _Struct.ahk for AHKv2
sizeof() Documentation - Download sizeof.ahk - sizeof.ahk for AHKv2If you use AutoHotkey_H also see AHKStructures.ahk
For compatibility with AHK_H build in Struct() function, save following function as Struct.ahk in your lib folder:
This will also allow to include _Struct function dynamically.
Struct.ahk:
#include <_Struct>
Struct(Structure,pointer=0,init=0){ ; For AHK_L v2 replace this line with Struct(Structure,pointer:=0,init:=0){
return new _Struct(Structure,pointer,init)
}
Changes and up to date version available on github
Struct 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.
;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 :!:
#include <_Struct>
- 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.
; Simple user defined structure (Use number for characters, so StrGet/StrSet will be used)
;typedef struct {
; TCHAR char[2];
; int code[2];
;} ASCIICharacter;
MyChar := 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:=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 := 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:=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:=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:=Struct("_WIN32_FIND_DATA[2]")
time:=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:=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:=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:=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:=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
;_______________________________________________
; 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:= 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 := Struct("HANDLE")
me32 := 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
02.09.2012
- Struct() function for compatibility with AHK_H build in Struct() function.
20.06.2012
- declared local variables as local, otherwise they could get in conflict with globals in v1
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 well04.08.2010 - Fix - structure parameters containing _ were not working02.08.2010 - Fix - Structure memory is filled with 'null character'
- Fix - Offset for Structure in Structure20.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 example27.06.2010 - Fix for Int6425.06.2010 - Struct("definition",pointer) will use existing structure
- Fixed memory issue (thanks Lexikos)




