Beiträge von Oscar

    Nachdem ich gestern wie blöd einen Fehler in meinem Programm gesucht habe, entdeckte ich den Fehler in "wNim/wImageList".

    Sowohl "getBitmap" als auch "getIcon" sind fehlerhaft!

    In beiden Fällen wird der übergebene Index nicht beachtet, sondern stattdessen immer mit "Index 0" gearbeitet.

    Die Original-Prozedur sieht so aus:

    Code
    proc getIcon*(self: wImageList, index: int): wIcon {.validate, property.} =
    ## Create the icon from specified index.
    if index <= self.getImageCount():
    var hIcon = ImageList_GetIcon(self.mHandle, 0, ILD_TRANSPARENT)
    result = Icon(hIcon, copy=false)

    Der zweite Parameter von "ImageList_GetIcon" muss eigentlich der Index sein, stattdessen steht da "0".

    Und in der Prozedur "getBitmap" das Gleiche:

    Der zweite Parameter von "ImageList_GetImageInfo" muss ebenfalls den Index enthalten, stattdessen "0".

    Ich habe die "getIcon"-Prozedur jetzt so geändert:

    Code
    proc newGetIcon*(self: wImageList, index: int): wIcon =
    if index <= self.getImageCount():
    var hIcon = ImageList_GetIcon(self.mHandle, cast[int32](index), ILD_TRANSPARENT)
    result = Icon(hIcon, copy=false)

    So arbeitet sie einwandfrei!

    Analog dazu kann man auch die "getBitmap"-Prozedur anpassen.

    Vielleicht praktischerweise gleich "einpacken" in eine Funktion

    Ja, stimmt!

    Aber dann als "FileIconInit()":

    Danke für den Stupser in die Richtung!

    So scheint es jetzt zu funktionieren:

    Code
    import winim
    type fii = proc(fRestoreCache: WINBOOL): WINBOOL {.gcsafe, stdcall.}
    let
    shell32 = LoadLibrary("shell32.dll")
    pAddr = GetProcAddress(shell32, cast[LPCSTR](660))
    if IsBadCodePtr(pAddr):
    echo "Error!"
    else:
    let FileIconInit = cast[fii](pAddr)
    echo "FileIconInit: ", FileIconInit(TRUE)

    Ich muss von Nim aus FileIconInit aufrufen. Nur leider gibt es die Funktion nicht in winim.

    Laut MSDN:

    Zitat

    FileIconInit is not included in a header file. You must call it directly from Shell32.dll, using ordinal 660.

    In AutoIt wird das so gelöst:

    AutoIt
    DllCall('shell32.dll', 'int', 660, 'int', True)

    Aber wie geht das in Nim?

    Weil es mich interessierte, wie das mit den Icons aus der System-ImageList im Listview funktioniert, habe ich mich mal reingekniet und ein Beispiel erarbeitet.

    Damit werden die Icons zu den Dateien/Verzeichnissen im Listview (funktioniert auch beim Treeview) wie im Explorer dargestellt, also mit den passenden Icons.

    Erklärungen gibt es noch bei den Kommentaren:

    Ich habe auch mal wieder ein Snippet!

    Das sind alles so Nebenprodukte vom meinem MP3-Player. :)

    Und wenn ich dafür sonst kein Beispiel ergoogeln konnte, muss ich halt selbst eines erstellen.

    Dieses Mal geht es um das Sortieren von einem Listview (bei wNim List-Ctrl):

    Aber dann sind die Min/Max-Button etwas "verloren" positioniert. Dann schon lieber disabled.

    Ist das denn so schlimm, dass der Close-Button zwar vorhanden ist, aber halt disabled?

    Ich denke, das ist doch einfach der "Look an feel" von Windows. Ein Fenster ohne Close-Button wirkt IMHO eher wie ein Exot (zumindest wenn es sich nicht um ein Fenster komplett ohne Systemmenü handelt).

    Um mit meinem MP3-Player voranzukommen, brauchte ich eine Möglichkeit die Reihenfolge der Einträge in der Playlist (ListView) mit der Maus zu verändern (nach oben/unten ziehen).

    Dazu habe ich bei Google nichts finden können. Mit AutoIt hatte ich das bereits umgesetzt. Vom Prinzip her wusste ich also, wie es geht, aber das Ganze mit Nim hinzukriegen war dann doch eine stundenlange Tortur, mit Suchen im AutoIt-Script und den UDFs, auf MSDN und bei C-Sourcecodes.

    Naja, lange Rede, kurzer Sinn: Ich hab's dann doch geschafft. :)

    Man kann jetzt also Dateien vom Explorer auf die Playlist ziehen (das war der einfache Teil) und innerhalb der Playlist die Einträge verschieben (der aufwendige Teil).

    Hier also das Beispielprogramm (ListView Drag and Drop):

    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:

    Edit:

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

    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.

    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:

    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.


    Hier mal das Beispielprogramm:


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

    Dateien

    • ooMPEG.zip

      (9,33 kB, 19 Mal heruntergeladen, zuletzt: )

    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:

    Mein Objekt in Nim sieht so aus:

    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, 17 Mal heruntergeladen, zuletzt: )

    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.

    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.

    Hier mal ein Beispiel mit Base64-kodierten Daten: