Jump to content

Nested DllStructs


ProgAndy
 Share

Recommended Posts

Since it is not likely to be implemented in the next AutoIt-releases, I have created some functions to work with nested DllStructs. It is merely proof of concept, proper error checking and documentation is missing.

; -----------------------------------------------------------------------------------------
; Proof of concept: Implement nested DLLStructs using Arrays and normal DLLStructs
; Author: ProgAndy
; Nested Structs habe to be defined as Global Constants as TYPENAME or tagTYPENAME
; Access members via qualifier string: first_member.submember
; Array access with:                   member[2].submember[5]
;
; Access members via index:            #2.#1.#6
; Fetching Pointer for array element is possible: _DllStructGetPtr($struct, "array[3]")
; Member index and array index are 1-based.
; Supports STRUCT;...;ENDSCTRUCT of AutoIt-Beta + added naming structs and multiple nesting levels.
; The indexing is different:
;    char a;STRUCT name;int b;ENDSTRUCT;int x
;    Access-Qualifiers: a        = #1
;                       name.b   = #2.#1
;                       x        = #3
;
; _DllStructCreate accepts an optional 3rd parameter: a Scripting.Dictionary.
; This dictionary can contain your substructure definitions. (Key = TypeName, value = definition)
; -----------------------------------------------------------------------------------------

; ### Nested DllStructs #######################################################################################
#region Nested DLLStructs


Func _DLLStructCreate($sStruct, $pPtr = 0, $oSubStructs=0)
    ; Author: ProgAndy
    Local $sStructTag, $fClean=False
    If IsObj($oSubStructs) Then $fClean = True
    __DllStructExtractSubStructs($sStruct, $oSubStructs)
    Local $aDllStruct = __DLLStructParse($sStruct, $sStructTag, $oSubStructs)
    Local $err = @error
    If $fClean Then
        Local $a
        For $a In $oSubStructs.Keys
            If StringLeft($a, 27) = "A__XX__XX__UNNAMED_STRUCT__" Then $oSubStructs.Remove($a)
        Next
    EndIf
    If $err Then Return SetError(5, $err, 0)
    If @NumParams = 1 Or (@NumParams = 3 And $pPtr = 0) Then
        $aDllStruct[0][0] = DllStructCreate($sStructTag)
    Else
        $aDllStruct[0][0] = DllStructCreate($sStructTag, $pPtr)
    EndIf
    If @error Then Return SetError(@error, 0, 0)
    Return $aDllStruct
EndFunc   ;==>_DLLStructCreate

Func _DllStructGetData(ByRef $aDllStruct, $sQualifier)
    ; Author: ProgAndy
    Local $sName = __DllStructFindIndex($aDllStruct, $sQualifier)
    If @error Then Return SetError(@error, 0, 0)
    Local $iIndex = @extended
    If IsArray($aDllStruct[$sName][0]) Then
        Local $aRet = $aDllStruct[$sName][0]
        $aRet[0][0] = DllStructCreate($aDllStruct[$sName][1], DllStructGetPtr($aDllStruct[0][0], $sName))
        If $iIndex > 1 Then $aRet[0][0] = DllStructCreate($aDllStruct[$sName][1], DllStructGetPtr($aDllStruct[0][0], $sName) + DllStructGetSize($aRet[0][0]) * ($iIndex - 1))
        If $sQualifier = '' Then
            Return $aRet
        Else
            Return _DllStructGetData($aRet, $sQualifier)
        EndIf
    Else
        If $iIndex = 0 Then Return DllStructGetData($aDllStruct[0][0], $sName)
        Return DllStructGetData($aDllStruct[0][0], $sName, $iIndex)
    EndIf
EndFunc   ;==>_DllStructGetData

