AutoIt selbst nimmt uns die Verwaltung von Datentypen ab, es gibt nur einen Typ (Variant), der funktionsgemäß verwendet wird.
Das ist bei der Arbeit mit Dll-Aufrufen anders. Hier ist eine Angabe der verwendeten Datentypen zwingend erforderlich.
Typ | Details |
---|---|
none | kein Wert (nur gültig für Rückgabetyp - entspricht void in C) |
BYTE | 8Bit (1Byte) Integer vorzeichenlos |
BOOLEAN | 8Bit (1Byte) Integer vorzeichenlos |
short | 16Bit (2Byte) Integer |
USHORT | 16Bit (2Byte) Integer vorzeichenlos |
WORD | 16Bit (2Byte) Integer vorzeichenlos |
int | 32Bit (4Byte) Integer |
long | 32Bit (4Byte) Integer |
BOOL | 32Bit (4Byte) Integer |
UINT | 32Bit (4Byte) Integer vorzeichenlos |
ULONG | 32Bit (4Byte) Integer vorzeichenlos |
DWORD | 32Bit (4Byte) Integer vorzeichenlos |
INT64 | 64Bit (8Byte) Integer |
UINT64 | 64Bit (8Byte) Integer vorzeichenlos |
ptr | ein allgemeiner Pointer (void *) |
HWND | ein Fenster Handle (Pointer) |
HANDLE | ein Handle (Pointer) |
float | eine Kommazahl einfacher Genauigkeit |
double | eine Kommazahl doppelter Genauigkeit |
INT_PTR, LONG_PTR, LRESULT, LPARAM | ein Integer, groß genug um einen Pointer zu speichern, wenn eine x86 oder x64 Versions von AutoIt läuft |
UINT_PTR, ULONG_PTR, DWORD_PTR, WPARAM | ein unsigned Integer, groß genug um einen Pointer zu speichern, wenn eine x86 oder x64 Versions von AutoIt läuft |
str | ein ANSI String (Speicher für 65536 Zeichen wird reserviert) |
wstr | ein UNICODE wide character String (Speicher für 65536 Zeichen wird reserviert) |
struct | eine mit DllStructCreate() erstellte Struktur |
* | Füge * an das Ende eines anderen Typs um ihn ByRef zu erstellen. Z.B.: "int*" erstellt einen Pointer zu einem "int" Typ. |
WINDOWS API Type | AutoIt Type |
---|---|
LPCSTR/ LPSTR | str |
LPCWSTR/ LPWSTR | wstr |
LPVOID | ptr |
LPxyz | xyz* |
HINSTANCE | handle |
HRESULT | long |
LONGLONG/ LARGE_INTEGER | INT64 |
ULONGLONG/ ULARGE_INTEGER | UINT64 |
SIZE_T | ULONG_PTR |
Eigentlich fehlen noch 2 Typen:
Für ANSI-Zeichen "char" und für UNICODE "wchar". Wir finden diese aber in der Auflistung der Strukturdatentypen.
Beide Typen repräsentieren 1 einzelnes Zeichen. Wie lassen sich damit aber Zeichenketten darstellen? Dazu definiert man ein Array
von Zeichen (z.B. char[20]). Wichtig bei der Verwendung von UNICODE: Zeichenketten werden dort NULL-terminiert, d.h. nach den Zeichen des Strings folgt der ASCII-Wert 0
um anzuzeigen, dass hier der String endet. Somit muss die Anzahl von "wchar" um 1 größer sein als die Stringlänge. Wenn in der Funktionsbeschreibung
angegeben wird, dass der String nullterminiert ist, gilt das ebenso bei ANSI.
Allerdings erleichtert uns AutoIt die Verwaltung dieser beiden Typen durch
Verwendung von "str" und "wstr".
Da erst ab Windows 2000 volle UNICODE Unterstützung existiert, sind fast alle Stringfunktionen mit ANSI- und UNICODE- Version
ausgestattet. Sie werden unterschieden durch den Zusatz "A" für ANSI-Funktion und "W" (wide char) für UNICODE-Funktion. Also "StringFunktionA" und "StringFunktionW".
Wenn ihr nicht gerade für Win98 programmiert (ha-ha), ist es eigentlich auch nicht sinnvoll, die ANSI-Varianten der Funktionen zu verwenden. Mein Tipp: Setzt nach Möglichkeit die UNICODE-Variante ein.
Wenn wir mit Dll arbeiten wollen, müssen wir auch über Strukturen reden.
Was also ist eine Struktur?
Eine Struktur weist Ähnlichkeit mit einem Array auf. D.h., unter einem Variablennamen werden 1 oder mehrere Werte gespeichert.
Was sind die Unterschiede?
Im Array ist es egal, was für Datentypen die einzelnen Werte haben. Sie können dort auch ständig wechseln. Die Anzahl der Element in einem Array ist niemals fix,
mit ReDim läßt sich die Größe zur Laufzeit ändern.
Ganz anders die Struktur. Hier bestimme ich beim Erstellen der Struktur, welche Datentypen die Inhalte haben dürfen. Das ist wichtig, da in den Dll-Funktionen genau
festgelegt ist, welche Datentypen an welcher Position erwartet werden. Die Anzahl der Strukturelemente kann zur Laufzeit nicht verändert werden.
AutoIt hat schon eine Vielzahl von Strukturen implementiert. In der Hilfe findet ihr diese unter
<User Defined Functions> <StructureConstants Management>.
Als Hauptinformationsquelle verwende ich die Windows Api Referenz.
Dort findet ihr neben allen API-Funktionen die zugehörigen Messages, Notifikationen, Strukturen und Konstanten.
Zum Erstellen einer Struktur stehen in AutoIt folgende Datentypen zur Verfügung
Type | Details |
---|---|
BYTE | 8Bit (1Byte) Zeichen vorzeichenlos |
BOOLEAN | 8Bit (1Byte) Zeichen vorzeichenlos |
CHAR | 8Bit (1Byte) ASCII-Zeichen |
WCHAR | 16Bit (2Byte) UNICODE-Zeichen, (wide char) |
short | 16Bit (2Byte) Integer mit Voreichen |
USHORT | 16Bit (2Byte) Integer vorzeichenlos |
WORD | 16Bit (2Byte) Integer vorzeichenlos |
int | 32Bit (4Byte) Integer mit Vorzeichen |
long | 32Bit (4Byte) Integer mit Vorzeichen |
BOOL | 32Bit (4Byte) Integer mit Vorzeichen |
UINT | 32Bit (4Byte) Integer vorzeichenlos |
ULONG | 32Bit (4Byte) Integer vorzeichenlos |
DWORD | 32Bit (4Byte) Integer vorzeichenlos |
INT64 | 64Bit (8Byte) Integer mit Vorzeichen |
UINT64 | 64Bit (8Byte) Integer vorzeichenlos |
ptr | 32 oder 64Bit Integer vorzeichenlos (in Abhängigkeit zur benutzten AutoIt Version x86 oder x64) |
HWND | 32Bit (4Byte) Integer |
HANDLE | 32Bit (4Byte) Integer |
float | 32Bit (4Byte) Fließkommazahl |
double | 64Bit (8Byte) Fließkommazahl |
INT_PTR, LONG_PTR, LRESULT, LPARAM | 32 oder 64Bit Integer mit Vorzeichen (in Abhängigkeit zur benutzten AutoIt Version x86 oder x64) |
UINT_PTR, ULONG_PTR, DWORD_PTR, WPARAM | 32 oder 64Bit Integer vorzeichenlos (in Abhängigkeit zur benutzten AutoIt Version x86 oder x64) |
STRUCT | Die nachfolgenden Datentypen werden ausgerichtet nach den Regeln der C-Deklaration |
ENDSTRUCT | Ende einer Sammlung von Datentypen |
ALIGN | n-Bytes Begrenzung an der Datentypen ausgerichtet werden |
Eine Struktur erstellen wir mit:
In der allgemeinen Definition ist als optionaler Parameter noch Pointer angegeben. Darauf gehe ich im Punkt Pointer näher ein.
Die Struktur wird in einem String definiert. Der String kann neben dem Datentyp auch noch einen Bezeichner führen. Dieser ist aber nicht zwingend erforderlich.
Im folgenden Bsp. enthält die Struktur 4 Integerwerte. Die Definition eines Wertes lautet: Datentyp-Leerzeichen-Bezeichner, die Abgrenzung zwischen den Werten erfolgt durch ein Semikolon.
Und zum Vergleich die identische Struktur, ohne Bezeichner.
Um Werte an eine Struktur zu übergeben, verwenden wir die Funktion
Struct | ist die Variable, der mit "DllStructCreate" erstellten Struktur (oder eine Struktur aus einem Funktionsaufruf) |
Element | ist entweder der 1-basierte Index des Wertes in der Struktur oder der Bezeichner |
value | ist der zu übergebende Wert |
index | [optional] ist das Element ein Array, kann auf ein einzelnes Arrayelement mit diesem 1-basierten Index zugegriffen werden |
Mit Einführung der Version 3.3.10.0 gab es Syntaxänderungen. Dadurch ist ein geänderter Zugriff auf Strukturelemente möglich. Die Bsp. sind dahingehend angepasst.
Die Verwendung der Punktnotation (Strukturname.Feld) ist zwar syntaktisch möglich, ganz offiziell aber kein sicherer Zugriffsstandard. Sollte es also damit mal nicht klappen, ist auf die Standardsyntax zurückzugreifen.
DllStructSetData ( $struct, "X1", 20 )
DllStructSetData ( $struct, "Y1", 10 )
DllStructSetData ( $struct, "X2", 200 )
DllStructSetData ( $struct, "Y2", 120 )
; oder
DllStructSetData ( $struct, 1, 20 )
DllStructSetData ( $struct, 2, 10 )
DllStructSetData ( $struct, 3, 200 )
DllStructSetData ( $struct, 4, 120 )
; oder (ab v3.3.10.0)
$struct.X1 = 20
$struct.Y1 = 10
$struct.X2 = 200
$struct.Y2 = 120
$struct1 = DllStructCreate ( "int;int;int;int" )
DllStructSetData ( $struct1, 1, 20 )
DllStructSetData ( $struct1, 2, 10 )
DllStructSetData ( $struct1, 3, 200 )
DllStructSetData ( $struct1, 4, 120 )
; entweder
DllStructSetData ( $struct2, 1, "AutoIt" )
; oder
DllStructSetData ( $struct2, 1, "A", 1 )
DllStructSetData ( $struct2, 1, "u", 2 )
DllStructSetData ( $struct2, 1, "t", 3 )
DllStructSetData ( $struct2, 1, "o", 4 )
DllStructSetData ( $struct2, 1, "I", 5 )
DllStructSetData ( $struct2, 1, "t", 6 )
Um Werte aus einer Struktur zu lesen, verwenden wir die Funktion
Struct | ist die Variable, der mit "DllStructCreate" erstellten Struktur (oder eine Struktur aus einem Funktionsaufruf) |
Element | ist entweder der 1-basierte Index des Wertes in der Struktur oder der Bezeichner |
index | [optional] ist das Element ein Array, kann auf ein einzelnes Arrayelement mit diesem 1-basierten Index zugegriffen werden |
Diese Funktion ist das exakte Gegenstück zu "DllStructSetData".
DllStructSetData ( $struct2, 1, "AutoIt" )
; Ausgabe der Werte
; entweder
$data = DllStructGetData ( $struct2, 1 ) ; liefert "AutoIt"
; oder
$data = DllStructGetData ( $struct2, 1, 1 ) ; liefert "A"
$data = DllStructGetData ( $struct2, 1, 2 ) ; liefert "u"
$data = DllStructGetData ( $struct2, 1, 3 ) ; liefert "t"
$data = DllStructGetData ( $struct2, 1, 4 ) ; liefert "o"
$data = DllStructGetData ( $struct2, 1, 5 ) ; liefert "I"
$data = DllStructGetData ( $struct2, 1, 6 ) ; liefert "t"
Bei dem Pointer handelt es sich nicht um die Jagdhundrasse Pointer ( :P Scherz am Rande ), sondern um eine Variable, die auf eine Speicheradresse verweist. Ich hatte ja bereits beim Erstellen der Struktur darauf hingewiesen.
Nehmen wir an, irgendeine WM_Message liefert uns über den Parameter "lParam" Informationen zu einer Desktopkoordinate. Aus der Beschreibung zu der Message wissen wir, dass die Werte in der Datenstruktur "int;int" übergeben werden.
Wir müssen also beim Erstellen der Struktur den Pointer mit angeben, sodass die Werte, auf die der Pointer verweist, an die Struktur übergeben werden können.
So könnte das dann aussehen:
Local $struct = DllStructCreate ( "int;int", $lParam ) ; lParam wird als Pointer übergeben
ConsoleWrite ( "Koordinate X = " & DllStructGetData ( $struct, 1 ) & @LF )
ConsoleWrite ( "Koordinate Y = " & DllStructGetData ( $struct, 2 ) & @LF )
;....
;....
EndFunc
Im umgekehrten Fall haben wir eine Struktur und die Funktion erwartet einen Pointer dafür. Somit müssen wir einen Pointer erstellen, der auf diese Struktur verweist. Der Pointer kann entweder auf die gesamte Struktur oder auf ein einzelnes Element der Struktur verweisen. Dafür nutzen wir in AutoIt die Funktion
Struct | ist die Variable, der mit "DllStructCreate" erstellten Struktur (oder eine Struktur aus einem Funktionsaufruf) |
Element | [optional] der 1-basierte Index des Elementes aus der Struktur auf das der Pointer zeigen soll |
Nehmen wir an, wir haben folgende Struktur: "int;int;int;ptr", wobei der Pointer auf eine "int;int"-Struktur verweisen soll. Das sieht dann so aus:
$pointer = DllStructGetPtr ( $struct ) ; Pointer für die Struktur
$struct1 = DllStructCreate ( "int;int;int" & $pointer ) ; Struktur mit Pointer
So sieht ein DllCall in AutoIt allgemein aus:
DLL | die Dll, die wir nutzen möchten |
Rückgabetyp | der Datentyp, den der Dll-Aufruf zurückliefert |
Funktionsname | die Funktion aus der Dll, die wir aufrufen möchten |
Parametertyp | [optional] Datentyp des Parameters |
Parametername | [optional] Name des Parameters |
... | [optional] weitere Parametertypen/ -namen |
Woher weiß ich, ob mein Aufruf erfolgreich war?
Dazu werte ich die Rückgabe des DllCall aus. Hierbei ist folgendes zu beachten:
Die Funktion DllCall() liefert ein Array zurück. Das Array enthält als erstes Element (Array[0]) den Ergebniswert des DllCall. Dieser ist im Fehlerfall = 0, ansonsten <> 0. Für jeden Parameter des Aufrufs wird ein Arrayelement erstellt. Sofern dieser Parameter vom Aufruf nicht verändert wird, ist also der übergebene Parameterwert auch im Ergebnisarray.
Für die Fehlerabfrage empfiehlt sich also:
If $return[0] = 0 Then ; Fehler
Es kommt vor, dass ein Dll-Aufruf als Element ein Array zur Übergabe/Übernahme von Werten verlangt.
Einen Strukturdatentyp "array" haben wir nicht zur Verfügung. Aber wir wissen, dass Datentypen in Arrayform übergeben werden können: "typ[anzahl]".
Somit bietet sich an, ein Pointerarray zu erstellen, dessen Elemente jeweils auf einen Wert unseres Datenarrays verweisen.
Die Struktur sieht dann folgendermaßen aus:
"Pointer-Array[Anzahl_Arrayelemente];je_Arrayelement_ein_Strukturelement...."
Nehmen wir an, das ist unsere Dll-Definition:
DLL | Meine.Dll |
Funktion | IrgendWas |
Returntyp | long |
Parameter | ElementName |
Parameter Typ | String Array |
Die Strings als Zeichenketten im Array
Local $countElements = 2
Local $maxStringLen = 255
Local $structChar = "ptr[" & $countElements & "];" & _
"char[" & $maxStringLen & "];" & _
"char[" & $maxStringLen & "]"
Local $arrChar = DllStructCreate ( $structChar )
Die Struktur ist erstellt und wird nun mit Daten befüllt
DllStructSetData ( $arrChar, 1, DllStructGetPtr ( $arrChar, 2 ), 1 )
DllStructSetData ( $arrChar, 1, DllStructGetPtr ( $arrChar, 3 ), 2 )
; die Array-Werte eintragen
DllStructSetData ( $arrChar, 2, Element_1 )
DllStructSetData ( $arrChar, 3, Element_2 )
Und so sieht es dann in der Struktur aus:
ptr[2] | char[255] | char[255] |
Pointer1 | E | E |
Pointer2 | l | l |
e | e | |
m | m | |
e | e | |
n | n | |
t | t | |
_ | _ | |
1 | 2 |
Jetzt übergeben wir das Array (bzw. den Pointer, der auf das Array verweist) an den DllCall.
In unserer Struktur $arrChar ist das erste Strukturelement das Array mit den Pointern, welche auf die eingetragenen Werte verweisen.
Als 'Nachweis', dass tatsächlich über das Pointerarray auf die Werte zugegriffen wird, lesen wir die Daten aus, indem wir eine neue Struktur erstellen, die über die verwendeten Pointer befüllt wird.
Local $ptrInDll = DllStructGetPtr ( $arrChar, 1 )
; Arraystruktur zum Lesen nachstellen
Local $structPtr = DllStructCreate ( "ptr[2]", $ptrInDll )
; Pointer des Wertearrays auslesen
Local $ptrElement1 = DllStructGetData ( $structPtr, 1, 1 )
Local $ptrElement1 = DllStructGetData ( $structPtr, 1, 2 )
; Struktur zum Lesen der Werte erstellen und aus Pointern befüllen
Local $structRead
$structRead = DllStructCreate ( "char[" & $maxStringLen & "]", $ptrElement1 )
ConsoleWrite ( DllStructGetData ( $structRead, 1 ) & @LF )
$structRead = DllStructCreate ( "char[" & $maxStringLen & "]", $ptrElement2 )
ConsoleWrite ( DllStructGetData ( $structRead, 1 ) & @LF )
Häufig verlangen Funktionen kein Pointerarray, sondern ein Bytearray. Hier zeige ich, wie sich das umsetzen läßt.
; == 1. Speichergröße für ein Element ermitteln
$SIZE = DllStructGetSize ( DllStructCreate ( "int", 1 ) )
; die "1" ist keine wirkliche Pointeradresse, sondern wird nur als Basis für die Berechnung genutzt
; == 2. Byte-Array mit gewünschter Anzahl Elementen erstellen
$aByte = DllStructCreate ( "byte[" & $SIZE *5 & "]" )
; == 3. Strukturen für jedes Arrayelement erstellen
$Element_0 = DllStructCreate ( "int", DllStructGetPtr ( $aByte ) )
$Element_1 = DllStructCreate ( "int", DllStructGetPtr ( $aByte + $SIZE ) )
$Element_2 = DllStructCreate ( "int", DllStructGetPtr ( $aByte + $SIZE *2 ) )
$Element_3 = DllStructCreate ( "int", DllStructGetPtr ( $aByte + $SIZE *3 ) )
$Element_4 = DllStructCreate ( "int", DllStructGetPtr ( $aByte + $SIZE *4 ) )
; == Alternativ die Strukturen in einem Datenarray führen
Local $aStructData[4]
For $i = 0 To 4
$aStructData[$i] = DllStructCreate ( "int", DllStructGetPtr ( $aByte + $SIZE *$i ) )
Next
; == 4. Werte eintragen
DllStructSetData ( $aStructData[0], 1, 123 ; usw. für die anderen Elemente
Das so erstellte und bei Bedarf mit Werten befüllte Array wird dann über einen Pointer an die Dll übergeben
Beep( )
Wir werden jetzt die Funktion Beep( ) als DllCall ausführen. Die Funktion verwendet 2 Parameter: Frequenz und Dauer. Wir führen den Aufruf mit 500 Hz über 700 ms aus.
Hier die Originalbeschreibung aus der Windows API-Referenz:
"Funktionsname" "DLL" ["Alias-Funktionsname"] ("Parametername", "Parametertyp", ...) Rückgabetyp
Der Dll Aufruf in AutoIt erwartet, wie schon gezeigt, folgende Darstellung:
Suchen wir uns die notwendigen Angaben zusammen:
DLL | kernel32 |
Rückgabetyp | long |
Funktionsname | Beep (der Alias braucht nur verwendet werden, wenn er vom Funktionsnamen abweicht) |
Parametertyp | long |
Parametername | dwFreq (500) |
Parametertyp | long |
Parametername | dwDuration (700) |
Und so sieht nun der fertige Aufruf aus:
Wir wollen per MsgBox den Text "Hallo Welt!" ausgeben.
Hier wiederum die Infos aus der Windows API-Referenz zur MsgBox:
hWnd | hier können wir 0 übergeben, da wir die Nachricht allgemein anzeigen |
lpText | hier kommt unser Text rein: "Hallo Welt!" |
lpCaption | das ist der Titel der MsgBox, wir nehmen: "Test" |
uType | wir brauchen nur den OK-Button, das ist die 0 |
So sieht es fertig aus:
Ihr seht in dieser Funktion den Suffix "A" am Funktionsnamen. Für UNICODE wäre also folgender Aufruf zuständig.
; Wenn der Standardtitel für die Messagebox verwendet werden soll, steht ab v3.3.10.0 das Schlüsselwort Null zur Verfügung
DllCall ( "user32", "long", "MessageBoxW", "hwnd", 0, "wstr", "Hallo Welt!", "wstr", Null, "long", 0 )
Nun zu einer Funktion, die uns mehrere Ergebniswerte liefert.
Wieder die Beschreibung aus der API-Referenz:
Hier gehts nun richtig zur Sache. :=)
In den Parameterbeschreibungen findet ihr fast überall: "Points to ...". Das bedeutet für uns, dass auf einen Pointer verwiesen wird, der zur Übergabe/Übernahme von Werten benötigt wird.
Wie das umzusetzen ist, haben wir ja schon bei den Themen Struktur und Pointer kennengelernt.
Hier die Vorbereitung der Parameter:
$Vol = "C:\"
; Erstellen der Struktur zur Übergabe (1 größer als Stringlänge!)
$lpRootPathName = DllStructCreate ( "wchar[" & StringLen ( $Vol ) +1 & "]" )
; Füllen der Struktur
DllStructSetData ( $lpRootPathName, 1, $Vol )
; Erstellen der Struktur zur Aufnahme des VolumeNamens
$lpVolumeNameBuffer = DllStructCreate ( "wchar[255]" )
; Angabe der Länge des Aufnahmepuffers für VolumeName
$nVolumeNameSize = 255
; Erstellen der Struktur zur Aufnahme der Seriennummer
$lpVolumeSerialNumber = DllStructCreate ( "wchar[255]" )
; Erstellen der Struktur zur Aufnahme der max. Komponentenlänge
$lpMaximumComponentLength = DllStructCreate ( "dword" )
; Erstellen der Struktur zur Aufnahme der FileSystemFlags
$lpFileSystemFlags = DllStructCreate ( "dword" )
; Erstellen der Struktur zur Aufnahme des FileSystemNamens
$lpFileSystemNameBuffer = DllStructCreate ( "wchar[255]" )
; Angabe der Länge des Aufnahmepuffers für FileSystemName
$nFileSystemNameSize = 255
Das ist dann der zugehörige Aufruf:
"ptr" , DllStructGetPtr ( $lpRootPathName ), _
"ptr" , DllStructGetPtr ( $lpVolumeNameBuffer ), _
"long", $nVolumeNameSize, _
"ptr" , DllStructGetPtr ( $lpVolumeSerialNumber ), _
"ptr" , DllStructGetPtr ( $lpMaximumComponentLength ), _
"ptr" , DllStructGetPtr ( $lpFileSystemFlags ), _
"ptr" , DllStructGetPtr ( $lpFileSystemNameBuffer ), _
"long", $nFileSystemNameSize )
Und hier die Auswertung der ermittelten Daten:
; Um auf die Werte zuzugreifen, werden diese mit "DllStructGetData( )" ausgelesen.
ConsoleWrite ( "Volume name: " & DllStructGetData ( $lpVolumeNameBuffer, 1 ) & @LF )
ConsoleWrite ( "Serial number: " & DllStructGetData ( $lpVolumeSerialNumber, 1 ) & @LF )
ConsoleWrite ( "Max. Component Length: " & DllStructGetData ( $lpMaximumComponentLength, 1 ) & @LF )
ConsoleWrite ( "File System: " & DllStructGetData ( $lpFileSystemNameBuffer, 1 ) & @LF )
ConsoleWrite ( "File System Flags: " & _checkFSflags ( DllStructGetData ( $lpFileSystemFlags, 1 ) ) & @LF )
; Hilfsfunktion zum Prüfen der Flags
Func _checkFSflags ( $flagsum )
Local Const $FS_CASE_IS_PRESERVED = 0x2
Local Const $FS_CASE_SENSITIVE = 0x1
Local Const $FS_UNICODE_STORED_ON_DISK = 0x4
Local Const $FS_PERSISTENT_ACLS = 0x8
Local Const $FS_FILE_COMPRESSION = 0x10
Local Const $FS_VOL_IS_COMPRESSED = 0x8000
Local $sFlags = @LF
If BitAnd ( $flagsum, $FS_CASE_IS_PRESERVED ) Then
$sFlags &= @TAB & "FS_CASE_IS_PRESERVED" & @LF
EndIf
If BitAnd ( $flagsum, $FS_CASE_SENSITIVE ) Then
$sFlags &= @TAB & "FS_CASE_SENSITIVE" & @LF
EndIf
If BitAnd ( $flagsum, $FS_UNICODE_STORED_ON_DISK ) Then
$sFlags &= @TAB & "FS_UNICODE_STORED_ON_DISK" & @LF
EndIf
If BitAnd ( $flagsum, $FS_PERSISTENT_ACLS ) Then
$sFlags &= @TAB & "FS_PERSISTENT_ACLS" & @LF
EndIf
If BitAnd ( $flagsum, $FS_FILE_COMPRESSION ) Then
$sFlags &= @TAB & "FS_FILE_COMPRESSION" & @LF
EndIf
If BitAnd ( $flagsum, $FS_VOL_IS_COMPRESSED ) Then
$sFlags &= @TAB & "FS_VOL_IS_COMPRESSED" & @LF
EndIf
Return $sFlags
EndFunc
Diese Funktion enthält als Parameter bereits eine Struktur.
Declare Function GetCursorPos Lib "user32" Alias "GetCursorPos" (lpPoint As POINTAPI) As Long
• lpPoint
Points to a POINT structure that receives the screen coordinates of the cursor.
Das Vorgehen für uns ist wie im letzten Bsp., die geforderte Struktur erstellen und mit einem Pointer darauf verweisen.
So sieht die enthaltene Struktur aus:
Type POINTAPI
x As Long
y As Long
End Type
Das übersetzen wir jetzt nach AutoIt:
DllCall ( "user32", "long", "GetCursorPos", "ptr", DllStructGetPtr ( $tPOINTAPI ) )
; die Werte aus der Struktur auslesen
ConsoleWrite ( "x: " & DllStructGetData ( $tPOINTAPI, 1 ) & @LF )
ConsoleWrite ( "y: " & DllStructGetData ( $tPOINTAPI, 2 ) & @LF )
; alternativ Ausgabe ab v3.3.10.0
ConsoleWrite ( "x: " & $tPOINTAPI.x & @LF )
ConsoleWrite ( "y: " & $tPOINTAPI.y & @LF )
Durch die Punktnotation lassen sich Dll-Strukturen auch zu netten Syntaxdarstellungen verwenden.
Ich habe hier eine Funktion erstellt, ähnlich der Funktion _PathSplit.
ConsoleWrite('kpl. Pfad ' & $path.FullPath & @CRLF)
ConsoleWrite('Laufwerk ' & $path.Drive & @CRLF)
ConsoleWrite('Ordner ' & $path.Dir & @CRLF)
ConsoleWrite('Dateiname ' & $path.File & @CRLF)
ConsoleWrite('Name Erweiterung ' & $path.Ext & @CRLF)
ConsoleWrite('Datei mit Erweiterung ' & $path.FileExt & @CRLF)
; oder direkt nur ein Parameter:
ConsoleWrite('Dateiname ' & _Path(@ScriptFullPath).File & @CRLF)
;===================================================================================================
; Function Name....: _Path
; Description......: Splittet eine Pfadangabe in einzelne Bestandteile
; Parameter(s).....: $sPath Pfadangabe, Lw-basiert oder UNC, absolut oder relativ - alles möglich
; .................: Pfad kann Laufwerk od. Laufwerk mit Ordner od. Lw/Ordner/Datei.suffix sein
; .................: Pfad wird nicht auf Existenz geprüft
; Return Value(s)..: Struktur mit den Feldern:
; .................: .FullPath Der kpl. Pfad in Normalform
; .................: .Drive Das Laufwerk (ohne Backslash), bei UNC-Pfad der Hostname
; .................: .Dir Das Verzeichnis (ohne endenden Backslash)
; .................: .File Der Dateiname
; .................: .Ext Der Name der Erweiterung
; .................: .FileExt Dateiname.Erweiterung
; Author(s)........: BugFix ( autoit@bug-fix.info )
;===================================================================================================
Func _Path($sPath)
Local $sDrive, $sDirFile, $sDir, $sFile, $sExt, $sFileExt, $sTmp
$sPath = DllCall('kernel32.dll', 'dword', 'GetFullPathNameW', 'wstr', $sPath, 'dword', 4096, 'wstr', '', 'ptr', 0)[3]
Select
Case StringLeft($sPath, 2) = '\\'
$sDrive = StringLeft($sPath, StringInStr($sPath, '\', 0, 3))
Case StringRegExp($sPath, '^[a-zA-Z]:')
$sDrive = StringLeft($sPath, 3)
EndSelect
$sDirFile = StringTrimLeft($sPath, StringLen($sDrive))
$sDir = StringLeft($sDirFile, StringInStr($sDirFile, '\', 0, -1))
$sTmp = StringTrimLeft($sDirFile, StringLen($sDir))
$sFileExt = StringInStr($sTmp, '.') ? $sTmp : ''
If $sFileExt = '' Then $sDir = $sDirFile
$sFile = ($sFileExt <> '') ? StringLeft($sFileExt, StringInStr($sFileExt, '.', 0, -1) -1) : ''
$sExt = ($sFileExt <> '') ? StringTrimLeft($sFileExt, StringLen($sFile) +1) : ''
Local $tPath, $tagPath = 'struct;' & _
'char FullPath[' & StringLen($sPath) & '];' & _
'char Drive[' & StringLen($sDrive) & '];' & _
'char Dir[' & ((StringLen($sDir) > 0) ? StringLen($sDir) : 1) & '];' & _
'char File[' & ((StringLen($sFile) > 0) ? StringLen($sFile) : 1) & '];' & _
'char Ext[' & ((StringLen($sExt) > 0) ? StringLen($sExt) : 1) & '];' & _
'char FileExt[' & ((StringLen($sExt) > 0) ? (StringLen($sFile)+StringLen($sExt)+1) : 1) & '];' & _
'endstruct'
$tPath = DllStructCreate($tagPath)
DllStructSetData($tPath, 1, StringRegExpReplace($sPath, '\\$', ''))
DllStructSetData($tPath, 2, StringRegExpReplace($sDrive, '\\$', ''))
DllStructSetData($tPath, 3, StringRegExpReplace($sDir, '\\$', ''))
DllStructSetData($tPath, 4, $sFile)
DllStructSetData($tPath, 5, $sExt)
DllStructSetData($tPath, 6, $sFileExt)
Return $tPath
EndFunc
Euer BugFix Kontakt: Mail BugFix
Für die Codedarstellung wurde der Font Source Code Pro verwendet. Der Font steht unter der "Open Font License" (Lizenzdatei).
Der Text wurde in Quattrocento Roman verfaßt, einem ebenfalls frei verwendbaren Font.