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

  • ​Sammlung: Nim Snippets / Procedures

    • Oscar
    • 23. Juli 2020 um 17:35
    Zitat von BugFix

    Immer wieder im Einsatz: INI-Dateien.

    Ich habe mal noch ergänzt um den Default-Wert beim Lesen eines Key.

    Ich habe das gerade gebraucht für mein großes Projekt mit Nim (ein MP3-Player). Insofern schonmal: Vielen Dank für das Beispiel! :):thumbup:

    Allerdings kann man das mit dem Defaultwert auch einfacher hinkriegen:

    Code
    import parsecfg, os, strutils, tables
    
    proc getSectionValueOrDefault*(dict: Config, section, key: string, default: string = ""): string =
      result = default
      if dict.hasKey(section):
        if dict[section].hasKey(key): result = dict[section][key]
    
    # Einen Anwendungsordner im ConfigDir erstellen
    # Bei Windows: getConfigDir() = "c:\Users\<user>\AppData\Roaming\"
    let appDir = getConfigDir() & "test\\"
    if not existsDir(appDir): createDir(appDir) # wenn er nicht existiert, anlegen
    let iniFile = appDir & "test.ini" # die Inidatei mit Pfad
    
    var 
      dict: Config
      test: int
    try: # versuchen, die Inidatei zu laden
      dict = loadConfig(iniFile)
    except IOError: # wenn nicht vorhanden
      echo "Inidatei nicht vorhanden! Erstelle neue Konfiguration."
      dict = newConfig()
    
    test = parseInt(getSectionValueOrDefault(dict, "config", "test", "10")) # Defaultwert = 10
    echo test
    test = 25 # vor dem speichern den Wert aendern
    dict.setSectionKey("config", "test", $test)
    dict.writeConfig(iniFile)
    Alles anzeigen

    Edit:

    Man kann die Prozedur auch überladen und kann sie dann mit unterschiedlichen Datentypen als Defaultwert aufrufen:

    Code
    import parsecfg, strutils, tables
    
    proc getSectionValueOrDefault*(dict: Config, section, key: string, default: string): string =
      result = default
      if dict.hasKey(section):
        if dict[section].hasKey(key): result = dict[section][key]
    
    proc getSectionValueOrDefault*(dict: Config, section, key: string): string =
      result = getSectionValueOrDefault(dict, section, key, "")
    
    proc getSectionValueOrDefault*(dict: Config, section, key: string, default: int): int =
      result = parseInt(getSectionValueOrDefault(dict, section, key, $default))
    
    proc getSectionValueOrDefault*(dict: Config, section, key: string, default: float): float =
      result = parseFloat(getSectionValueOrDefault(dict, section, key, $default))
    
    proc getSectionValueOrDefault*(dict: Config, section, key: string, default: bool): bool =
      result = getSectionValueOrDefault(dict, section, key, $default) == "true"
    
    var 
      dict = newConfig()
      test0: string
      test1: string
      test2: int
      test3: float
      test4: bool
    
    test0 = getSectionValueOrDefault(dict, "config", "test0")        # ohne Defaultwert ist die Rueckgabe ein Leerstring
    test1 = getSectionValueOrDefault(dict, "config", "test1", "35")  # Defaultwert = 35 als String
    test2 = getSectionValueOrDefault(dict, "config", "test2", 10)    # Defaultwert = 10 als Int
    test3 = getSectionValueOrDefault(dict, "config", "test3", 3.14)  # Defaultwert = 3.14 als Float
    test4 = getSectionValueOrDefault(dict, "config", "test4", false) # Defaultwert = false als Bool
    
    echo "'", test0, "'", " -> ", test0.typeof()
    echo test1, " -> ", test1.typeof()
    echo test2, " -> ", test2.typeof()
    echo test3, " -> ", test3.typeof()
    echo test4, " -> ", test4.typeof()
    Alles anzeigen
  • ooMPEG

    • Oscar
    • 13. Juli 2020 um 19:01

    Ich habe das Modul quasi nochmal neu geschrieben (objektorientiert).

    Dadurch, dass ich jetzt auch den MPEG-Header analysiere, gibt es noch mehr Informationen über die MPEG-Datei (Bitrate, Kodiermethode, Samlingfrequenz, Laufzeit, etc.).

    Alles weitere in Post#1.

  • Problem: Button mit Icon - Icon ist verschoben

    • Oscar
    • 10. Juli 2020 um 07:15

    Das mit dem Button hat wohl etwas mit dem Rand zu tun. Jedenfalls wird es zentriert, wenn man die Size vom Button auf 38,38 setzt, aber dann hat man einen Rand um das Icon.

    Mit StaticBitmap kann man aber auch einen (randlosen) Button erzeugen:

    Code
    import os
    import wNim
    
    proc CurrentDir(): string =
      result = getAppFilename().splitPath().head
    
    
    let 
      icon = Icon(CurrentDir().joinPath("exit.ico"), size=(32,32))
      bmp = Bitmap(icon)
      app = App()
      frame = Frame(title="Test Icon-Button", size=(300,200))
      panel = frame.Panel()
      btExit = panel.StaticBitmap(pos=(20,20), size=(32,32), bitmap=bmp)
    
    btExit.wEvent_CommandLeftClick do (): frame.delete()
    
    frame.wIdExit do (): frame.delete()
    
    frame.center()
    frame.show()
    app.mainLoop()
    Alles anzeigen
  • Funktion soll nicht erneut starten, solange sie nicht ganz abgeschlossen wurde

    • Oscar
    • 9. Juli 2020 um 17:15
    Zitat von geradeStudent

    Wie verhindere ist das?

    Indem Du beim spielen, keinen Bot benutzt!?

    Und Forenregeln lesen!

  • ooMPEG

    • Oscar
    • 7. Juli 2020 um 13:00

    Ich habe mich mal rangesetzt und ein Modul programmiert, dass die ID3-Tags aus MPEG-Dateien auslesen kann.

    Es werden die Versionen v1.0, v1.1 und v2.3 und v2.4 (eingeschränkt) unterstützt und dabei werden die wichtigsten ID3-Frames ausgelesen.

    Edit 13.07.2020: Komplett neue Version (deswegen auch die Änderung des Threadtitels).

    - Es werden jetzt nicht nur die ID3-Frames ausgelesen, sondern auch noch der MPEG-Header analysiert (Bitrate, Kodiermethode, Samlingfrequenz, Laufzeit, etc.).

    - Fast komplett neu geschrieben. Der Code ist jetzt sehr Objektorientiert. Das erleichert die Verwendung, weil alle Daten im Objekt enthalten sind.

    - DIe benutzen Konstanten (Arrays) sind jetzt in einer extra Datei untergebracht ("ooMPEGconstants.nim").

    - Ich habe den Code ausführlich kommentiert. Hauptsächlich, damit ich mich selbst, nach einem Jahr oder so, noch daran erinnern kann, was ich da geschrieben habe, aber vielleicht ist das ja auch für euch hilfreich.

    Edit 18.08.2020: So einiges entdeckt man erst, wenn man die Funktionen auf zahlreiche MP3s loslässt.

    - Bug, beim ID3v1.x Format. Dort konnte ein Array-Überlauf passieren, wenn die Genrenummer >126 war. Behoben!

    - Man kann jetzt als ID3-Versionsnummer auch "0" angeben. In dem Fall wird versucht, erst die ID3v2.x Daten zu laden und wenn die nicht vorhanden sind, dann ID3v1.x.

    - Wenn beim ID3v1.x Format zwar die "TAG"-Kennung vorhanden ist, aber dann keine Daten vorhanden sind, kommt es nun zum "Fallback" auf den Dateinamen.

    - Wenn beim ID3v2.x Format die Größe eines Frames 0 Bytes beträgt, wird der Frame jetzt übersprungen (fehlerhafte ID3-Daten).

    - Wenn nach dem ID3v2.x Tag nicht gleich ein MPEG-Header folgt, sondern erst einige Bytes später, wurde die MP3-Datei als "nicht gültig" angesehen. Behoben!

    - Wenn keinerlei ID3-Daten vorhanden sind, erfolgt ein "Fallback" auf die Daten im Dateinamen (mit Separator-Split). Jetzt gibt es noch ein letztes "Fallback" (wenn auch der Separator nicht gefunden wird). Es wird dann der Dateiname (ohne Endung) als Interpret eingetragen.


    Hier mal das Beispielprogramm:

    Code
    import ooMPEG, wNim
    
    echo "Unterstuetzte Frames (", aID3v2Frames.len, "): ", aID3v2Frames
    
    let mpeg = MPEGinfo() # MPEGinfo-Objekt erstellen
    
    # Mit "readInfo" wird die uebergebene MPEG-Datei eingelesen und analysiert.
    # Die Daten befinden sich dann im Objekt und koennen benutzt werden.
    # Parameter: Dateiname, gewuenschte ID3-Version, Trennzeichen
    # Die Trennzeichen dienen dazu, Interpret und Titel auch dann zu ermitteln,
    # wenn *keine* ID3-Daten gespeichert sind.
    # Dabei wird versucht, die Daten anhand des Dateinamens zu ermitteln.
    # Der Dateiname muss dieses Format aufweisen: <Interpret><Trennzeichen><Titel>
    if mpeg.readInfo("Status Quo - Whatever You Want.mp3", 0, " - "):
      echo "MPEG-Version: ", mpeg.Version
      echo "MPEG-Layer:   ", mpeg.Layer
      echo "MPEG-Methode: ", mpeg.CompMethod
      echo "MPEG-Bitrate: ", mpeg.Bitrate, " kBit/s"
      echo "Samplingfreq: ", mpeg.Samplingrate, " kHz"
      echo "Dateigroesse: ", mpeg.Filesize, " Bytes"
      echo "Musikgroesse: ", mpeg.Datasize, " Bytes"
      echo "ID3-Version:  ", mpeg.ID3version
      echo "ID3-Frames:   ", mpeg.getID3frames
      echo "Encoded by:   ", mpeg.getID3value("TENC")
      echo "Interpret:    ", mpeg.getID3value("TPE1")
      echo "Titel:        ", mpeg.getID3value("TIT2")
      echo "Album:        ", mpeg.getID3value("TALB")
      echo "Track:        ", mpeg.getID3value("TRCK")
      echo "Jahr:         ", mpeg.getID3value("TYER")
      echo "Genre:        ", mpeg.getID3value("TCON")
      echo "Laufzeit:     ", mpeg.Duration, " Millisekunden"
      echo "Laufzeit:     ", mpeg.DurationString, " (mm:ss)"
      echo "Bilderanzahl: ", mpeg.ApicCount
    let apic1 = mpeg.getID3data("APIC2") # Binaerdaten des Bildes holen
    
    # Zum testen, ob das APIC-Bild korrekt ausgelesen wird
    let app = App()
    let frame = Frame(title="Test", size=(640, 480))
    let panel = Panel(frame)
    let idPic = StaticBitmap(panel, size=(260, 260), pos=(10, 10), style=wSbCenter)
    idPic.setBackgroundColor(0x004A1A1A)
    let idInterpret = StaticText(panel, label=mpeg.getID3value("TPE1"), size=(360, 60), pos=(280, 30))
    idInterpret.font = Font(14, faceName="Arial", weight=wFontWeightNormal)
    let idTitle = StaticText(panel, label=mpeg.getID3value("TIT2"), size=(360, 60), pos=(280, 60))
    idTitle.font = Font(14, faceName="Arial", weight=wFontWeightNormal)
    if apic1.len > 0:
      let myImage = Image(apic1) # die Binaerdaten in ein Image umwandeln
      var sw, sh: int = 240 # Zielgroesse 240x240 px
      let h = myImage.height # momentane hoehe
      let w = myImage.width # und breite
      if h > w: sw = 240 - (h - 240) # wenn hoehe groesser, dann die breite anpassen
      if h < w: sh = 240 - (w - 240) # wenn breite groesser, dann die hoehe anpassen
      let scaleImage = myImage.scale(sw, sh) # Image skalieren (legt eine Kopie an)
      idPic.bitmap = Bitmap(scaleImage) # und dem Bitmap-Control zuweisen
    
    frame.center()
    frame.show()
    app.mainLoop()
    Alles anzeigen

    Alles nochmal im ZIP-Archiv (Anhang) zum herunterladen.

    Dateien

    ooMPEG_v12.zip 9,84 kB – 424 Downloads
  • ​Sammlung: Nim Snippets / Procedures

    • Oscar
    • 5. Juli 2020 um 12:41

    Projekt: SerialComm

    Für die Kommunikation zwischen einem Arduino und dem PC (Windows) wird die serielle Schnittstelle verwendet (USB->Serial-Adapter auf Arduino-Seite).

    Um die serielle Schnittstelle mit Nim ansprechen zu können, habe ich ein Objekt erstellt, das die entsprechenden Methoden bereitstellt.

    Zum testen habe ich einen Arduino Nano genommen und dieses C++ Programm darauf gepackt:

    Code
    char buf[64];
    
    void TicksToTime(uint32_t ticks) {
      uint16_t h, m, s;
      s = (ticks / 1000);
      h = (s / 3600);
      s = (s % 3600);
      m = (s / 60);
      s = (s % 60);
      sprintf(buf, "Time = %02d:%02d:%02d ", h, m, s);
    }
    
    void setup() {
      Serial.begin(115200);
      pinMode(LED_BUILTIN, OUTPUT);
      digitalWrite(LED_BUILTIN, LOW);
    }
    
    void loop() {
      if (Serial.available()) {
        String s = Serial.readString();
        digitalWrite(LED_BUILTIN, HIGH);
        TicksToTime(millis());
        Serial.print(buf);
        Serial.println(s);
        Serial.flush();
        delay(1000);
        digitalWrite(LED_BUILTIN, LOW);
      }
    }
    Alles anzeigen

    Mein Objekt in Nim sieht so aus:

    Code
    include winim/[inc\winbase]
    
    type
      SerialComm* = ref object of RootObj
        hPort: HANDLE
        cto: COMMTIMEOUTS
        dcb: DCB
    
    method SetTimeOut*(this: SerialComm, ms: int): bool {.discardable, base.} =
      if this.hPort <= 0: return false
      this.cto.ReadIntervalTimeout = DWORD ms
      this.cto.ReadTotalTimeoutMultiplier = 10
      this.cto.WriteTotalTimeoutMultiplier = 10
      this.cto.ReadTotalTimeoutConstant = DWORD ms
      this.cto.WriteTotalTimeoutConstant = DWORD ms
      return SetCommTimeouts(this.hPort, this.cto.addr) == TRUE
    
    method SetState*(this: SerialComm, bdRate: int = CBR_9600): bool {.discardable, base.} =
      this.dcb.DCBlength = DWORD sizeof(DCB)
      this.dcb.fBinary = TRUE
      this.dcb.fParity = FALSE
      this.dcb.fOutxCtsFlow = FALSE
      this.dcb.fOutxDsrFlow = FALSE
      this.dcb.fDtrControl = DTR_CONTROL_DISABLE
      this.dcb.fDsrSensitivity = FALSE
      this.dcb.fNull = FALSE
      this.dcb.fOutX = FALSE
      this.dcb.fInX = FALSE
      this.dcb.fRtsControl = RTS_CONTROL_DISABLE
      this.dcb.fAbortOnError = TRUE
      this.dcb.BaudRate = DWORD bdRate
      this.dcb.ByteSize = 8
      this.dcb.Parity = NOPARITY
      this.dcb.StopBits = ONESTOPBIT
      result = SetCommState(this.hPort, this.dcb.addr) == TRUE
    
    method Tx*(this: SerialComm, data: cstring): bool {.discardable, base.} =
      if this.hPort <= 0: return false
      var
        sData: cstring = data
        dummy: DWORD
      WriteFile(this.hPort, sData, DWORD sData.len + 1, dummy.addr, NULL)
      FlushFileBuffers(this.hPort)
      return true
    
    method Rx*(this: SerialComm): string {.base.} =
      if this.hPort <= 0: return ""
      var
        buffer: array[128, char]
        length: DWORD
      ReadFile(this.hPort, buffer.addr, 128, length.addr, NULL)
      if length == 0: return ""
      for i in 0..length-1: 
        case buffer[i] 
        of chr(0), chr(10), chr(13): break
        else: result.add(buffer[i])
    
    method OpenPort*(this: SerialComm, port: string, bdRate: int = 9600, tmMillis: int = 50): bool {.discardable, base.} =
      if port == "": return false
      var sPort: string
      if port[0..3] != "\\\\.\\": sPort = "\\\\.\\" & port else: sPort = port
      let sFile = newWideCString(sPort)
      let pFile = cast[LPCWSTR](sFile[0].addr)
      this.hPort = CreateFile(pFile, GENERIC_READ or GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0)
      if this.hPort <= 0: return false
      # PurgeComm discards all characters from the output or input buffer of a specified communications resource.
      # It can also terminate pending read or write operations on the resource.
      PurgeComm(this.hPort, PURGE_TXABORT or PURGE_RXABORT or PURGE_TXCLEAR or PURGE_RXCLEAR)
      this.SetState(bdRate)
      this.SetTimeOut(tmMillis)
      return true
    
    method ClosePort*(this: SerialComm): bool {.discardable, base.} =
      if this.hPort <= 0: return false
      CloseHandle(this.hPort)
      this.hPort = -1
      return true
    Alles anzeigen

    Und das Beispielprogramm dazu:

    Code
    import SerialComm
    
    let mySerial = SerialComm() # Objekt erstellen
    mySerial.OpenPort("COM6", 115200, 50) # COM6 oeffnen (115200 Baud, 50 ms Timeout)
    mySerial.Tx("Das ist ein Test.\r\n") # den Text senden
    let ret = mySerial.Rx() # die Antwort empfangen
    echo "Laenge: ", ret.len
    echo "Empfang: ",  ret
    mySerial.ClosePort() # die Schnittstelle schliessen

    Wenn man, wie ich, mehrere Arduinos bestzt, dann kommt es schonmal vor, dass man unter Windows COM-Ports mit Nummern größer als 9 hat (COM10, COM11, COM12, usw.).

    Um diese COM-Ports ansprechen zu können, muss man "\\.\" davor schreiben. Mein Objekt berücksichtigt das aber bereits intern und setzt immer diese Kennung davor (falls nicht vorhanden), sodass man auch die "hohen" Ports problemlos benutzen kann.

    Außerdem habe ich die Einstellungen mal fest auf acht Datenbits, keine Parität und ein Stopbit ("8N1") gesetzt, weil das bei den meisten Geräten so Standard ist.

    Man kann also "nur" die Baudrate und die TimeOut-Zeit (in Millisekunden) übergeben. Ich denke, dass das aber wohl ausreicht.

    Die obigen Programme befinden sich auch nochmal im ZIP-Archiv (Anhang) zum herunterladen.

    Dateien

    SerialComm.zip 2,24 kB – 552 Downloads
  • Icon Datei in .exe einbinden

    • Oscar
    • 2. Juli 2020 um 18:21
    Zitat von HansJ54

    vermutlich hat Oscar das Beispiel auch damit erstellt!?

    Genau! Der Generator wird immer angeschmissen, wenn ich Binaries (Bilder, Musik oder Fonts) mit in die Exe packen will.

  • AutoIT - Prognosen zur Weiterentwicklung

    • Oscar
    • 2. Juli 2020 um 16:20
    Zitat von alpines

    Jede Sprache hat ihre eigene Daseinsberechtigung. Natürlich kann man in AutoIt Programme schreiben, und das kann ich auch nur jedem empfehlen der mal die Füße ins kalte Wasser namens Programmieren stecken möchte,

    AutoIt war (und ist) für mich immer eine BASIC-ähnliche Sprache. Also das, was ich früher in BASIC (zum Beispiel auf dem C64) geschrieben habe, schreibe ich heute in AutoIt.

    Ehrlich gesagt, habe ich AutoIt noch nie zur Automatisierung von Fremdprogrammen benutzt. Ich habe das immer gleich komplett mit AutoIt erledigt. Gerade weil AutoIt diese Möglichkeiten bietet.

    Ok, manches ist etwas zeitkritisch, aber dafür habe ich im Laufe der Jahre gelernt, wie man Assembler-Routinen mit AutoIt benutzten kann (an dieser Stelle ein dickes Dankeschön an Andy).

    Das Einzige, was mir in den letzten Jahren auf den Keks geht, sind die blöden AntiViren-Programme, die alle AutoIt-Programm fälschlicherweise als Virus ansehen und ungefragt löschen.

    Dafür kann AutoIt nichts, zugegeben, aber das führte dazu, dass ich mich in letzter Zeit viel mit "Nim" beschäftige.

  • AutoIT - Prognosen zur Weiterentwicklung

    • Oscar
    • 2. Juli 2020 um 14:49
    Zitat von Landfloh

    Aber wenn das Teil eh stirbt, dann such ich was neues..

    Naja, nur weil eine Programmiersprache "nicht mehr weiterentwickelt wird" (was ja nicht ganz stimmt), stirbt sie ja nicht (im Sinne von Aussterben).

    AutoIt funktioniert einwandfrei, auch unter Windows10.

    Insofern muss man sagen: Wenn Dir AutoIt als Programmiersprache gefällt und Dir ausreicht, dann arbeite Dich wieder ein.

  • Icon Datei in .exe einbinden

    • Oscar
    • 2. Juli 2020 um 10:20

    Hier mal ein Beispiel mit Base64-kodierten Daten:

    AutoIt
    #include <GDIPlus.au3>
    #include <GUIConstantsEx.au3>
    #include <SendMessage.au3>
    #include <StaticConstants.au3>
    #include <WinAPIHObj.au3>
    #include <WinAPIInternals.au3>
    
    _GDIPlus_Startup()
    Global $iSize = 32, $hResize, $hRed, $hGreen
    
    $hRed = _GDIPlus_BitmapCreateFromMemory(_redpng()) ; GDI+ Bitmap erstellen von Base64-Daten
    $hResize = _GDIPlus_ImageResize($hRed, $iSize, $iSize) ; auf gewuenschte Groesse skalieren ($hResize ist eine Kopie)
    _GDIPlus_BitmapDispose($hRed) ; $hRed kann weg
    $hRed = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hResize) ; $hResize von GDI+ nach GDI-Bitmap wandeln
    _GDIPlus_BitmapDispose($hResize) ; jetzt kann auch $hResize weg
    
    $hGreen = _GDIPlus_BitmapCreateFromMemory(_greenpng())
    $hResize = _GDIPlus_ImageResize($hGreen, $iSize, $iSize)
    _GDIPlus_BitmapDispose($hGreen)
    $hGreen =  _GDIPlus_BitmapCreateHBITMAPFromBitmap($hResize)
    _GDIPlus_BitmapDispose($hResize)
    
    _GDIPlus_Shutdown()
    
    Global $hGui = GUICreate('Test', 240, 240)
    Global $idPic1 = GUICtrlCreatePic('', 10, 10, $iSize, $iSize)
    Global $idPic2 = GUICtrlCreatePic('', 10, 20 + $iSize, $iSize, $iSize)
    
    GUISetState()
    
    _SetImage($idPic1, $hRed)
    _SetImage($idPic2, $hGreen)
    Sleep(2000)
    _SetImage($idPic1, $hGreen)
    _SetImage($idPic2, $hRed)
    Do
    Until GUIGetMsg() = $GUI_EVENT_CLOSE
    _WinAPI_DeleteObject($hRed)
    _WinAPI_DeleteObject($hGreen)
    
    Func _SetImage(ByRef $idCtrl, ByRef $hImg)
        Local $hCtrl, $hPrevImage
        $hCtrl = GUICtrlGetHandle($idCtrl)
        $hPrevImage = _SendMessage($hCtrl, $STM_SETIMAGE, $IMAGE_BITMAP, $hImg)
        If $hPrevImage Then _WinAPI_DeleteObject($hPrevImage)
    EndFunc
    
    ;Code below was generated by: 'File to Base64 String' Code Generator v1.20 Build 2015-09-19
    Func _greenpng($bSaveBinary = False, $sSavePath = @ScriptDir)
        Local $greenpng
        $greenpng &= 'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAC4jAAAuIwF4pT92AAAFpklEQVRYw7WXTWxc1RXHf+fOvJnxJHUcj2KIrBaIIqjrNLgBB+erUlVVLSzamEqgqs0CVdmkFSsE7LrpJotKFRuEKG0jtYvQKPGmKeJDISQYAqRxI0IJTsa0jZPx2DMD8/W+3+lirqPBIaqT2ufpaUaaee//cc6591xRVZYTmUxmw4FnD+yiwN5UmNreL/1fE5FUkARx+VpZLjcv/+dy7fLZhQsLE82LzVNRFJWW815ZDoGXDr/0Wm+2d0/cFzvvtt41p9ecpnFvAzZAQkIwH+D/w8eb8kidSyV3l+8OWqb13sUTF7+vqt5tEzjw3IEnH9n0yG/ntszJK3e9QlGLhBqCgqKEGhIT4+JSi2u46mIw9JgezGkDPyEJR8Nftf/a/vUtE3jx2Ivv9w30bTux44Q5wxkCAnrpZY/sYUzGMBjmmadOnRmdYVIn+TT+lGbSJIgDFEVESP08lcjH8nF4LtyiXwJ2A4GDvz+YH8wNfu6OuunDmw8zq7MMyiCPyWPcyZ00aHCFK1zlKhUqzDGHj0+GDJ56lLREKS7RjtpopCAgx4XcEzn17vcGkslkoRsvvZTRxtzG6uwPZ9MT+Ql89RmXccZkDB+fN3mTC1ygQoUmTRZYoE0bB4cBBnDEQUQoSAEMtKWNBor+QPEWPMkVcmXA3JTAC0dfOMW3yE7kJ4iI2Gf2McQQU0zxFm8xwwxXuYqP36kBQhTFs5cgODisl/X0ml40o7jqdkj4ivc7T5wR53w4FW5dxLzOZueTO58gy45D9x2ipjUeN48zxBBv8AZHOcokkxQp0qCBj09AJ8/QKciAAB+fFi3mmKMudfImT0+2B3EEEtCHleieaFi+K09fV62qqCoHf3Mw3NHaof1hv+5N9uoRPaJP6VM6oiO6VteqqCi3cImK5jWvhaSgTugodZR5lBpKmhhIq2rHgf3P7P/L9O7p9Iwzwx1yB7tlN+c5z0lOcolLtGhdV7vcUBQXl7rUiVIRZKzfAfAyhq/yNwAjItKnfT9+54F3iDRixIzg4fE2b/MJn9wWeDeJkBAV7VSbAyTAHqDKt0VkvRm6f2i0ua4ZV+Mqa2UtW2UrRYpc4Qou7m2D3xDGElh0YYQ0A+w05ptm/GR4Ml2NqxhjqGiFS1ziGtcICVnRSNm+i4FRDHcxbgo9hV2VTRVQWCNrmJZpypTx8FZOPYBY9WlAgS1Ak1GTa+Xu1WElK1kKFKhTZ575lVffTQLgG0CJe9K1f9X6g6EAFEJCGjRo015Z9UtJKLARUFLp2ZnZtJd0dsySdrbwhIRVC7WdABCQNpWeSik4FxAkAaWkREtbq6debQEq8G+gB9f46/yLOqVorLSTNhWtrE7+F8FD+/kRMEDR4HCKc50/aNQZMlbFgUUCgf3+IZDnjOEsE7xPhHSx01XKewB4thA/IKbIMVFVxEhCFSGhs2b32HaRFSKQAD7wOVAHcsB9BHhs6HTlRv7MH63zQZdNukLqI8AF2lbUq0A/r6tq/fpIJuvE5Sw5ertccOwD8n/mvW3Vu3Y5/jqJhpr6wkDCQ+zjp8QYa5dra+J2nVgEd4FGF/h+Ysb45Q0Tkb6qR4h5nT9YxS7QsmSSWyCxWHChVV637xHgOFDmAz2lz990KpZeqXOcr7DZKnBsOrJWgelaUrtBl/a6BzStkEVB2wnV18zSXfqL0WA9D9PkT/ZXz6qoW0W+Lap4yd0N+hlQtcpTVvlDBGymb9kHE9kmr5HlOxwiRdaCpKwjGbutyhLLfUsisuSNzXmN9/S87rzZnPLlqfy7fo8sP2MbAYdRcpZE06orA3Ndd8UWW2z7fBIYJiHmFzcDX/bhVAblZeZ4lGGUB0kzbPfzTdaBGbu2/9OucB+iDHBcZ/VHK3I6BhARhzzbGWIcn12U2UyVPjJE5GkxQJEck0xzjAZn/tep'
        $greenpng &= 'eDH+C03pDPEhJjFDAAAAAElFTkSuQmCC'
        Local $bString = _WinAPI_Base64Decode($greenpng)
        If @error Then Return SetError(1, 0, 0)
        $bString = Binary($bString)
        If $bSaveBinary Then
            Local Const $hFile = FileOpen($sSavePath & "\green.png", 18)
            If @error Then Return SetError(2, 0, $bString)
            FileWrite($hFile, $bString)
            FileClose($hFile)
        EndIf
        Return $bString
    EndFunc   ;==>_greenpng
    
    Func _redpng($bSaveBinary = False, $sSavePath = @ScriptDir)
        Local $redpng
        $redpng &= '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'
        $redpng &= '8aynZskAAAAASUVORK5CYII='
        Local $bString = _WinAPI_Base64Decode($redpng)
        If @error Then Return SetError(1, 0, 0)
        $bString = Binary($bString)
        If $bSaveBinary Then
            Local Const $hFile = FileOpen($sSavePath & "\red.png", 18)
            If @error Then Return SetError(2, 0, $bString)
            FileWrite($hFile, $bString)
            FileClose($hFile)
        EndIf
        Return $bString
    EndFunc   ;==>_redpng
    
    Func _WinAPI_Base64Decode($sB64String)
        Local $aCrypt = DllCall("Crypt32.dll", "bool", "CryptStringToBinaryA", "str", $sB64String, "dword", 0, "dword", 1, "ptr", 0, "dword*", 0, "ptr", 0, "ptr", 0)
        If @error Or Not $aCrypt[0] Then Return SetError(1, 0, "")
        Local $bBuffer = DllStructCreate("byte[" & $aCrypt[5] & "]")
        $aCrypt = DllCall("Crypt32.dll", "bool", "CryptStringToBinaryA", "str", $sB64String, "dword", 0, "dword", 1, "struct*", $bBuffer, "dword*", $aCrypt[5], "ptr", 0, "ptr", 0)
        If @error Or Not $aCrypt[0] Then Return SetError(2, 0, "")
        Return DllStructGetData($bBuffer, 1)
    EndFunc   ;==>_WinAPI_Base64Decode
    Alles anzeigen
  • BinToBase64

    • Oscar
    • 1. Juli 2020 um 14:51

    Ich habe jetzt noch ein Beispiel mit einem Font (Base64 kodiert) hinzugefügt (Post#1).

  • BinToBase64

    • Oscar
    • 1. Juli 2020 um 10:41
    Zitat von UEZ

    Die Exe ist 1,66 MB groß

    Ja, weil der Debugger viel Platz weg nimmt.

    Bei einer Release-Version des Programms, würde man eher so compilieren: nim c -d:release --app:gui BinToBase64_example.nim

    Dann sind es nur noch 1.07 MB.

  • BinToBase64

    • Oscar
    • 1. Juli 2020 um 06:44
    Zitat von UEZ

    Ok, wie war das noch mit dem Problem?

    Hast Du denn Git installiert? (Punkt 4 auf BugFix Installationsanleitung)

  • Ausschnitt aus Bild nehmen und speichern.

    • Oscar
    • 1. Juli 2020 um 05:13
    Zitat von Commander21

    aus jedem Bild soll ein Ausschnitt ausgeschnitten und gespeichert werden.

    Immer der gleiche Ausschnitt? Also z.B. immer von 20, 60 (x,y) ein Ausschnitt von 240 x 120 (w, h).

    Geht mit GDI+ auf jeden Fall.

    Das brauchst Du dafür:

    _GDIPlus_Startup

    _GDIPlus_BitmapCreateFromFile

    _GDIPlus_BitmapCreateFromScan0

    _GDIPlus_ImageGetGraphicsContext

    _GDIPlus_GraphicsDrawImageRectRect

    _GDIPlus_ImageSaveToFile

    _GDIPlus_Shutdown

    Edit: Ich hab mal schnell eine Funktion geschrieben:

    AutoIt
    #include <GDIPlus.au3>
    _GDIPlus_Startup()
    Global $hImg = _GDIPlus_BitmapCreateFromFile(@ScriptDir & '\test.jpg')
    _GDIPlus_ImageSaveRect($hImg, @ScriptDir & '\new.jpg', 560, 288, 540, 440)
    _GDIPlus_BitmapDispose($hImg)
    _GDIPlus_Shutdown()
    
    Func _GDIPlus_ImageSaveRect(ByRef $hImage, $sFilename, $iX, $iY, $iW, $iH, $iQuality = 90)
        Local $hBitmap, $hGraphic, $sExt, $sCLSID, $tParams, $tData
        $hBitmap = _GDIPlus_BitmapCreateFromScan0($iW, $iH)
        $hGraphic = _GDIPlus_ImageGetGraphicsContext($hBitmap)
        _GDIPlus_GraphicsSetInterpolationMode($hGraphic, 7)
        _GDIPlus_GraphicsSetSmoothingMode($hGraphic, 2)
        _GDIPlus_GraphicsDrawImageRectRect($hGraphic, $hImage, $iX, $iY, $iW, $iH, 0, 0, $iW, $iH)
        $sExt = StringRegExpReplace($sFilename, '.+\.(.+)', '$1')
        Switch $sExt
            Case 'jpg', 'jpeg'
                $sCLSID = _GDIPlus_EncodersGetCLSID('JPG')
                $tParams = _GDIPlus_ParamInit(1)
                $tData = DllStructCreate('int Quality') ; Struktur fuer die JPG-Qualitaet erstellen
                DllStructSetData($tData, 'Quality', $iQuality) ; JPG-Qualitaet entsprechend setzen (von 0 = schlechteste bis 100 = beste)
                _GDIPlus_ParamAdd($tParams, $GDIP_EPGQUALITY, 1, $GDIP_EPTLONG, DllStructGetPtr($tData, 'Quality'))
                _GDIPlus_ImageSaveToFileEx($hBitmap, $sFilename, $sCLSID, $tParams)
            Case Else
                _GDIPlus_ImageSaveToFile($hBitmap, $sFilename)
        EndSwitch
        _GDIPlus_GraphicsDispose($hGraphic)
        _GDIPlus_BitmapDispose($hBitmap)
    EndFunc
    Alles anzeigen
  • BinToBase64

    • Oscar
    • 30. Juni 2020 um 19:13
    Zitat von UEZ

    muss ich miniz kompilieren oder wie kann ich es benutzen?

    Meinst Du mit Nim?

    Wenn ja, dann musst Du nur miniz in der Powershell installieren: nimble install miniz

    Danach reicht im Nim-Quellcode ein import miniz und es gibt "compress" und "uncompress" als Prozeduren.

  • BinToBase64

    • Oscar
    • 30. Juni 2020 um 10:34

    Ich habe nach einer Möglichkeit gesucht, Binärdaten mit in der Exedatei einzubinden. Analog zu dem AutoIt-"File to Base64 String Code Generator" von UEZ.

    In Nim gibt es bereits die Base64/Mime-Unterstützung und zum packen habe ich den zlib-Wrapper "miniz" gefunden (https://nimble.directory/pkg/miniz).

    Ich habe nun zwei Prozeduren geschrieben. Eine zum umwandeln von Binärdaten in einen gepackten Base64/Mime-String und Eine um das wieder rückgängig zu machen.

    Im ZIP-Archiv (Anhang) findet ihr die benötigten Dateien. Miniz muss allerdings installiert sein (siehe obigen Link)!

    In der Datei "res.nim" befinden sich bereits Base64/Mime-Daten (zum Test: das Foto von einem Zilpzalp).

    Edit: Im ZIP-Archiv "AddFontMemResourceEx.zip" (Anhang) findet ihr ein Beispiel mit einem Font, der (Base64 kodiert) vom Programm benutzt werden kann.

    Dateien

    BinToBase64.zip 373,21 kB – 555 Downloads AddFontMemResourceEx.zip 75,08 kB – 582 Downloads
  • shell.dll streikt, wenn die Gesamtlänge der Befehlszeile > 270 Zeichen ist.​

    • Oscar
    • 29. Juni 2020 um 04:52

    Versuch's mal als UNC-Pfad:

    Zitat


    To specify an extended-length path, use the "\\?\" prefix. For example, "\\?\D:\very long path".

  • ​Sammlung: Nim Snippets / Procedures

    • Oscar
    • 26. Juni 2020 um 14:10

    Nicht schlecht! :):thumbup:

    Oder gleich als OOP-Variante:

    Code
    import times, os
    
    type
      Timer* = ref object of RootObj
        t0: Time
    
    proc newTimer*(): Timer =
      new result
      result.t0 = getTime()
    
    proc init*(self: Timer): bool {.discardable.} = 
      self.t0 = getTime()
    
    proc diff*(self: Timer, unit: string = "ns", T: type = int): T =
      let 
        t1 = getTime()
        td = int((t1 - self.t0).inNanoseconds)
      case unit
        of "ns": return T(td)
        of "µs": return T(td / 1_000)
        of "ms": return T(td / 1_000_000)
        of "s": return T(td / 1_000_000_000)
        else: return T(td)
    
    let tm = newTimer()
    sleep(2500)
    echo "diff ns: ", tm.diff()
    echo "diff µs: ", tm.diff("µs")
    echo "diff ms: ", tm.diff("ms")
    echo "diff  s: ", tm.diff("s", float)
    tm.init
    sleep(1000)
    echo "diff ns: ", tm.diff()
    echo "diff µs: ", tm.diff("µs")
    echo "diff ms: ", tm.diff("ms")
    echo "diff  s: ", tm.diff("s", float)
    Alles anzeigen

    Edit: Oder noch kürzer: :)

    Code
    import times, os
    
    type
      tmUnit* = enum ns = 1, µs = 1_000, ms = 1_000_000, s = 1_000_000_000
      Timer* = ref object of RootObj
        t0: Time
    
    proc newTimer*(): Timer =
      new result
      result.t0 = getTime()
    
    proc init*(self: Timer): bool {.discardable.} = 
      self.t0 = getTime()
    
    proc diff*(self: Timer, u: tmUnit = ns, T: type = int): T =
      result = T(int((getTime() - self.t0).inNanoseconds) / int(u))
    
    let tm = newTimer()
    sleep(2500)
    echo "diff ns: ", tm.diff(ns)
    echo "diff µs: ", tm.diff(µs)
    echo "diff ms: ", tm.diff(ms)
    echo "diff  s: ", tm.diff(s, float)
    tm.init
    sleep(1000)
    echo "diff ns: ", tm.diff()
    echo "diff µs: ", tm.diff(µs)
    echo "diff ms: ", tm.diff(ms)
    echo "diff  s: ", tm.diff(s, float)
    Alles anzeigen
  • Wie kann man etwas in der MainLoop ausführen?

    • Oscar
    • 26. Juni 2020 um 13:16
    Zitat von BugFix

    Teste mal, ob das wie von dir gewünscht funktioniert.

    Nee, das funktioniert nicht. Eine Schleife in der Proc blockiert alles.

    Mit der Thread-Geschichte bin ich jetzt etwas weiter. Wenn ich das Sound-Object (was ich im Thread verwende) nochmal im zusätzlichen Thread generiere, dann klappt das ohne Absturz. Finde ich zwar nicht optimal, aber was soll's? Speicher gibt's ja genug. ;)

    Das hat also wohl damit zu tun, dass mein ooSound nicht Threadsicher ist. Aber da ich zum ersten Mal mit Multithreading zu tun habe, weiß ich überhaupt nicht, wo ich da ansetzen soll, um das zu ändern (falls das überhaupt geht).

  • Wie kann man etwas in der MainLoop ausführen?

    • Oscar
    • 25. Juni 2020 um 16:51

    Es war ja klar, dass das nicht so einfach sein kann. X/

    Wenn ich jetzt meine "ooSound" benutzen möchte, um die Sounds abzuspielen (im zusätzlichen Thread), dann stürzt das Programm ab, sobald ich auf den Button klicke und es kommen folgende Meldungen:

    Zitat

    e:\Nim Source\MainLoop\ooSound.nim(5, 8) Warning: imported and not used: 'os' [UnusedImport]

    e:\Nim Source\MainLoop\MainLoopThread.nim(34) MyMainLoop

    e:\Nim Source\MainLoop\ooSound.nim(43) play

    e:\Nim Source\MainLoop\ooSound.nim(45) play

    e:\Nim Source\MainLoop\ooSound.nim(36) pos

    e:\Nim Source\MainLoop\ooSound.nim(41) pos

    C:\Users\Thomas\.choosenim\toolchains\nim-1.2.0\lib\pure\strutils.nim(1087) parseInt

    Error: unhandled exception: invalid integer: [ValueError]

    Error: execution of an external program failed: '"e:\Nim Source\MainLoop\MainLoopThread.exe" '

    Alles anzeigen

    Damit ihr das nachvollziehen könnt, habe ich mal alle benötigten Dateien zusammengepackt (Anhang).

    Nach meinen Recherchen im INet, kommt das wohl vom Garbage Collector (GC), weil ich ja ein Sound-Object vom Mainthread verwende.

    Aber wie kann ich das Problem lösen?

    Dateien

    MainLoop.zip 4,15 kB – 468 Downloads

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™