Func _DllStructGetPtr(ByRef $aDllStruct, $sQualifier="")
    ; Author: ProgAndy
    If @NumParams = 1 Then Return DllStructGetPtr($aDllStruct[0][0])
    Local $sName = __DllStructFindIndex($aDllStruct, $sQualifier)
    If @error Then Return SetError(@error, 0, 0)
    Local $iIndex = @extended
    If IsArray($aDllStruct[$sName][0]) Then
        If $iIndex <= 1 And $sQualifier = "" Then
            Return DllStructGetPtr($aDllStruct[0][0], $sName)
        Else
            Local $tTemp = DllStructCreate($aDllStruct[$sName][1], 1)
            If $iIndex < 1 Then $iIndex = 1
            Local $pPtr = DllStructGetPtr($aDllStruct[0][0], $sName) + ($iIndex - 1) * DllStructGetSize($tTemp)
            If $sQualifier = "" Then Return $pPtr
            $tTemp = DllStructCreate($aDllStruct[$sName][1], $pPtr)
            Local $aRet = $aDllStruct[$sName][0]
            $aRet[0][0] = $tTemp
            Return _DllStructGetPtr($aRet, $sQualifier)
        EndIf
    Else
        If $iIndex > 1 Then Return DllStructGetPtr($aDllStruct[0][0], $sName) + DllStructGetSize(DllStructCreate($aDllStruct[$sName][1], 1)) * ($iIndex-1)
        Return DllStructGetPtr($aDllStruct[0][0], $sName)
    EndIf
EndFunc   ;==>_DllStructGetPtr

Func _DllStructGetSize(ByRef $aDllStruct)
    ; Author: ProgAndy
    Return DllStructGetSize($aDllStruct[0][0])
EndFunc

Func _DllStructSetData(ByRef $aDllStruct, $sQualifier, $vValue)
    ; Author: ProgAndy
    Local $sName = __DllStructFindIndex($aDllStruct, $sQualifier)
    If @error Then Return SetError(@error, 0, 0)
    Local $iIndex = @extended
    If IsArray($aDllStruct[$sName][0]) Then
        Local $t = DllStructCreate($aDllStruct[$sName][1], DllStructGetPtr($aDllStruct[0][0], $sName))
        If $iIndex > 1 Then $t = DllStructCreate($aDllStruct[$sName][1], DllStructGetPtr($aDllStruct[0][0], $sName) + DllStructGetSize($t) * ($iIndex - 1))
        If $sQualifier = '' Then
            DllStructSetData(DllStructCreate("byte[" & DllStructGetSize($t) & "]", DllStructGetPtr($t)), 1, $vValue)
        Else
            Local $aRet = $aDllStruct[$sName][0]
            $aRet[0][0] = $t
            Return _DllStructSetData($aRet, $sQualifier, $vValue)
        EndIf
    Else
        If $iIndex = 0 Then Return DllStructSetData($aDllStruct[0][0], $sName, $vValue)
        Return DllStructSetData($aDllStruct[0][0], $sName, $vValue, $iIndex)
    EndIf
EndFunc   ;==>_DllStructSetData

Func __DllStructFindIndex(ByRef $aDllStruct, ByRef $sQualifier)
    ; Author: ProgAndy
    Local $sName, $iIndex = 0
    If IsInt($sQualifier) Then
        $sName = $sQualifier
        $sQualifier = ""
    Else
        $sName = __DllStructSplitNameIndexNext($sQualifier)
        $iIndex = @extended
    EndIf
    If IsInt($sName) Then
        Local $iBound = UBound($aDllStruct)-1
        If $sName < 1 Or $sName > $iBound Then Return SetError(1, 0, 0)
        ; Find index, skipping alignment bytes
        For $i = 1 To $sName
            If IsInt($aDllStruct[$i][0]) Then $sName += 1
            If $sName > $iBound Then Return SetError(1,0,0)
        Next
    Else
        $sName = __DllStructGetNameIndex($aDllStruct[0][1], $sName)
        If @error Then Return SetError(1, 0, 0)
    EndIf
    SetExtended($iIndex)
    Return $sName
EndFunc

Func __DllStructSplitNameIndexNext(ByRef $sName)
    ; Author: ProgAndy
    $sName = StringStripWS($sName, 8)
    Local $iPos = StringInStr($sName, ".", 1, 1), $aName
    If $iPos Then
        $aName = StringSplit(StringLeft($sName, $iPos - 1), '[]')
        $sName = StringTrimLeft($sName, $iPos)
    Else
        $aName = StringSplit(StringStripWS($sName, 8), '[]')
        $sName = ""
    EndIf
    If StringLeft($aName[1], 1) = "#" Then $aName[1] = Number(StringTrimLeft($aName[1], 1))
    If $aName[0] = 1 Then Return SetExtended(0, $aName[1])
    Return SetExtended($aName[2], $aName[1])
