Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

[Class _Struct]+[Func sizeof] ! updated 01.04.12 ! ++AHKv2


  • Please log in to reply
219 replies to this topic
HotKeyIt
  • Moderators
  • 7439 posts
  • Last active: Jun 22 2016 09:14 PM
  • Joined: 18 Jun 2008

Struct() supports now structure definition within union

struct:=Struct("")
struct.OVERLAPPED:="
(
  ULONG_PTR Internal;
  ULONG_PTR InternalHigh;
  union {
    struct {
      DWORD Offset;
      DWORD OffsetHigh;
    } ;
    PVOID  Pointer;
  } ;
  HANDLE    hEvent;
)"
;~ MyOVERLAPPED:=struct.OVERLAPPED
MsgBox % OVERLAPPED

EDIT:
Small bugfix when PVOID 'Pointer' is listed before struct

HotKeyIt
  • Moderators
  • 7439 posts
  • Last active: Jun 22 2016 09:14 PM
  • Joined: 18 Jun 2008
- Fixed bug with pointers.
- Added Void parameter = UPTR
func:=Struct("AHKFunc",Func())
MsgBox % StrGet(func.param.var.Name)
func(parameter=""){
	static pCb:=RegisterCallback("func"),pFunc := NumGet(pCb+28),pCB:=DllCall("GlobalFree","uint",pCb)
	Return pFunc
}


kenn
  • Members
  • 407 posts
  • Last active: Jan 14 2015 08:16 PM
  • Joined: 11 Oct 2010
HotkeyIt, I really much appreciate your contributions to AHK. I am beginner, I'm trying to write simple scripts with AHK, I can say that I covered a long way, your efforts and helpful people encoarage me, thanks a lot!

HotKeyIt
  • Moderators
  • 7439 posts
  • Last active: Jun 22 2016 09:14 PM
  • Joined: 18 Jun 2008
thanks ;)

Updated Struct() for full 64-bit support (thanks Lexikos).

peterm
  • Members
  • 60 posts
  • Last active: Jul 04 2013 05:24 PM
  • Joined: 25 Jul 2006
Is the download broken?
<!-- m -->https://ahknet.autoh...eyIt/Struct.ahk<!-- m -->

It seems to have lost it's formatting.

Peterm

HotKeyIt
  • Moderators
  • 7439 posts
  • Last active: Jun 22 2016 09:14 PM
  • Joined: 18 Jun 2008
No it's alright, simply click right mouse Save as Struct.ahk

peterm
  • Members
  • 60 posts
  • Last active: Jul 04 2013 05:24 PM
  • Joined: 25 Jul 2006
Yup, that works, sorry,not seen this way before for ahk code.
Thanks

hughman
  • Members
  • 192 posts
  • Last active: Feb 14 2016 06:59 AM
  • Joined: 11 Feb 2007
Dear HotkeyIt, can u help me? Why can't I get the right result? All the members of LOGFONTW from window metrics are 0 or null.

Struct := Struct("")
Struct.LOGFONTW := "
(
    LONG		lfHeight;				
    LONG		lfWidth;					
    LONG		lfEscapement;		
    LONG		lfOrientation;		
    LONG		lfWeight;				
    BYTE		lfItalic;					
    BYTE		lfUnderline;			
    BYTE		lfStrikeOut;			
    BYTE		lfCharSet;				
    BYTE		lfOutPrecision;		
    BYTE		lfClipPrecision;		
    BYTE		lfQuality;				
    BYTE		lfPitchAndFamily;	
    WCHAR	lfFaceName[32];	
)"

Struct.NONCLIENTMETRICSW := "
(
    UINT    cbSize;
    int     iBorderWidth;
    int     iScrollWidth;
    int     iScrollHeight;
    int     iCaptionWidth;
    int     iCaptionHeight;
    LOGFONTW lfCaptionFont;
    int     iSmCaptionWidth;
    int     iSmCaptionHeight;
    LOGFONTW lfSmCaptionFont;
    int     iMenuWidth;
    int     iMenuHeight;
    LOGFONTW lfMenuFont;
    LOGFONTW lfStatusFont;
    LOGFONTW lfMessageFont;
)"

	SPI_GETNONCLIENTMETRICS := 0x29, SPI_SETNONCLIENTMETRICS := 0x3A
	NCMW := Struct("NONCLIENTMETRICSW")
	NCMW.cbSize := Struct(NCMW)
	DllCall("SystemParametersInfoW", "UInt", SPI_GETNONCLIENTMETRICS, "UInt", Struct(NCMW), "UPtr", &NCMW, "UInt", 0)
	MsgBox % NCMW.lfMenuFont.lfItalic
	MsgBox % StrGet(NCMW.lfMenuFont.lfFaceName[])
	NCMW.lfMenuFont.lfWeight := 700
	DllCall("SystemParametersInfo", "UInt", SPI_SETNONCLIENTMETRICS, "UInt", Struct(NCMW), "Ptr", &NCMW, "UInt", 2)


HotKeyIt
  • Moderators
  • 7439 posts
  • Last active: Jun 22 2016 09:14 PM
  • Joined: 18 Jun 2008
Instead of &NCMW you need to use NCMW[""].
Better to pass NCMW.cbSize rather than Struct(NCMW).
Struct := Struct("")
Struct.LOGFONTW := "
(
    LONG      lfHeight;            
    LONG      lfWidth;               
    LONG      lfEscapement;      
    LONG      lfOrientation;      
    LONG      lfWeight;            
    BYTE      lfItalic;               
    BYTE      lfUnderline;         
    BYTE      lfStrikeOut;         
    BYTE      lfCharSet;            
    BYTE      lfOutPrecision;      
    BYTE      lfClipPrecision;      
    BYTE      lfQuality;            
    BYTE      lfPitchAndFamily;   
    WCHAR   lfFaceName[32];   
)"

Struct.NONCLIENTMETRICSW := "
(
    UINT    cbSize;
    int     iBorderWidth;
    int     iScrollWidth;
    int     iScrollHeight;
    int     iCaptionWidth;
    int     iCaptionHeight;
    LOGFONTW lfCaptionFont;
    int     iSmCaptionWidth;
    int     iSmCaptionHeight;
    LOGFONTW lfSmCaptionFont;
    int     iMenuWidth;
    int     iMenuHeight;
    LOGFONTW lfMenuFont;
    LOGFONTW lfStatusFont;
    LOGFONTW lfMessageFont;
)"

   SPI_GETNONCLIENTMETRICS := 0x29, SPI_SETNONCLIENTMETRICS := 0x3A
   NCMW := Struct.NONCLIENTMETRICSW ;looks better ;)
   NCMW.cbSize := Struct(NCMW)
   DllCall("SystemParametersInfoW", "UInt", SPI_GETNONCLIENTMETRICS, "UInt", [color=red]NCMW.cbSize[/color], "UPtr", [color=red]NCMW[""][/color], "UInt", 0)
   MsgBox % NCMW.lfMenuFont.lfItalic
   MsgBox % StrGet(NCMW.lfMenuFont.lfFaceName[])
   NCMW.lfMenuFont.lfWeight := 700
   DllCall("SystemParametersInfo", "UInt", SPI_SETNONCLIENTMETRICS, "UInt", [color=red]NCMW.cbSize[/color], "Ptr", [color=red]NCMW[""][/color], "UInt", 2)


hughman
  • Members
  • 192 posts
  • Last active: Feb 14 2016 06:59 AM
  • Joined: 11 Feb 2007
Thx, HotkeyIt. It's so convenient to manipluate struct.
Now I have a puzzle about a struct below and help is need.
the size of strcut created by Struct() is 36, but the size of buffer returned by QueryServiceConfig is variable. So how to handle it?
typedef struct _QUERY_SERVICE_CONFIG {
  DWORD  dwServiceType;
  DWORD  dwStartType;
  DWORD  dwErrorControl;
  LPTSTR lpBinaryPathName;
  LPTSTR lpLoadOrderGroup;
  DWORD  dwTagId;
  LPTSTR lpDependencies;
  LPTSTR lpServiceStartName;
  LPTSTR lpDisplayName;
} QUERY_SERVICE_CONFIG, *LPQUERY_SERVICE_CONFIG;

BOOL WINAPI QueryServiceConfig(
  __in       SC_HANDLE hService,
  __out_opt  LPQUERY_SERVICE_CONFIG lpServiceConfig,
  __in       DWORD cbBufSize,
  __out      LPDWORD pcbBytesNeeded
);



tonne
  • Members
  • 1654 posts
  • Last active: May 06 2014 06:22 PM
  • Joined: 06 Jun 2006
This is nice!

My I suggest another example of usage (arrays of struct)?
user := "TCHAR Id[10], TCHAR Name[30]" ; structure

users := Object() ; array object

newuser := Struct(user) ; create an user
newuser.Id := "Id1"
newuser.Name := "Name 1"
users[1] := newuser ; store

newuser := Struct(user)
newuser.Id := "Id2"
newuser.Name := "Name 2"
users[2] := newuser

; now the fields in the struct can be referenced this way:
users[1].Name := "tonne"
MsgBox % users[1].Id " " users[1].Name
MsgBox % users[2].Id " " users[2].Name


HotKeyIt
  • Moderators
  • 7439 posts
  • Last active: Jun 22 2016 09:14 PM
  • Joined: 18 Jun 2008

the size of strcut created by Struct() is 36, but the size of buffer returned by QueryServiceConfig is variable. So how to handle it

As I understand you have to call the function setting lpServiceConfig := 0 and cbBufSize:=0 to find out the size of array.
After that Struct can accept an array of structures.
DllCall("QueryServiceConfig","PTR",hService,"PTR", (lpServiceConfig:=Struct("QUERY_SERVICE_CONFIG[" [color=red]cbBufSize [/color]"]"))[""],"UInt",cbBufSize,"PTR*",pcbBytesNeeded)
Do you have example code?

