Ich weiß nicht genau, was Du vorhast, aber SendMessageCallback (mit A oder W) hört sich danach an.
Befindet sich in: winim\inc\winuser.nim
Ich weiß nicht genau, was Du vorhast, aber SendMessageCallback (mit A oder W) hört sich danach an.
Befindet sich in: winim\inc\winuser.nim
dein Skript gibt aber nur den ersten Monitor zurück auf dem das Fenster gefunden wurde oder nicht?
Ja!
Es gibt die Nummer des Displays zurück, auf dem sich die obere/linke Ecke des Fenster befindet.
Natürlich ist es möglich, dass das Fenster sich über mehrere Displays erstreckt, aber war das die Frage? ![]()
Habt Ihr ein besseres Script
Hier:
#include <WinAPIGdi.au3>
#include <WinAPISysInternals.au3>
Run("notepad.exe")
WinWait("[CLASS:Notepad]", "", 10)
$hWnd = WinGetHandle("[CLASS:Notepad]")
ConsoleWrite(_GetDisplayNumber($hWnd) & @CR)
Func _GetDisplayNumber(ByRef $hWnd)
Local $tPoint = DllStructCreate($tagPoint), $tRect = _WinAPI_GetWindowRect($hWnd)
$tPoint.x = $tRect.left
$tPoint.y = $tRect.top
Local $aDiplays = _WinAPI_EnumDisplayMonitors()
For $i = 1 To $aDiplays[0][0]
If _WinAPI_PtInRect($aDiplays[$i][1], $tPoint) Then Return $i
Next
Return 0
EndFunc
Alles anzeigen
Edit: Noch etwas abgeändert.
Nur klappt das leider nicht bei Dateinamen mit Dateiendung, wenn man nur den Dateinamen haben will.
Na dann halt so:
Global $sPath = "c:\doc\test\abc.de"
Global $sFile = _PathGetFilename($sPath)
ConsoleWrite('File: "' & $sFile & '"' & @CR)
Global $sPath = "c:\doc\test\abc.de"
Global $sFile = _PathGetFilename($sPath, True)
ConsoleWrite('File: "' & $sFile & '"' & @CR)
Global $sPath = "c:\doc\test\"
Global $sFile = _PathGetFilename($sPath)
ConsoleWrite('File: "' & $sFile & '"' & @CR)
Func _PathGetFilename(ByRef $sPath, $bWithExt = False)
Local $sRet, $sReplace = $bWithExt ? '$1$2' : '$1'
$sRet = StringRegExpReplace($sPath, '.+\\(.+?)(\..+)', $sReplace)
If $sRet = $sPath Then $sRet = ''
Return $sRet
EndFunc
Alles anzeigen
Gibt es auch eine _Winapi-Funktion die mir den kompletten Ordner ohne Dateiname zurückgibt?
Ja!
_WinAPI_PathRemoveFileSpec
Nim beherrscht ja auch die Objekt-Orientierte-Programmierung (OOP) und eigentlich gefällt mir diese Variante sogar noch besser.
Hier also mal als OOP-Version:
Edit: Noch ein paar Korrekturen vorgenommen.
- Wenn beim öffnen einer Datei, noch eine andere Datei geöffnet war, wird diese erstmal geschlossen.
- Die Laufzeit wird jetzt nur einmalig beim öffnen ausgelesen und objektintern gespeichert. "length" ist nur noch eine Getter-Methode.
import winim
import os
import strutils
import strformat
import random
import math
randomize()
type sound = ref object of RootObj
sAlias: string
iLength: int
method close(this: sound): bool {.discardable, base.} =
if this.sAlias == "": return false
result = mciSendStringW(fmt("close {this.sAlias}"), "", 0, 0) == 0
this.sAlias = ""
this.iLength = 0
method open(this: sound, sFilename: string): bool {.discardable, base.} =
if this.sAlias != "": this.close()
for i in 0..9:
this.sAlias &= char(rand(65..90))
if mciSendStringW(fmt("open \"{sFilename}\" alias {this.sAlias}"), "", 0, 0) != 0: return false
mciSendStringW(fmt("set {this.sAlias} time format milliseconds"), "", 0, 0)
var buf: array[255, WCHAR]
var lpszReturn: LPWSTR = buf.addr
result = mciSendStringW(fmt("status {this.sAlias} length"), lpszReturn, 255, 0) == 0
this.iLength = parseInt($lpszReturn)
method seek(this: sound, iPos: int = 0): bool {.discardable, base.} =
if this.sAlias == "": return false
return mciSendStringW(fmt("seek {this.sAlias} to ") & (if iPos > 0: $iPos else: "start"), "", 0, 0) == 0
method length(this: sound): int {.base.} = return this.iLength
method pos(this: sound): int {.base.} =
if this.sAlias == "": return -1
var buf: array[255, WCHAR]
var lpszReturn: LPWSTR = buf.addr
mciSendStringW(fmt("status {this.sAlias} position"), lpszReturn, 255, 0)
result = parseInt($lpszReturn)
method play(this: sound, bWait: bool = false): bool {.discardable, base.} =
if this.sAlias == "": return false
if this.pos() >= this.iLength: this.seek()
return mciSendStringW(fmt("play {this.sAlias}") & (if bWait: " wait" else: ""), "", 0, 0) == 0
method pause(this: sound): bool {.discardable, base.} =
if this.sAlias == "": return false
return mciSendStringW(fmt("pause {this.sAlias}"), "", 0, 0) == 0
method resume(this: sound): bool {.discardable, base.} =
if this.sAlias == "": return false
return mciSendStringW(fmt("resume {this.sAlias}"), "", 0, 0) == 0
method stop(this: sound): bool {.discardable, base.} =
if this.sAlias == "": return false
return mciSendStringW(fmt("stop {this.sAlias}"), "", 0, 0) == 0
method status(this: sound): string {.base.} =
if this.sAlias == "": return "no alias"
var buf: array[255, WCHAR]
var lpszReturn: LPWSTR = buf.addr
mciSendStringW(fmt("status {this.sAlias} mode"), lpszReturn, 255, 0)
return $lpszReturn
method setVolume(this: sound, iVolume: int): bool {.discardable, base.} =
if this.sAlias == "" or iVolume < 0 or iVolume > 1000: return false
return mciSendStringW(fmt("setaudio {this.sAlias} volume to {iVolume}"), "", 0, 0) == 0
proc ticksToTime(iTicks: int): string =
if iTicks < 0: return "error"
var m, h, s: int
s = int(iTicks / 1000)
h = int(s / 3600)
s = floorMod(s, 3600)
m = int(s / 60)
s = floorMod(s, 60)
if h > 0:
result = fmt("{h:0>2}:{m:0>2}:{s:0>2}")
else:
result = fmt("{m:0>2}:{s:0>2}")
# Beispielcode
# ==============
# Die Methode "open" muss mit dem Dateinamen aufgerufen werden
# Alle anderen Methoden benutzen das objektinterne sAlias.
# Einschraenkungen:
# MP3s mit VBR-Kodierung funktionieren nicht!
# Bei WAV-Dateien funktioniert das aendern der Lautstaerke nicht!
let mp3 = sound() # Sound-Objekt erstellen
if not mp3.open(r"Asia - Heat Of The Moment.mp3"): # versuchen die MP3-Datei zu laden
echo "Error! Can't open this file."
quit()
mp3.setVolume(1000) # Lautstaerke festlegen (0 = aus bis 1000 = max.)
let iLength = mp3.length # Laufzeit des Sounds holen
echo "Soundlength " & ticksToTime(iLength) # in (hh:)mm:ss umwandeln
mp3.play # Sound abspielen
var iPosition: int
while iPosition < iLength:
sleep(1000)
iPosition = mp3.pos # momentane Position auslesen
echo "Position " & ticksToTime(iPosition) # in (hh:)mm:ss umwandeln
echo mp3.close # Datei schliessen
Alles anzeigen
Im ZIP-Archiv (Anhang) befindet sich der obige Code zum herunterladen.
Analog zur AutoIt-UDF habe ich mal die wichtigsten Sachen in Prozeduren erstellt. Ich denke, so ist das übersichtlicher.
Mir sind zwei Einschränkungen aufgefallen:
- MP3s mit VBR-Kodierung funktionieren nicht!
- Bei WAV-Dateien funktioniert das aendern der Lautstaerke nicht!
import winim
import os
import strutils
import strformat
import random
import math
randomize()
proc soundOpen(sfile: string): string =
var sAlias: string
for i in 0..9:
sAlias &= char(rand(65..90))
let err = mciSendStringW(fmt("open \"{sfile}\" alias {sAlias}"), "", 0, 0)
if err != 0: return ""
mciSendStringW(fmt("set {sAlias} time format milliseconds"), "", 0, 0)
return sAlias
proc soundClose(sAlias: string): bool {.discardable.} =
if sAlias == "": return false
return mciSendStringW(fmt("close {sAlias}"), "", 0, 0) == 0
proc soundSeek(sAlias: string, iPos: int = 0): bool {.discardable.} =
if sAlias == "": return false
return mciSendStringW(fmt("seek {sAlias} to ") & (if iPos > 0: $iPos else: "start"), "", 0, 0) == 0
proc soundLength(sAlias: string): int =
if sAlias == "": return -1
var lpszReturn: LPWSTR = newWideCString("", 10)
mciSendStringW(fmt("status {sAlias} length"), lpszReturn, 255, 0)
result = parseInt($lpszReturn)
proc soundPos(sAlias: string): int =
if sAlias == "": return -1
var lpszReturn: LPWSTR = newWideCString("", 10)
mciSendStringW(fmt("status {sAlias} position"), lpszReturn, 255, 0)
result = parseInt($lpszReturn)
proc soundPlay(sAlias: string, bWait: bool = false): bool {.discardable.} =
if sAlias == "": return false
if soundPos(sAlias) >= soundLength(sAlias):
discard soundSeek(sAlias)
return mciSendStringW(fmt("play {sAlias}") & (if bWait: " wait" else: ""), "", 0, 0) == 0
proc soundPause(sAlias: string): bool {.discardable.} =
if sAlias == "": return false
return mciSendStringW(fmt("pause {sAlias}"), "", 0, 0) == 0
proc soundResume(sAlias: string): bool {.discardable.} =
if sAlias == "": return false
return mciSendStringW(fmt("resume {sAlias}"), "", 0, 0) == 0
proc soundStop(sAlias: string): bool {.discardable.} =
if sAlias == "": return false
return mciSendStringW(fmt("stop {sAlias}"), "", 0, 0) == 0
proc soundStatus(sAlias: string): string =
if sAlias == "": return "no alias"
var lpszReturn: LPWSTR = newWideCString("", 10)
mciSendStringW(fmt("status {sAlias} mode"), lpszReturn, 255, 0)
return $lpszReturn
proc soundSetVolume(sAlias: string, iVolume: int): bool {.discardable.} =
if sAlias == "": return false
if iVolume < 0 or iVolume > 1000: return false
return mciSendStringW(fmt("setaudio {sAlias} volume to {iVolume}"), "", 0, 0) == 0
proc soundTicksToTime(iTicks: int): string =
if iTicks < 0: return "error"
var m, h, s: int
s = int(iTicks / 1000)
h = int(s / 3600)
s = floorMod(s, 3600)
m = int(s / 60)
s = floorMod(s, 60)
if h > 0:
result = fmt("{h:0>2}:{m:0>2}:{s:0>2}")
else:
result = fmt("{m:0>2}:{s:0>2}")
# Beispielcode
# ==============
# "soundOpen" muss mit dem Dateinamen aufgerufen werden
# alle anderen Funktionen werden dann mit dem Alias aufgerufen.
# Einschraenkungen:
# MP3s mit VBR-Kodierung funktionieren nicht!
# Bei WAV-Dateien funktioniert das aendern der Lautstaerke nicht!
let sSndfile = r"Asia - Heat Of The Moment.mp3" # Pfad zur mp3-Datei
let sMyAlias = soundOpen(sSndfile) # Datei oeffnen (Rueckgabe = zufaelliger Alias)
echo "Alias: " & sMyAlias
soundSetVolume(sMyAlias, 1000) # Lautstaerke festlegen (0 = aus bis 1000 = max.)
var iLength = soundLength(sMyAlias) # Laufzeit des Sounds holen
echo "Soundlength " & soundTicksToTime(iLength)
soundPlay(sMyAlias) # Sound abspielen
var iPosition: int
while iPosition < iLength:
sleep(1000)
iPosition = soundPos(sMyAlias) # momentane Position auslesen
echo "Position " & soundTicksToTime(iPosition) # in (hh:)mm:ss umwandeln
soundClose(sMyAlias) # Sound schliessen
Alles anzeigen
Im ZIP-Archiv (Anhang) befindet sich der obige Code zum herunterladen.
Ich habe mich jetzt intensiv mit der "winmm.dll" beschäftigt. Die Sound-UDF von AutoIt basiert ja auf dieser dll und damit kann man problemlos MP3s abspielen.
Also muss das ja auch unter Nim funktionieren, habe ich mir gedacht und nachdem ich jetzt den halben Tag damit verbracht habe, kann ich eine Erfolgsmeldung abgeben.
Hier nun der kommentierte Programmcode zum abspielen von MP3s (ganz ohne BASS.dll):
# Um unter Windows eine mp3-Datei abzuspielen, kann man die "winmm.dll" verwenden.
# Mittels "Multimedia Command Strings" kann man ein MCI-Device ansteuern.
# Diese Strings werden mit mciSendStringW gesendet. Weitere Infos gibts hier:
# https://docs.microsoft.com/en-us/previous-versions/ms709492(v%3Dvs.85)
import winim
import os
import strutils
let sAlias = "nimtest" # beliebiger String als Alias
let sSndfile = r"Asia - Heat Of The Moment.mp3" # Pfad zur mp3-Datei
let iStartTime = 31000 # zum testen vorspulen zu dieser Position (in ms)
let iVolume = 1000 # Lautstaerke (0 = Aus bis 1000 = volle Lautstaerke)
var
iRet, iLength, iPosition: int
lpszReturn: LPWSTR = newWideCString("", 10) # Stringbuffer fuer die Rueckgabe reservieren
iRet = mciSendStringW("""open "$1" alias $2""" % [sSndfile, sAlias], "", 0, 0) # mp3-Datei oeffnen
if iRet != 0: quit() # falls "open" fehlschlaegt, das Programm beenden (Rueckgabe = 0 = erfolgreich)
echo "open: " & $(iRet == 0)
iRet = mciSendStringW("set " & sAlias & " time format milliseconds", "", 0, 0) # Zeitformat festlegen (ms)
echo "set: " & $(iRet == 0)
# Lautstaerke fuer den Sound setzen (0 = Aus bis 1000 = volle Lautstaerke)
iRet = mciSendStringW("setaudio " & sAlias & " volume to " & $iVolume, "", 0, 0)
echo "volume: " & $(iRet == 0)
mciSendStringW("status " & sAlias & " length", lpszReturn, 255, 0) # die Laufzeit auslesen
iLength = parseInt($lpszReturn) # String nach int konvertieren
echo "length: " & $iLength
iRet = mciSendStringW("seek " & sAlias & " to " & $iStartTime, "", 0, 0) # so kann man vorspulen
echo "seek: " & $(iRet == 0)
iRet = mciSendStringW("play " & sAlias, "", 0, 0) # Sound abspielen
echo "play: " & $(iRet == 0)
iRet = mciSendStringW("pause " & sAlias, "", 0, 0) # Sound pausieren
echo "pause: " & $(iRet == 0)
# Modus auslesen (Werte: "not ready", "paused", "playing", "stopped")
iRet = mciSendStringW("status " & sAlias & " mode", lpszReturn, 255, 0)
echo "mode: " & $lpszReturn
sleep(1000)
iRet = mciSendStringW("resume " & sAlias, "", 0, 0) # Sound fortsetzen
echo "resume: " & $(iRet == 0)
# Modus auslesen (Werte: "not ready", "paused", "playing", "stopped")
iRet = mciSendStringW("status " & sAlias & " mode", lpszReturn, 255, 0)
echo "mode: " & $lpszReturn
while iPosition < iLength: # solange das Ende noch nicht erreicht ist
mciSendStringW("status " & sAlias & " position", lpszReturn, 255, 0) # momentane Position auslesen
iPosition = parseInt($lpszReturn) # String nach int konvertieren
echo "position: " & $iPosition
sleep(1000)
iRet = mciSendStringW("stop " & sAlias, "", 0, 0) # Sound stoppen
echo "stop: " & $(iRet == 0)
iRet = mciSendStringW("close " & sAlias, "", 0, 0) # mp3-Datei schliessen
echo "close: " & $(iRet == 0)
Alles anzeigen
Bei dynamisch erstellten Buttons kommst Du um Arrays nicht herum.
Hier mal ein Beispiel:
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <MsgBoxConstants.au3>
Opt("GUIOnEventMode", 1)
Global $aidButton[6]
Global $hGUI = GUICreate("Example", 300, 200)
For $i = 0 To UBound($aidButton) - 1
$aidButton[$i] = GUICtrlCreateButton("Config_" & $i + 1, 20, 10 + $i * 30, 85, 25)
GUICtrlSetOnEvent(-1, "_test")
Next
GUISetState(@SW_SHOW, $hGUI)
While Sleep(50)
WEnd
Func _test()
Local $iIndex = @GUI_CtrlId - $aidButton[0]
ConsoleWrite('Config: ' & $iIndex + 1 & @CR)
Sleep(1000)
GUIDelete($hGUI)
Exit
EndFunc
Alles anzeigen
Wenn man ein Programm mit Gui erstellt und man einen "eigenen" Font benutzen will, so müsste man ja den Font nicht nur mitliefern, sonder auch noch installieren.
Irgendwann stapeln sich bei den Anwendern dann die installierten Fonts. Das ist aber gar nicht notwendig, denn man kann unter Windows einen Font auch temporär ins System einbinden.
Er wird dann nur von dem einen Programm benutzt und nach Programmende automatisch wieder vom System entfernt.
Hier mal ein Beispiel dafür:
Der Font "TeXGyreCursor" befindet sich im ZIP-Archiv (Anhang).
# Verwendung von AddFontResourceExA, um Font(s) vom eigenen Programm
# nutzen zu koennen
import wNim
import times
import winim # <- fuer "AddFontResourceExA"
# Font "TeXGyreCursor" nur fuer diesen Prozess verfuegbar machen
# (wird beim beenden des Prozesses automatisch wieder entfernt)
AddFontResourceExA(r"texgyrecursor-bold.otf", FR_PRIVATE or FR_NOT_ENUM, NULL)
let app = App()
let frame = Frame(title="Timer Test", size=(380, 200))
let panel = Panel(frame)
panel.setBackgroundColor(0x001A1A1A)
let timeLbl = StaticText(panel, label="Test giylpa öäüß", pos=(20, 10), size=(300, 40))
timeLbl.font = Font(22, faceName="TeXGyreCursor", weight=wFontWeightNormal)
timeLbl.setForegroundColor(0x00CCCCCC) # BGR-Format
let timeCtrl = StaticText(panel, label="00:00:00", pos=(20, 50), size=(320, 70), style=wAlignCenter)
timeCtrl.font = Font(48, faceName="TeXGyreCursor", weight=wFontWeightBold)
timeCtrl.setForegroundColor(0x0000AA00) # BGR-Format
frame.startTimer(1.0) # starte den Timer (Zeit in Sekunden als Float)
frame.wEvent_Timer do (event: wEvent): # hier wird der Timer-Event ausgewertet
let dt = now() # Datum/Uhrzeit holen
timeCtrl.setLabel(dt.format("HH:mm:ss")) # und formatiert in das Text-Ctrl schreiben
frame.center()
frame.show()
app.mainLoop()
Alles anzeigen
Achso, "FindWindowA" gibt es auch schon in der "winuser"!
Dann geht auch:
Wie muss ich hier vorgehen?
Offenbar muss man erstmal die Länge des Titels auslesen und dann einen Buffer in der Größe erstellen:
import strutils
include winim/[inc\winuser]
# FindWindow by CLASSNAME and TITLE
proc FindWindow*(lpClass: cstring, lpName: cstring): cint {.cdecl, varargs, importc: "FindWindowA", dynlib: "User32.dll".}
# FindWindow by CLASSNAME
proc FindWindow*(lpClass: cstring, lpName: cint = 0): cint {.cdecl, varargs, importc: "FindWindowA", dynlib: "User32.dll".}
# FindWindow On Top (ACTIVE Window)
proc FindWindow*(lpClass: cint = 0, lpName: cint = 0): cint {.cdecl, varargs, importc: "FindWindowA", dynlib: "User32.dll".}
let hWnd = FindWindow("SciTEWindow")
echo toHex(hWnd)
let nMaxCount = GetWindowTextLengthA(hWnd) + 1
echo nMaxCount
var lpString: LPSTR = spaces(nMaxCount)
let iLen = GetWindowTextA(hWnd, lpString, nMaxCount)
echo lpString
Alles anzeigen
Ich übergebe Dateipfade, lese mit Nim die Dateien ein, parse Includes, Variablen, Konstanten, Funktionen und will all diese Daten zurückgeben. Menge ist vorher unbekannt.
Ah ok! Das ist ein Problem!
Ich würde trotzdem von AutoIt aus den Speicher reservieren (DllStructCreate).
Einfach eine geschätzte Maximalgröße eintragen, den Pointer darauf an Nim übergeben, dort die Änderungen vornehmen und dann (je nach Datenstruktur) ein Int für die Anzahl an AutoIt zurückgeben.
Das bisherige diente dazu um 1..n Dateipfade übergeben zu können. Jetzt verarbeite ich die entsprechenden Dateien mit Nim und will das Ergebnis sofort zurückliefern.
Was willst Du denn verarbeiten?
Für die Strings (Dateipfade) hast Du doch schon die Pointer übergeben. Die Strings kannst Du somit in Nim ändern und dann mit AutoIt (DllStructGetData) auslesen.
Da musst Du nichts extra zurückgeben.
Wenn Du statt des Sternchen ein Plus verwendest, geht es auch mit einem Leerstring.
Wenn Du Strings übergeben willst, pack sie am besten in eine Struktur (mit Nullbyte am Ende) und übergib nur die Pointer auf die Strings:
#AutoIt3Wrapper_UseX64=y
Local $aData[3] = ["Daten #1","Daten Nummer 2","Daten Item #3"]
Local $tPointerArr = DllStructCreate('ptr[' & UBound($aData) & ']') ; Struktur fuer das Pointer-Array
Local $pPointerArr = DllStructGetPtr($tPointerArr) ; Pointer auf das Pointer-Array
Local $atData[UBound($aData)], $apData[UBound($aData)], $iLen = 0
For $i = 0 To UBound($aData) - 1
$iLen += StringLen($aData[$i])
$atData[$i] = DllStructCreate('char[' & StringLen($aData[$i]) + 1 & ']') ; Struktur erzeugen
DllStructSetData($atData[$i], 1, $aData[$i] & Chr(0)) ; Stringdaten einfuegen mit Nullbyte am Ende (cstring)
DllStructSetData($tPointerArr, 1, DllStructGetPtr($atData[$i]), $i + 1) ; Pointer auf den String in das Pointer-Array einfuegen
Next
ConsoleWrite('$iLen = ' & $iLen & @CRLF)
Local $aRet = DllCall('test.dll', 'int', 'sendData', 'ptr', $pPointerArr, 'int', UBound($aData))
If Not @error Then
ConsoleWrite('$aRet[0] = ' & $aRet[0] & @CRLF)
EndIf
Alles anzeigen
Und in Nim:
proc sendData(pData: ptr UncheckedArray[cstring], iCount: int): int {.stdcall,exportc,dynlib.} =
var sData: cstring
for i in 0..iCount - 1:
sData = pData[i]
result += sData.len
Damit man den Erfolg sieht, lasse ich in Nim die Stringlängen addieren und an AutoIt zurückgeben.
Um das Ganze noch flexibler zu machen, kann man auch den Pointer und die Anzahl der Bytes übergeben:
#AutoIt3Wrapper_UseX64=y
Global $tData = DllStructCreate('byte[32]')
Global $pData = DllStructGetPtr($tData), $iChecksum
For $i = 0 To 31
DllStructSetData($tData, 1, $i, $i + 1)
$iChecksum += $i
Next
ConsoleWrite('Checksum1: ' & $iChecksum & @CR)
Global $aRet = DllCall('test.dll', 'int', 'sendData', 'ptr', $pData, 'int', 32)
ConsoleWrite('Dll-Return: ' & $aRet[0] & @CR)
; Der Wert vom letzten Byte wurde in der Dll abschliessend auf "0" gesetzt.
; Testen, ob das korrekt uebernommen wurde (Ergebnis = Checksum1 - 31).
$iChecksum = 0
For $i = 0 To 31
$iChecksum += DllStructGetData($tData, 1, $i + 1)
Next
ConsoleWrite('Checksum2: ' & $iChecksum & @CR)
Alles anzeigen
In Nim dann ein Pointer auf ein "UncheckedArray" verwenden:
Ich habe mal ein einfacheres Beispiel erstellt:
In AutoIt erstellen wir ein Array mit 8 Bytewerten:
#AutoIt3Wrapper_UseX64=y
Global $tData = DllStructCreate('byte[8]')
Global $pData = DllStructGetPtr($tData)
For $i = 0 To 7
DllStructSetData($tData, '', $i, $i + 1)
Next
Global $aRet = DllCall('test.dll', 'int', 'sendData', 'ptr', $pData)
ConsoleWrite($aRet[0] & @CR)
Der Pointer wird an die Dll in Nim gesendet.
In Nim bekommen wir den Pointer und erstellen damit ebenfalls ein Array mit 8 Werten:
proc sendData(pData: ptr array[8, byte]): int {.stdcall,exportc,dynlib.} =
var received: ptr array[8, byte]
received = pData
for i in 0..7:
result += int(received[i])
Zum testen addiere ich die übergebenen Werte und sende sie an AutoIt zurück, damit man das korrekte Ergebnis sehen kann.
Woher stammen diese Pfade, selbst erstellt?
Äh! Nein, nicht selbst erstellt.
Aber wo Du es schreibst, in "scoop" habe ich auch noch ein "nim".