EndFunc   ;==>__DllStructSplitNameIndexNext

Func __DllStructGetNameIndex(ByRef $sData, $sName)
    ; Author: ProgAndy
    If $sName = "" Then Return SetError(2, 0, 0)
    Local $iPos = StringInStr($sData, ";" & StringLower($sName) & ";", 2, 1)
    If Not $iPos Then Return SetError(1, 0, 0)
    StringReplace(StringLeft($sData, $iPos), ";", ";", 0, 1)
    Return @extended
EndFunc   ;==>__DllStructGetNameIndex

Func __DLLStructParse($sStruct, ByRef $sStructTag, $oSubStructs=0, $iAlignment=0)
    ; Author: ProgAndy
    Local Static $sTypes = "|align|BYTE|BOOLEAN|CHAR|WCHAR|short|USHORT|WORD|int|long|BOOL|UINT|ULONG|DWORD|INT64|UINT64|ptr|HWND|HANDLE|float|double|INT_PTR|LONG_PTR|LRESULT|LPARAM|UINT_PTR|ULONG_PTR|DWORD_PTR|WPARAM|"
    Local $a = StringSplit($sStruct, ";")
    Local $sName, $r = "", $sItems = ";", $aDllStruct[UBound($a)*2][2], $iMemberIndx = 0
    $sStructTag = ""
    If StringStripWS($a[$a[0]], 8) = "" Then $a[0] -= 1
    If $a[0] = 0 Then Return SetError(2, 0, 0)
    Local $iOffset = 0, $iFirstAlign = $iAlignment;, $iAlignment = 0
    For $i = 1 To $a[0]
        $sName = StringRegExp($a[$i], "^\h*(\w+)\h*(\w*)\h*(?:\[(\d*)\])?\h*$", 1)
        If @error Then Return SetError(2, 0, 0)
        ReDim $sName[3]
        If $sName[0] = "" Then
            ; nothing
        ElseIf StringInStr($sTypes, '|' & $sName[0] & '|', 2, 1) Then
            $r &= $a[$i] & ";"
            If $sName[0] <> "align" Then
                $iMemberIndx += 1
                $aDllStruct[$iMemberIndx][1] = $sName[0]
                $sItems &= $sName[1] & ";"
                If $sName[2] < 1 Then $sName[2] = 1
                $iOffset += __DllStructAlignBytesType($iOffset, $sName[0], $iAlignment) & __DllStructGetTypeSize($sName[0])*$sName[2]
            Else
                $iAlignment = Number($sName[1])
                If $i = 1 Then $iFirstAlign = $iAlignment
            EndIf
        Else
            $iMemberIndx += 1
            Local $sSubTag, $sSubByteMember, $t
            $t = __DllStructSubCreate($sName[0], $sName[1], $sName[2], $sSubByteMember, $sSubTag, $oSubStructs, $iAlignment)
            If @error Then Return SetError(2, 0 , 0)

            Local $iAlign = __DllStructAlignBytesSubStruct($iOffset, $t, $iAlignment)
            If $iAlign Then
                $r &= "byte[" & $iAlign & "];"
                $aDllStruct[$iMemberIndx][0] = 1 ; mark alignment bytes
                $iMemberIndx += 1
                $iOffset += $iAlign
                $sItems &= ";"
            EndIf

            $r &= $sSubByteMember
            $aDllStruct[$iMemberIndx][1] = $sSubTag
            $aDllStruct[$iMemberIndx][0] = $t
            $sItems &= $sName[1] & ";"

            $iOffset += DllStructGetSize(DllStructCreate($sSubTag, 1)) * $sName[2]
        EndIf
    Next

    ; $iOffset is length of struct, make sure size is correct for array of structs
;~  Local $iAlign = __DllStructAlignBytesSubStruct($iOffset, $aDllStruct, $iFirstAlign)
    Local $iAlign = __DllStructAlignBytesSubStruct($iOffset, $aDllStruct, $iAlignment)
    If $iAlign Then
        $r &= "byte[" & $iAlign & "];"
        $iOffset += $iAlign
    EndIf

    $aDllStruct[0][1] = $sItems
    ReDim $aDllStruct[$iMemberIndx + 1][2]
    $sStructTag = $r
    Return $aDllStruct