@tonne you can define array of structure straight away, I have added this example ;)
user := "TCHAR Id[10], TCHAR Name[30]" ; structure

users := Struct("user[2]") ; array of structs

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
MsgBox % users.2.Id " " users.2.Name


tonne
  • Members
  • 1654 posts
  • Last active: May 06 2014 06:22 PM
  • Joined: 06 Jun 2006
My aim was to avoid the somewhat awkward .1. notation (at the cost of extra code to initiate).

hughman
  • Members
  • 192 posts
  • Last active: Feb 14 2016 06:59 AM
  • Joined: 11 Feb 2007

Do you have example code?


cbSize is the whole capacity of the returned struct, not the number of the array. So lpServiceConfig:= Struct("QSC[" cbSize "]") should be wrong.
Service_QueryServiceConfig("Browser")
Service_QueryServiceConfig(ServiceName)
{
    SCM_HANDLE := DllCall("advapi32\OpenSCManager"
                        , "Int", 0 ;NULL for local
                        , "Int", 0
                        , "UInt", 0x1) ;SC_MANAGER_CONNECT (0x0001)    

    if !(SC_HANDLE := DllCall("advapi32\OpenService"
                            , "UInt", SCM_HANDLE
                            , "Str", ServiceName
                            , "UInt", 0x1)) ;SERVICE_QUERY_CONFIG (0x0001)
        result := -4 ;Service Not Found
    
    DllCall("advapi32\QueryServiceConfig"
        , "UInt", SC_HANDLE
        , "UInt", 0
        , "UInt", 0
        , "UIntP", cbSize)
        
    struct := Struct("")
    struct.QUERY_SERVICE_CONFIG := "
    (
        DWORD  dwServiceType;
        DWORD  dwStartType;
        DWORD  dwErrorControl;
        LPTSTR lpBinaryPathName;
        LPTSTR lpLoadOrderGroup;
        DWORD  dwTagId;
        LPTSTR lpDependencies;
        LPTSTR lpServiceStartName;
        LPTSTR lpDisplayName;
    )"
    QSC := struct.QUERY_SERVICE_CONFIG
    lpServiceConfig:= Struct("QSC[" . Ceil(cbSize/36) . "]")
    MsgBox % Struct(lpServiceConfig) ; why is the size null?
    DllCall("advapi32\QueryServiceConfig"
        , "UInt", SC_HANDLE
        , "UInt", lpServiceConfig[""]
        , "UInt", cbSize
        , "UIntP", 0)

    MsgBox % ServiceType := NumGet(lpServiceConfig[1], 0)
    MsgBox % StartType := lpServiceConfig[1].dwStartType


HotKeyIt
  • Moderators
  • 7439 posts
  • Last active: Jun 22 2016 09:14 PM
  • Joined: 18 Jun 2008
Thanks for example, I think I got it.
The buffer contains structure+data.
Service_QueryServiceConfig("Browser")
Service_QueryServiceConfig(ServiceName)
{
    SCM_HANDLE := DllCall("advapi32\OpenSCManager"
                        , "Int", 0 ;NULL for local
                        , "Int", 0
                        , "UInt", 0x1) ;SC_MANAGER_CONNECT (0x0001)    
	
    if !(SC_HANDLE := DllCall("advapi32\OpenService"
                            , "UInt", SCM_HANDLE
                            , "Str", ServiceName
                            , "UInt", 0x1)) ;SERVICE_QUERY_CONFIG (0x0001)
        result := -4 ;Service Not Found
    
    DllCall("advapi32\QueryServiceConfig"
        , "UInt", SC_HANDLE
        , "UInt", 0
        , "UInt", 0
        , "UIntP", cbSize)
		MsgBox % cbSize "`n" ErrMsg()
    struct := Struct("")
    struct.QUERY_SERVICE_CONFIG := "
    (
        DWORD  dwServiceType;
        DWORD  dwStartType;
        DWORD  dwErrorControl;
        LPTSTR lpBinaryPathName;
        LPTSTR lpLoadOrderGroup;
        DWORD  dwTagId;
        LPTSTR lpDependencies;
        LPTSTR lpServiceStartName;
        LPTSTR lpDisplayName;
    )"
		VarSetCapacity(QSC,cbSize)
    lpServiceConfig:= Struct("QUERY_SERVICE_CONFIG",&QSC)
    DllCall("advapi32\QueryServiceConfig"
        , "UInt", SC_HANDLE
        , "UInt", lpServiceConfig[""]
        , "UInt", cbSize
        , "UIntP", 0)
		
    MsgBox % StrGet(lpServiceConfig.lpBinaryPathName)
    MsgBox % StrGet(lpServiceConfig.lpLoadOrderGroup)
    MsgBox % StrGet(lpServiceConfig.lpDependencies)
    MsgBox % StrGet(lpServiceConfig.lpServiceStartName)
    MsgBox % StrGet(lpServiceConfig.lpDisplayName)
    MsgBox % ServiceType := lpServiceConfig.dwServiceType
    MsgBox % StartType := lpServiceConfig.dwStartType
}