1. Dashboard
  2. Mitglieder
    1. Letzte Aktivitäten
    2. Benutzer online
    3. Team
    4. Mitgliedersuche
  3. Forenregeln
  4. Forum
    1. Unerledigte Themen
  • Anmelden
  • Registrieren
  • Suche
Alles
  • Alles
  • Artikel
  • Seiten
  • Forum
  • Erweiterte Suche
  1. AutoIt.de - Das deutschsprachige Forum.
  2. Mitglieder
  3. Oscar

Beiträge von Oscar

  • Eigene Auswertung zu einer WindowMessage in die MainLoop einfügen

    • Oscar
    • 12. Juni 2020 um 15:44

    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

  • Auf welchem Monitor befindet sich das Fenster?

    • Oscar
    • 12. Juni 2020 um 12:48
    Zitat von alpines

    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? :/

  • Auf welchem Monitor befindet sich das Fenster?

    • Oscar
    • 12. Juni 2020 um 12:28
    Zitat von Banana_2_Day

    Habt Ihr ein besseres Script

    Hier:

    AutoIt
    #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.

  • _Winapi-Funktionen

    • Oscar
    • 12. Juni 2020 um 12:06
    Zitat von fee

    Nur klappt das leider nicht bei Dateinamen mit Dateiendung, wenn man nur den Dateinamen haben will.

    Na dann halt so:

    AutoIt
    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
  • _Winapi-Funktionen

    • Oscar
    • 12. Juni 2020 um 08:18

    Naja, StringRegex reicht doch:

    AutoIt
    Global $sPath = "c:\doc\test\a"
    Global $sFile = StringRegExpReplace($sPath, '.+\\(.*?)', '$1')
    ConsoleWrite('File: "' & $sFile & '"' & @CR)
  • _Winapi-Funktionen

    • Oscar
    • 10. Juni 2020 um 18:39
    Zitat von Tweaky

    Gibt es auch eine _Winapi-Funktion die mir den kompletten Ordner ohne Dateiname zurückgibt?

    Ja!

    _WinAPI_PathRemoveFileSpec

  • ​Sammlung: Nim Snippets / Procedures

    • Oscar
    • 10. Juni 2020 um 11:49

    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.

    Code
    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.

    Dateien

    ooSound.zip 1,39 kB – 732 Downloads
  • ​Sammlung: Nim Snippets / Procedures

    • Oscar
    • 10. Juni 2020 um 08:53

    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!

    Code
    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.

    Dateien

    sound.zip 1,28 kB – 753 Downloads
  • ​Sammlung: Nim Snippets / Procedures

    • Oscar
    • 9. Juni 2020 um 17:32

    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):

    Code
    # 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
  • Herausfinden, welcher Button die Funktion mit GUICtrlSetOnEvent aufgerufen hat

    • Oscar
    • 8. Juni 2020 um 14:00

    Bei dynamisch erstellten Buttons kommst Du um Arrays nicht herum.

    Hier mal ein Beispiel:

    AutoIt
    #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
  • ​Sammlung: Nim Snippets / Procedures

    • Oscar
    • 7. Juni 2020 um 16:43

    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).

    Code
    # 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

    Dateien

    texgyrecursor-bold.zip 73,29 kB – 761 Downloads
  • Windows Titel auslesen

    • Oscar
    • 1. Juni 2020 um 17:11

    Achso, "FindWindowA" gibt es auch schon in der "winuser"!

    Dann geht auch:

    Code
    import strutils 
    include winim/[inc\winuser]
    
    let hWnd = FindWindowA("SciTEWindow", nil)
    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
  • Windows Titel auslesen

    • Oscar
    • 1. Juni 2020 um 15:04
    Zitat von BugFix

    Wie muss ich hier vorgehen?

    Offenbar muss man erstmal die Länge des Titels auslesen und dann einen Buffer in der Größe erstellen:

    Code
    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
  • Daten aus Pointer in Nim Datentyp einlesen

    • Oscar
    • 1. Juni 2020 um 07:42
    Zitat von BugFix

    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.

  • Daten aus Pointer in Nim Datentyp einlesen

    • Oscar
    • 31. Mai 2020 um 18:57
    Zitat von BugFix

    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.

  • IsNumber() und Zahlen in Textvariablen

    • Oscar
    • 31. Mai 2020 um 16:35

    Wenn Du statt des Sternchen ein Plus verwendest, geht es auch mit einem Leerstring.

  • Daten aus Pointer in Nim Datentyp einlesen

    • Oscar
    • 31. Mai 2020 um 16:11

    Wenn Du Strings übergeben willst, pack sie am besten in eine Struktur (mit Nullbyte am Ende) und übergib nur die Pointer auf die Strings:

    AutoIt
    #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:

    Code
    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.

  • Daten aus Pointer in Nim Datentyp einlesen

    • Oscar
    • 31. Mai 2020 um 12:39

    Um das Ganze noch flexibler zu machen, kann man auch den Pointer und die Anzahl der Bytes übergeben:

    AutoIt
    #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:

    Code
    proc sendData(pData: ptr UncheckedArray[byte], iCount: int): int {.stdcall,exportc,dynlib.} =
        for i in 0..iCount - 1:
          result += int(pData[i])
        pData[iCount - 1] = 0 # den letzten Wert auf 0 setzen (als Test)
  • Daten aus Pointer in Nim Datentyp einlesen

    • Oscar
    • 31. Mai 2020 um 11:31

    Ich habe mal ein einfacheres Beispiel erstellt:

    In AutoIt erstellen wir ein Array mit 8 Bytewerten:

    AutoIt
    #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:

    Code
    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.

  • [offen] Kompilieren für x86 ?

    • Oscar
    • 30. Mai 2020 um 15:19
    Zitat von BugFix

    Woher stammen diese Pfade, selbst erstellt?

    Äh! Nein, nicht selbst erstellt.

    Aber wo Du es schreibst, in "scoop" habe ich auch noch ein "nim".

Spenden

Jeder Euro hilft uns, Euch zu helfen.

Download

AutoIt Tutorial
AutoIt Buch
Onlinehilfe
AutoIt Entwickler
  1. Datenschutzerklärung
  2. Impressum
  3. Shoutbox-Archiv
Community-Software: WoltLab Suite™