EndFunc   ;==>__DLLStructParse

Func __DllStructSubCreate(ByRef $sType, ByRef $sName, ByRef $iCount, ByRef $sByteMember, ByRef $sStructTag, $oSubStructs = 0, $iAlignment = 0)
    ; Author: ProgAndy
    $sByteMember = ""
    Local $aDllStruct
    Select
        Case IsObj($oSubStructs) And $oSubStructs.Exists($sType)
            $aDllStruct = __DLLStructParse($oSubStructs($sType), $sStructTag, $oSubStructs, $iAlignment)
            If @error Then ContinueCase
        Case True
            $aDllStruct = __DLLStructParse(Eval("tag" & $sType), $sStructTag, $oSubStructs, $iAlignment)
            If @error Then ContinueCase
        Case Else
            $aDllStruct = __DLLStructParse(Eval($sType), $sStructTag, $oSubStructs, $iAlignment)
            If @error Then Return SetError(1, 0, 0)
            $sType = "tag" & $sType
    EndSelect
    Local $iSize = DllStructGetSize(DllStructCreate($sStructTag, 1))
    If @error Or $iSize = 0 Then Return SetError(1, 0, 0)
    If Number($iCount) < 1 Then $iCount = 1
    $sByteMember = "byte " & $sName & "[" & $iCount * $iSize & "];"
    Return $aDllStruct
EndFunc   ;==>__DllStructSubCreate

Func __DllStructAlignBytesSubStruct($iOffset, ByRef $aDllStruct, $iAlignment = Default)
    Return __DllStructAlignBytesType($iOffset, __DllStructFindLargestMember($aDllStruct), $iAlignment)
EndFunc

Func __DllStructFindLargestMember(ByRef $aDllStruct)
    Local $iLargest = 0, $iNew
    ; find largest member alignment
    For $i = 1 To UBound($aDllStruct)-1
        If IsArray($aDllStruct[$i][0]) Then
            $iNew = __DllStructFindLargestMember($aDllStruct[$i][0])
        Else
            $iNew = __DllStructGetTypeSize($aDllStruct[$i][1])
        EndIf
        If $iNew > $iLargest Then $iLargest = $iNew
    Next
    Return $iLargest
EndFunc

Func __DllStructAlignBytesType($iOffset, $sType, $iAlignment=Default)
    If IsInt($sType) Then
        Local $iLen = $sType
    Else
        Local $iLen = __DllStructGetTypeSize($sType)
    EndIf
    If IsKeyword($iAlignment) Or $iAlignment < 1 Then $iAlignment = 8
    If $iLen = 1 Or $iAlignment = 1 Then
        Return 0
    ElseIf $iAlignment > $iLen Then
        $iOffset = $iLen - Mod($iOffset, $iLen)
        If $iOffset = $iLen Then Return 0
    Else
        $iOffset = $iAlignment - Mod($iOffset, $iAlignment)
        If $iOffset = $iAlignment Then Return 0
    EndIf
    Return $iOffset
EndFunc

Func __DllStructGetTypeSize($sType)
    Local Static $iPtrSize = DllStructGetSize(DllStructCreate("ptr", 1))
    Switch $sType
        Case "BYTE", "BOOLEAN", "CHAR"
            Return 1
        Case "WCHAR", "short", "USHORT", "WORD"
            Return 2
        Case "int", "long", "BOOL", "UINT", "ULONG", "DWORD", "float"
            Return 4
        Case "INT64", "UINT64", "double"
            Return 8
        Case "ptr", "HWND", "HANDLE", "INT_PTR", "LONG_PTR", "LRESULT", "LPARAM", "UINT_PTR", "ULONG_PTR", "DWORD_PTR", "WPARAM"
            Return $iPtrSize
    EndSwitch
    Return SetError(1,0,0)
EndFunc

Func __DllStructExtractSubStructs(ByRef $sStruct, ByRef $oSubStructs, $iStart = 0)
    ; ProgAndy
    Local Static $counter = 0
    $sStruct = StringReplace(StringReplace(StringRegExpReplace($sStruct, "\s+", " "), "; ", ";", 0, 1), " ;", ";", 0, 1)
    $sStruct = StringReplace(";"&$sStruct&";", ";;", ";", 0, 1)
    If $iStart < 1 Then $iStart = StringInStr($sStruct, ";STRUCT", 2, 1)
    Local $iEnd, $iStart2, $iNameEnd, $sName
    While $iStart
        If Not IsObj($oSubStructs) Then $oSubStructs = ObjCreate("Scripting.Dictionary")
        $iNameEnd = StringInStr($sStruct, ";", 2, 1, $iStart+7)
        If Not $iNameEnd Then Return SetError(1, 0, 0)
        $sName = StringMid($sStruct, $iStart+7, $iNameEnd-$iStart-7)
        If $sName <> "" And Not StringRegExp($sName, "^\h\w+$") Then Return SetError(2,0,0)
        $iEnd = StringInStr($sStruct, ";ENDSTRUCT;", 2, 1, $iNameEnd)
        $iStart2 = StringInStr($sStruct, ";STRUCT", 2, 1, $iNameEnd)
        If $iStart2 > 0 And $iEnd > $iStart2 Then
            __DllStructExtractSubStructs($sStruct, $oSubStructs, $iStart2)
        Else
            Local $sTemp = StringLeft($sStruct,  $iStart)
            Local $sSub = StringMid($sStruct, $iNameEnd+1, $iEnd - $iNameEnd - 1)
            Local $sTemp2 = StringTrimLeft($sStruct, $iEnd+9)
            __DllStructExtractSubStructs($sSub, $oSubStructs)
            Local $sAlign = ""
            Local $iAlign = StringInStr(";" & $sSub, ";align ", 2, -1)
            If $iAlign Then
                Local $iCut = StringInStr($sSub & ";", ";", 1, 1, $iAlign)
                $sAlign = ";" & StringMid($sSub, $iAlign, $iCut-$iAlign)
            EndIf
            $counter += 1
            $oSubStructs("A__XX__XX__UNNAMED_STRUCT__" & $counter) = $sSub
            $sStruct = $sTemp & "A__XX__XX__UNNAMED_STRUCT__" & $counter & $sName & $sAlign & $sTemp2
        EndIf
        $iStart = StringInStr($sStruct, ";STRUCT", $iStart)
    WEnd
    If @NumParams = 2 Then $sStruct = StringMid($sStruct, 2, StringLen($sStruct)-2)
EndFunc

#endregion Nested DLLStructs

; ### End Nested DllStructs ###################################################################################

Some examples:

Global Const $SUBTESTTYPE = "wchar s[12]"
Global Const $tagTEST = "int test;int blub; SUBTESTTYPE hi[3]"

$x = _DLLStructCreate("byte[2]; TEST x")

_DllStructSetData($x, "x.blub", 23)
MsgBox(0, 'x.blub = #2.#2', _DllStructGetData($x, "#2.#2"))
MsgBox(0, 'Ptr to #1 and #1[2]', _DllStructGetPtr($x, "#1") & @CRLF &  _DllStructGetPtr($x, "#1[2]"))
_DllStructSetData($x, "x.hi[1].s", "hello")
_DllStructSetData($x, "x.hi[3].s", "bb")
_DllStructSetData($x, "x.hi[2].s", ":)")
MsgBox(0, 'x.hi.s = x.hi[1].s', _DllStructGetData($x, "x.hi.s"))
MsgBox(0, 'x.hi[2].s', _DllStructGetData($x, "x.hi[2].s"))
MsgBox(0, 'x.hi[3].s', _DllStructGetData($x, "x.hi[3].s"))

Edit: Alignment does not work correctly I'm not sure how to fix it yet.

Edit: Implemented aligment calculation, including align keyword. Each nested structure has its own alignment, always calculated relative to structure beginning. I don't know if this is right.

Edit: Alignment correction + some new features.

Edited by ProgAndy

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Link to comment
Share on other sites

I implemented alignment, not sure if it is really working. (Currently only for align 8 = default)

Edit: Done.

Edited by ProgAndy

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Link to comment
Share on other sites

I just hacked it together, many things should be improved :huh2:

Local Static $iPtrSize = DllStructGetSize(DllStructCreate("ptr", 1))
Edited by ProgAndy

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Link to comment
Share on other sites

Thanks to jchd I was able to correct some alignment problems. There are some new features, too. Read the file header :huh2:

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Link to comment
Share on other sites

Man, I wish I understood half the things you guys talk about. It took me a minute to figure out what you meant bout nested structures; that it was a structure with a pointer to a structure.

I still dont get what alignment is; Is it like where you try and keep all your memory thingys in nice neat blocks (of 4, 8, 16 bytes?).

ongoing projects:-firestorm: Largescale P2P Social NetworkCompleted Autoit Programs/Scripts: Variable Pickler | Networked Streaming Audio (in pure autoIT) | firenet p2p web messenger | Proxy Checker | Dynamic Execute() Code Generator | P2P UDF | Graph Theory Proof of Concept - Breadth First search

Link to comment
Share on other sites

Man, I wish I understood half the things you guys talk about. It took me a minute to figure out what you meant bout nested structures; that it was a structure with a pointer to a structure.

It is not a structure with a pointer to a structure. It means, that the structure has a complete structure as a member. This are two completely different things:

Ptr to a struct:

$x = DLLStructCreate("dword a;ptr substruct")
$y = DLLStructCreate("int a; dword c")
DLLStructSetData($x, "substruct", DLLStructGetPtr($y)

And nested structure

$tagSUBSTRUCT = "int a; dword c"
$tagX = "dword a; tagSUBSTRUCT substruct"
$x = _DllStructCreate($tagX) ; does not work with native DLLStruct, but my functions allow it

I still dont get what alignment is; Is it like where you try and keep all your memory thingys in nice neat blocks (of 4, 8, 16 bytes?).

That is correct. Edited by ProgAndy

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Link to comment
Share on other sites

  • 6 months later...

ProgAndy how deep can you nest structures? I have some code from another application and it apears to go quite deep, although I maybe missunderstood.

I have

Global Const $tagPOINTPAPERINFO = "int PaperSizeX;int PaperSizeY;int"
Global Const $tagPOINTIMAGEINFO = "int ImageDataX;int ImageDataY;int OffsetX;int OffsetY"
Global Const $tagPOINTCOLORINFO = "short nSharpness; int nReserved"
Global Const $tagCnaSendPring = "BOOL"

$tagPrintInfo = "WORD Copies;tagPOINTPAPERINFO PaperInfo;tagPOINTIMAGEINFO ImageInfo;tagPOINTCOLORINFO ColorInfo;short nPrintMode"
$printInfo = _DllStructCreate($tagPrintInfo)

DllStructSetData($tagPrintInfo,"Copies",1)

_DllStructSetData($printInfo,"ImageInfo.ImageDataX",$WIDTH_K)
_DllStructSetData($printInfo,"ImageInfo.ImageDataY",$HEIGHT_K)
_DllStructSetData($printInfo,"ImageInfo.OffsetX",0)
_DllStructSetData($printInfo,"ImageInfo.OffsetY",0)

_DllStructSetData($printInfo,"PaperInfo.PaperSizeX",$PAPER_WIDTH_K)
_DllStructSetData($printInfo,"PaperInfo.PaperSizeY",$PAPER_HEIGHT_K)

_DllStructSetData($printInfo,"ColorInfo.nSharpness",$SHARPNESS_DEFAULT)
DllStructSetData($tagPrintInfo,"nPrintMode",$HI_SPEED)

But the sample I have shows..

;printInfo.PrintSetting.ImageInfo.ImageData.x = resultImageSize.x;
;printInfo.PrintSetting.ImageInfo.ImageData.y = resultImageSize.y;
;printInfo.PrintSetting.ImageInfo.Offset.x = 0;
;printInfo.PrintSetting.ImageInfo.Offset.y = 0;
;printInfo.PrintSetting.PaperInfo.PaperSize.x = paperSize.x;
;printInfo.PrintSetting.PaperInfo.PaperSize.y = paperSize.y;

printInfo.PrintSetting is passed to the next function ie SetUpPrint(printInfo.PrintSetting)

I think I need 1 more nest for the tagPOINTs PaperInfo.PaperSize.X is this possible?

Link to comment
Share on other sites

In theory the nesting level is unlimited :)

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...