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

Beiträge von Andy

  • Mit StringFromASCIIArray ANSI-Zeichensatz erzeugen ?

    • Andy
    • 3. Dezember 2013 um 18:54

    Hi,
    beim "normalen" programmieren in AutoIt benötigt man idR keine Structs, die Funktion erfüllen universelle Arrays viel einfacher und übersichtlicher.
    Der Vorteil an den Structs ist, dass man eine Speicheradresse bekommt, imho in AutoIt die einzige Möglichkeit direkt an Datenstrukturen im Speicher zu kommen.
    Die Speicheradresse ist somit der Schlüssel, um mit "schnellerem" Code (in welcher Programmiersprache auch immer) die Daten zu bearbeiten.

    Zitat

    Allein schon die Erkenntnis, dass man Assemblercode in ein AutoIt-Programm einbauen kann.

    Hehe, ja, das ist schon etwas seltsam. Da gibt es KOSTENLOS die geilsten Hochsprachencompiler, und die Bekloppten werkeln in einer SCRIPT-Sprache mit Assembler rum....viel bescheuerter geht es kaum noch :D
    Aber da stehe ich drüber, ich bin kein Programmierer, sondern Techniker. Ich mache das, weil es mir Spass macht. Wenn mir etwas keinen Spass macht, dann mache ich es nicht! Das Leben ist zu kurz, um sich mit Sachen rumzuschlagen, gegen die man eine Abneigung hat...

  • kurze frage :)

    • Andy
    • 3. Dezember 2013 um 18:32

    Hi,
    ich habe diesen Beitrag nicht freigeschaltet, weil

    Zitat

    Ich vermute mal, er möchte eher auf einem imaginären (hoffe ich doch) Ziffernblock alle Kombination von 0000 bis 9999 automatisiert durchprobieren

    das keine Vermutung ist, sondern klar wie Kloßbrühe!
    Daher geht ein Modcall raus.

  • Mit StringFromASCIIArray ANSI-Zeichensatz erzeugen ?

    • Andy
    • 2. Dezember 2013 um 22:39

    Hi,

    Zitat

    Ich habe zwar mein ganzes berufliches Leben nur immer in Assembler auf "Großrechnern" programmiert (seit 1963).

    Juhuuuuu, noch einer dieser Dinosaurier :thumbup: Da bin ich endlich nicht mehr alleine^^
    Obwohl ich um die Zeit, als du angefangen hast Großrechner zu programmieren, gerade mal geboren wurde :D
    Trotzdem fing ich schon relativ früh an als Schüler, Ende der Siebziger, mit per Maschinesprache programmierbaren Taschenrechnern rumzuwerkeln. 3435 Byte waren da das Limit an RAM, da musste das Programm, die Daten und auch noch die "Grafikausgabe" rein, selbstmodifizierender Code war selbstverständlich, da habe ich nicht mal drüber nachgedacht...
    Dann endlich der erste gebrauchte IBM-PC mit 8088-Prozessor (4,77 Mhz) , dem ich dann nach 1/2 Jahr sparen einen der superseltenen 8087 Coprozessoren gegönnt hatte um endlich SCHNELL mit "echten" Floats rechnen zu können. Dieser Coprozessor konnte sowieso nur direkt mit Maschinesprache bzw mit Assembler angesteuert werden. Compiler mit dem "x87-Schalter" gab es erst Jahre später.
    So habe ich die Ein-Ausgabe und das Grundgrüst der Programme in Basic geschrieben, die geschwindigkeitskritischen Teile dann in Assembler. Diese Kombination benutze ich heute noch, AutoIt als "Träger" und Assembler, wenns mal etwas schneller werden muss 8o

    Das geht sogar relativ einfach, entweder man erstellt mit einem Assembler eine DLL und ruft eine Funktion innerhalb dieser DLL aus AutoIt heraus auf, oder man schreibt den assemblierten Code in den Speicher und springt diesen aus AutoIt heraus direkt an, sehr simpel.
    Mittlerweile habe ich schon einen sehr leistungsfähigen Assembler (FASM) so mit AutoIt verbinden können, dass der Assemblercode "fast" inline im AutoItcode zu verwenden ist.
    Lange Rede, kurzer Sinn, gerade für die Bildbe- und Verarbeitung bietet sich Assembler an, das Bitmap-Format ist simpel, und die erreichbaren Geschwindigkeiten übertreffen (nach tagelanger Handoptimierung ^^ ) sogar manchmal die gängigen C-Compiler :rolleyes:
    Hier im Forum finden sich einige Threads und Beispiele zu diesem Thema, idR verwende ich nicht mehr als eine Handvoll Oldschool-8088-Assemblerbefehle, die zu "lernen" sollte das Problem nicht sein, und da du ja aus der Materie kommst, schonmal garnicht :thumbup:

    Für dein "Problem" benutze ich gerne mal AssembleIt() , aber lieber in der neuen Version AssembleIt2(). Damit reduziert sich die Laufzeit um geschätzt Faktor 100 bis 200.

    Spoiler anzeigen
    [autoit]

    #include <ScreenCapture.au3>
    #include "AssembleIt2.au3"

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ;assemblercode ersetzt Farben bestimmter Spezifikation innerhalb einer Bitmap

    [/autoit] [autoit][/autoit] [autoit]

    #cs Farben_ersetzen
    use32 ;32-Bitmode

    [/autoit] [autoit][/autoit] [autoit]

    mov edi,[esp+4] ;pointer bitmap
    mov ecx,[esp+8] ;Bitmap anzahl bytes
    mov esi,[esp+12] ;pointer parameterstruct
    mov ebx,[esi+8] ;farbe_ersetzen
    mov edx,0 ;zähler ersetzte pixel

    [/autoit] [autoit][/autoit] [autoit]

    schleife:
    mov eax,[edi+ecx] ;pixel ARGB

    [/autoit] [autoit][/autoit] [autoit]

    cmp al,byte[esi+4] ;al>blau_von?
    jb naechstes_pixel ;wenn kleiner, nächstes pixel
    cmp al,byte[esi+5] ;al<blau_bis?
    ja naechstes_pixel ;wenn grösser, nächstes pixel

    [/autoit] [autoit][/autoit] [autoit]

    shr eax,8 ;al = ah
    cmp al,byte[esi+2] ;al>gruen_von?
    jb naechstes_pixel ;wenn kleiner, nächstes pixel
    cmp al,byte[esi+3] ;al<gruen_bis?
    ja naechstes_pixel ;wenn grösser, nächstes pixel

    [/autoit] [autoit][/autoit] [autoit]

    shr eax,8 ;al = ah
    cmp al,byte[esi+0] ;al>rot_von?
    jb naechstes_pixel ;wenn kleiner, nächstes pixel
    cmp al,byte[esi+1] ;al<rot_bis?
    ja naechstes_pixel ;wenn grösser, nächstes pixel

    [/autoit] [autoit][/autoit] [autoit]

    mov [edi+ecx],ebx ;pixel mit Farbe_ersetzen
    add edx,1 ;eins mehr ersetzt

    [/autoit] [autoit][/autoit] [autoit]

    naechstes_pixel:
    sub ecx,4 ;nächstes pixel
    cmp ecx,0 ;erstes pixel erreicht?
    jge schleife ;nein, weitermachen

    [/autoit] [autoit][/autoit] [autoit]

    mov eax,edx ;rückgabe anzahl ersetzte pixel

    [/autoit] [autoit][/autoit] [autoit]

    ret

    [/autoit] [autoit][/autoit] [autoit]

    #ce

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ;Farben in einer Bitmap-Datei ändern

    [/autoit] [autoit][/autoit] [autoit]

    $bitmap_datei = "Testbitmap.bmp"

    [/autoit] [autoit][/autoit] [autoit]

    $hgui = GUICreate("") ;fenster mit rotem Inhalt erstellen
    GUISetBkColor(0x960AD2)
    GUISetState()
    Sleep(500) ;fenster anzeigen
    ; Erstellt einen Screenshot vom kompletten Bildschirm, Bitmapdatei erzeugen
    _ScreenCapture_SetBMPFormat(4) ;4 = 32 bpp; 8 Bit für jede RGB und Alpha Komponente
    _ScreenCapture_Capture($bitmap_datei) ;screenshot vom Bildschirm erstellen und abspeichern

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    $inhalt = FileRead($bitmap_datei) ;Dateiinhalt
    $header = StringLeft($inhalt, 54) ;54byte Bitmap-Header
    $inhalt = StringTrimLeft($inhalt, 54) ;header abschneiden$bitmap_anzahl_bytes = StringLen($inhalt) ;länge string

    [/autoit] [autoit][/autoit] [autoit]

    $bitmap_anzahl_bytes = StringLen($inhalt)
    $struct_bitmap = DllStructCreate("byte[" & $bitmap_anzahl_bytes & "]") ;string im speicher BGRA als BYTEs
    $ptr_Bitmap = DllStructGetPtr($struct_bitmap) ;pointer startadresse Bitmap
    $struct_pixel = DllStructCreate("dword[" & $bitmap_anzahl_bytes / 4 & "]", $ptr_Bitmap);an derselben Adresse eine struct für die "Pixel" DWORD

    [/autoit] [autoit][/autoit] [autoit]

    DllStructSetData($struct_bitmap, 1, StringToBinary($inhalt)) ;string in struct

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ;ab hier fängt der Assemblerteil an, zuerst wird eine hilfs-struct erstellt, damit man nicht so viele parameter an die Funktion übergeben muss
    $struct_parameter = DllStructCreate("byte Rot_von;" & _
    "byte Rot_bis;" & _
    "byte Gruen_von;" & _
    "byte Gruen_bis;" & _
    "byte Blau_von;" & _
    "byte Blau_bis;" & _
    "word _align;" & _ ;nur zur verdeutlichung, AutoIt aligned jeden anderen Datentyp an einer 8-Bit-grenze!
    "dword Farbe_ersatz") ;fängt bei startadresse +8 an, auch wenn das word _align weggelassen wird!
    $ptr_parameter = DllStructGetPtr($struct_parameter) ;pointer auf die parameter

    [/autoit] [autoit][/autoit] [autoit]

    ;farbfeld des Pixels, innerhalb dessen das Pixel durch eine bestimmte Farbe ersetzt wird
    $Rot_von = 123
    $Rot_bis = 188
    $Gruen_von = 0
    $Gruen_bis = 20
    $Blau_von = 200
    $Blau_bis = 220

    [/autoit] [autoit][/autoit] [autoit]

    ;in die struct schreiben, man könnte auch direkt die parameter schreiben^^
    DllStructSetData($struct_parameter, "Rot_von", $Rot_von) ;ESI
    DllStructSetData($struct_parameter, "Rot_bis", $Rot_bis) ;ESI+1
    DllStructSetData($struct_parameter, "Gruen_von", $Gruen_von) ;ESI+2
    DllStructSetData($struct_parameter, "Gruen_bis", $Gruen_bis) ;ESI+3
    DllStructSetData($struct_parameter, "Blau_von", $Blau_von) ;ESI+4
    DllStructSetData($struct_parameter, "Blau_bis", $Blau_bis) ;ESI+5
    ;dllstructcreate aligned an 8 byte grenzen, daher habe ich zur verdeutlichung das word _align in die struct eingefügt
    DllStructSetData($struct_parameter, "Farbe_ersatz", 0xFF00FF00) ;ESI+8 Achtung, wg little Endian ARGB !!!

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    $t = TimerInit()
    ;code assemblieren und aufrufen
    $anzahl_pixel_ersetzt = _AssembleIt2("uint", "Farben_ersetzen", "ptr", $ptr_Bitmap, "int", $bitmap_anzahl_bytes, "ptr", $ptr_parameter)

    [/autoit] [autoit][/autoit] [autoit]

    $m = TimerDiff($t)
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $m = ' & $m & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $anzahl_pixel_ersetzt = ' & $anzahl_pixel_ersetzt & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    $inhalt = BinaryToString(DllStructGetData($struct_bitmap, 1)) ;Bitmap aus der struct in den string

    [/autoit] [autoit][/autoit] [autoit]

    FileDelete($bitmap_datei) ;alte datei löschen
    FileWrite($bitmap_datei, $header & $inhalt) ;und neu schreiben

    [/autoit] [autoit][/autoit] [autoit]

    ShellExecute($bitmap_datei)

    [/autoit] [autoit][/autoit] [autoit]

    Exit

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ;alternativ kann man auch einmal assemblieren, dann nur noch den code in den speicher schreiben und callen
    ;Assembleit ist dann nicht mehr erforderlich

    [/autoit] [autoit][/autoit] [autoit]

    $ret_asm = _AssembleIt2("retbinary", "Farben_ersetzen") ;assemblieren
    ;$ret_asm = "0x8B7C24048B4C24088B74240C8B5E08BA000000008B040F3A460472243A4605771FC1E8083A460272173A46037712C1E8083A06720B3A46017706891C0F83C20183E90483F9007DCC89D08B4608C3"
    $struct_asm = DllStructCreate("byte[" & StringLen($ret_asm) / 2 - 1 & "]") ;platz für asmcode im speicher
    $ptr_asm = DllStructGetPtr($struct_asm) ;pointer asmcode
    DllStructSetData($struct_asm, 1, $ret_asm) ;asmcode in struct schreiben

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    $ret = DllCallAddress("uint:cdecl", $ptr_asm, "ptr", $ptr_Bitmap, "int", $bitmap_anzahl_bytes, "ptr", $ptr_parameter)

    [/autoit]


    Mittels AssembleIt2() läuft der Code, welcher in AutoIt ca. 8 Sekunden gebraucht hat (nicht schlecht übrigens^^) nun in ca. 50 Millisekunden. Also wirklich 200x schneller...

    Allerdings sollte man bedenken, dass ja der komplette Code assembliert werden muss, das ist ja noch als "Overhead" beim Aufruf vorhanden.
    Assembliert man den Code mittels Assembleit einmal und schreibt diesen in den Speicher und called, dann bleibt als reine Laufzeit 5ms übrig, also 2000x schneller als der AutoIt-Code.
    Dann kann auch AssembleIt() völlig wegfallen...

    Spoiler anzeigen
    [autoit]


    #AutoIt3Wrapper_UseUpx=n
    #AutoIt3Wrapper_UseX64=n

    [/autoit] [autoit][/autoit] [autoit]

    ;assemblercode ersetzt Farben bestimmter Spezifikation innerhalb einer Bitmap

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    #include <ScreenCapture.au3>
    ;Farben in einer Bitmap-Datei ändern

    [/autoit] [autoit][/autoit] [autoit]

    $bitmap_datei = "Testbitmap.bmp"

    [/autoit] [autoit][/autoit] [autoit]

    $hgui = GUICreate("") ;fenster mit rotem Inhalt erstellen
    GUISetBkColor(0x960AD2)
    GUISetState()
    sleep(500)
    ; Erstellt einen Screenshot vom kompletten Bildschirm, Bitmapdatei erzeugen
    _ScreenCapture_SetBMPFormat(4) ;4 = 32 bpp; 8 Bit für jede RGB und Alpha Komponente
    _ScreenCapture_Capture($bitmap_datei) ;screenshot vom Bildschirm erstellen und abspeichern
    Sleep(500) ;fenster anzeigen

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    $inhalt = FileRead($bitmap_datei) ;Dateiinhalt
    $header = StringLeft($inhalt, 54) ;54byte Bitmap-Header
    $inhalt = StringTrimLeft($inhalt, 54) ;header abschneiden$bitmap_anzahl_bytes = StringLen($inhalt) ;länge string

    [/autoit] [autoit][/autoit] [autoit]

    $bitmap_anzahl_bytes = StringLen($inhalt)
    $struct_bitmap = DllStructCreate("byte[" & $bitmap_anzahl_bytes & "]") ;string im speicher BGRA als BYTEs
    $ptr_Bitmap = DllStructGetPtr($struct_bitmap) ;pointer startadresse Bitmap
    $struct_pixel = DllStructCreate("dword[" & $bitmap_anzahl_bytes / 4 & "]", $ptr_Bitmap);an derselben Adresse eine struct für die "Pixel" DWORD

    [/autoit] [autoit][/autoit] [autoit]

    DllStructSetData($struct_bitmap, 1, StringToBinary($inhalt)) ;string in struct

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ;ab hier fängt der Assemblerteil an, zuerst wird eine hilfs-struct erstellt, damit man nicht so viele parameter an die Funktion übergeben muss
    $struct_parameter = DllStructCreate("byte Rot_von;" & _
    "byte Rot_bis;" & _
    "byte Gruen_von;" & _
    "byte Gruen_bis;" & _
    "byte Blau_von;" & _
    "byte Blau_bis;" & _
    "word _align;" & _ ;nur zur verdeutlichung, AutoIt aligned jeden anderen Datentyp an einer 8-Bit-grenze!
    "dword Farbe_ersatz") ;fängt bei startadresse +8 an, auch wenn das word _align weggelassen wird!
    $ptr_parameter = DllStructGetPtr($struct_parameter) ;pointer auf die parameter

    [/autoit] [autoit][/autoit] [autoit]

    ;farbfeld des Pixels, innerhalb dessen das Pixel durch eine bestimmte Farbe ersetzt wird
    $Rot_von = 123
    $Rot_bis = 188
    $Gruen_von = 0
    $Gruen_bis = 20
    $Blau_von = 200
    $Blau_bis = 220

    [/autoit] [autoit][/autoit] [autoit]

    ;in die struct schreiben, man könnte auch direkt die parameter schreiben^^
    DllStructSetData($struct_parameter, "Rot_von", $Rot_von) ;ESI
    DllStructSetData($struct_parameter, "Rot_bis", $Rot_bis) ;ESI+1
    DllStructSetData($struct_parameter, "Gruen_von", $Gruen_von) ;ESI+2
    DllStructSetData($struct_parameter, "Gruen_bis", $Gruen_bis) ;ESI+3
    DllStructSetData($struct_parameter, "Blau_von", $Blau_von) ;ESI+4
    DllStructSetData($struct_parameter, "Blau_bis", $Blau_bis) ;ESI+5
    ;dllstructcreate aligned an 8 byte grenzen, daher habe ich zur verdeutlichung das word _align in die struct eingefügt
    DllStructSetData($struct_parameter, "Farbe_ersatz", 0xFF00FF00) ;ESI+8 Achtung, wg little Endian ARGB !!!

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ;assemblercode in den Speicher schreiben, die folgenden Zeilen wurden von AssembleIt() erstellt
    $ret_asm = "0x8B7C24048B4C24088B74240C8B5E08BA000000008B040F3A460472243A4605771FC1E8083A460272173A46037712C1E8083A06720B3A46017706891C0F83C20183E90483F9007DCC89D0C3"
    $struct_asm = DllStructCreate("byte[" & StringLen($ret_asm) / 2 - 1 & "]") ;platz für asmcode im speicher
    $ptr_asm = DllStructGetPtr($struct_asm) ;pointer asmcode
    DllStructSetData($struct_asm, 1, $ret_asm) ;asmcode in struct schreiben

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    $t = TimerInit()
    ;asmcode callen
    $ret = DllCallAddress("uint:cdecl", $ptr_asm, "ptr", $ptr_Bitmap, "int", $bitmap_anzahl_bytes, "ptr", $ptr_parameter)

    [/autoit] [autoit][/autoit] [autoit]

    $m = TimerDiff($t)

    [/autoit] [autoit][/autoit] [autoit]

    $anzahl_pixel_ersetzt = $ret[0] ;DllCallAddress gibt ein array zurück
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $m = ' & $m & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $anzahl_pixel_ersetzt = ' & $anzahl_pixel_ersetzt & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    $inhalt = BinaryToString(DllStructGetData($struct_bitmap, 1)) ;Bitmap aus der struct in den string

    [/autoit] [autoit][/autoit] [autoit]

    FileDelete($bitmap_datei) ;alte datei löschen
    FileWrite($bitmap_datei, $header & $inhalt) ;und neu schreiben

    [/autoit] [autoit][/autoit] [autoit]

    ShellExecute($bitmap_datei)

    [/autoit] [autoit][/autoit] [autoit]

    Exit

    [/autoit]

    //EDIT Script für 64-Bit Windows-Versionen angepasst, #AutoIt3Wrapper_UseX64=n
    Auf meinem Win7-64-Laptop seltsames Verhalten. Die "GUI" wird, wenn kein sleep() nach dem GuiSetState() eingesetzt wird, nicht dargestellt!
    Bei Sleep(100) wird die GUI Transparent angezeigt ?(
    Bei sleep(500) läuft alles wie gewollt!

  • Mit StringFromASCIIArray ANSI-Zeichensatz erzeugen ?

    • Andy
    • 1. Dezember 2013 um 22:50

    Hi,
    habe da mal etwas auf die schnelle gebastelt:
    Es wird jedes Pixel aus der Bitmap verglichen, ob es deinen Spezifikationen entspricht, wenn ja, wird die Farbe ausgetauscht, in der gesamten Bitmap.
    Ich habe dazu die Bitmap als String geladen und in eine Struct (in den Speicher) geschrieben, um jedes einzelne Pixel adressieren zu können.

    Bei mir dauert der Lauf durch die Bitmap incl. Austauschen ca. 8 Sekunden, bei 1680x1050 Pixeln.

    Spoiler anzeigen
    [autoit]

    #include <ScreenCapture.au3>
    ;Farben in einer Bitmap-Datei ändern

    [/autoit] [autoit][/autoit] [autoit]

    $bitmap_datei = "Testbitmap.bmp"

    [/autoit] [autoit][/autoit] [autoit]

    $hgui = GUICreate("") ;fenster mit rotem Inhalt erstellen
    GUISetBkColor(0x960AD2)
    GUISetState()

    [/autoit] [autoit][/autoit] [autoit]

    ; Erstellt einen Screenshot vom kompletten Bildschirm, Bitmapdatei erzeugen
    _ScreenCapture_SetBMPFormat(4) ;4 = 32 bpp; 8 Bit für jede RGB und Alpha Komponente

    [/autoit] [autoit][/autoit] [autoit]

    _ScreenCapture_Capture($bitmap_datei) ;screenshot vom Bildschirm erstellen und abspeichern
    Sleep(500) ;fenster anzeigen

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    $inhalt = FileRead($bitmap_datei) ;Dateiinhalt
    $header = StringLeft($inhalt, 54) ;54byte Bitmap-Header
    $inhalt = StringTrimLeft($inhalt, 54) ;header abschneiden

    [/autoit] [autoit][/autoit] [autoit]

    ;zähler
    $p = 0

    [/autoit] [autoit][/autoit] [autoit]

    $t = TimerInit()
    $x = StringLen($inhalt) ;länge string

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    $struct = DllStructCreate("byte[" & $x & "]") ;string im speicher BGRA
    $struct_pixel = DllStructCreate("dword[" & $x / 4 & "]", DllStructGetPtr($struct));an derselben adresse eine struct für die "Pixel"
    DllStructSetData($struct, 1, StringToBinary($inhalt));string in struct

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    For $i = 1 to $x step 4 ;jedes Pixel in der Bitmap BGRA, 4 Byte sind 1 Pixel
    $b = DllStructGetData($struct, 1, $i) ;blau
    if $b > 200 and $b < 220 then
    $g = DllStructGetData($struct, 1, $i + 1);grün
    if $g < 20 then
    $r = DllStructGetData($struct, 1, $i + 2);rot
    if $r > 123 and $r < 188 then
    DllStructSetData($struct_pixel, 1, 0xFF000000, Int($i / 4) + 1) ;wenn treffer, schwarz schreiben, achtung little endian!
    $p += 1 ;ersetzen-zähler
    EndIf
    EndIf
    endif
    next
    $m = TimerDiff($t)
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $m = ' & $m & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $p = ' & $p & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console

    [/autoit] [autoit][/autoit] [autoit]

    $inhalt = BinaryToString(DllStructGetData($struct, 1)) ;Bitmap aus der struct in den string

    [/autoit] [autoit][/autoit] [autoit]

    FileDelete($bitmap_datei) ;alte datei löschen
    FileWrite($bitmap_datei, $header & $inhalt) ;und neu schreiben

    [/autoit] [autoit][/autoit] [autoit]

    ShellExecute($bitmap_datei)

    [/autoit] [autoit][/autoit] [autoit][/autoit]


    Wenn es noch schneller sein muss, dann sollte man eine Lösung per asm oder, am schnellsten, OpenCl verwenden.
    Selbst asm wäre in einigen Zeilen erledigt, beschränkt sich lediglich auf einige Vergleiche, die Struct ist ja vorhanden.

  • Mit StringFromASCIIArray ANSI-Zeichensatz erzeugen ?

    • Andy
    • 1. Dezember 2013 um 19:24

    Hi,
    na dann sag das doch gleich^^
    Da die Bitmaps so einfach aufgebaut sind, lassen sie sich vortrefflich mit Assembler bearbeiten^^
    Aber zu deinem Problem:

    Zitat

    Und das dauert mit StringReplace bei einer großen Datei und vielen zu ersetzenden Pixeln eine Ewigkeit.

    Na, da schauen wir mal...
    Irgendwo hatte ich das schon mal in AutoIt programmiert, sooo lange hat das garnicht gedauert.
    20x20x50 = 20000 mögliche Pixelfarben...mit welcher Farbe sollen die ersetzt werden?

  • Mit StringFromASCIIArray ANSI-Zeichensatz erzeugen ?

    • Andy
    • 1. Dezember 2013 um 18:35

    Hi,
    stringreplace() ersetzt pfeilschnell beliebige Strings. Ob die "Daten" nun Pixel in einer Bitmap sind oder ein Text ist dabei völlig irrelevant!
    Ich vermute, deine Bitmap-Dateien haben entweder das RGBA (32Bit) oder RGB(24-Bit) -Format.
    Wichtig ist das ehrlich gesagt nicht, wichtiger wäre vielmehr, was du genau machen willst!

    Die Bitmap wird definiert über ihren sog. Header, das ist ein Datenfeld von 54 Bytes, in dem die Bitmap beschrieben ist. Breite, Höhe, Farbformat usw.
    Dieser Header steht in der Bitmap-Datei vor den Pixel-Daten.

    Anbei ein kurzes Script, welches in einer Bitmap rot (ABGR 0xFF0000FF) durch Grün (ABGR 0xFF00FF00) ersetzt und zwar mittels stringreplace()

    Spoiler anzeigen
    [autoit]

    #include <ScreenCapture.au3>
    ;Farben in einer Bitmap-Datei ändern

    [/autoit] [autoit][/autoit] [autoit]

    $bitmap_datei = "Testbitmap.bmp"

    [/autoit] [autoit][/autoit] [autoit]

    $hgui = GUICreate("") ;fenster mit rotem Inhalt erstellen
    GUISetBkColor(0xFF0000)
    GUISetState()

    [/autoit] [autoit][/autoit] [autoit]

    ; Erstellt einen Screenshot vom kompletten Bildschirm, Bitmapdatei erzeugen
    _ScreenCapture_SetBMPFormat(4) ;4 = 32 bpp; 8 Bit für jede RGB und Alpha Komponente

    [/autoit] [autoit][/autoit] [autoit]

    _ScreenCapture_Capture($bitmap_datei) ;screenshot vom Bildschirm erstellen und abspeichern
    Sleep(500) ;fenster anzeigen

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    $inhalt = FileRead($bitmap_datei) ;Dateiinhalt
    $header = StringLeft($inhalt, 54) ;54byte Bitmap-Header

    [/autoit] [autoit][/autoit] [autoit]

    ;Farben je Pixel: Alpha,Blau,Grün,Rot
    $weiss = BinaryToString("0xFFFFFFFF") ;ABGR
    $schwarz = BinaryToString("0xFF000000") ;ABGR
    $rot = BinaryToString("0xFF0000FF")
    $gruen = BinaryToString("0xFF00FF00")

    [/autoit] [autoit][/autoit] [autoit]

    $inhalt = StringTrimLeft($inhalt, 54) ;header abschneiden

    [/autoit] [autoit][/autoit] [autoit]

    $inhalt = StringReplace($inhalt, $weiss, $schwarz, 0, 1);weiß durch schwarz ersetzen
    $inhalt = StringReplace($inhalt, $rot, $gruen, 0, 1);rot durch grün ersetzen

    [/autoit] [autoit][/autoit] [autoit]

    $ersetzt = @extended ;anzahl der ersetzten Pixel

    [/autoit] [autoit][/autoit] [autoit]

    FileDelete($bitmap_datei) ;alte datei löschen
    FileWrite($bitmap_datei, $header & $inhalt);und neu schreiben

    [/autoit] [autoit][/autoit] [autoit]

    ShellExecute($bitmap_datei)

    [/autoit]
  • While Schleife beenden - wie Fehlermeldung von Windows benutzen

    • Andy
    • 1. Dezember 2013 um 16:54

    Hi,
    am allerbesten ist es, "Fehlermeldungen" erst garnicht entstehen zu lassen!
    Statt Energie darauf zu verwenden, Fehler zu kompensieren, sollte man lieber dafür sorgen, dass diese Fehler nicht auftreten.

    Zitat

    In meiner ersten Aufgabe wollte ich Tastendrücke in einer Applikation automatisieren. Dort kann es zu "störenden" Meldungen kommen, wenn der bearbeitete Datensatz Fehler beinhaltet.

    wenn du externe Programme steuern willst und die "Datensätze" nicht bereinigen kannst, dann hast du die Möglichkeit, mit dem AU3Info.EXE-Tool (schau mal im root-Verzeichnis von AutoIt) die nötigen Informationen aus dem "Fehlerfenster" zu ziehen und darauf zu reagieren.

  • Mit StringFromASCIIArray ANSI-Zeichensatz erzeugen ?

    • Andy
    • 1. Dezember 2013 um 00:12

    Hallo Dieter,

    Zitat

    Ich habe eine Bitmap-Datei eingelesen und in ein Array umgewandelt. Dann habe ich eine große Anzahl von Pixeln verändert und das veränderte Array wieder zurückverwandelt und als neue Bitmap-Datei geschrieben. Und das hat nicht richtig geklappt.


    Viele Wege führen nach Rom :D
    Die Variante, die "Pixel" über ein Array auszutauschen, bzw. zu bearbeiten, ist eher ungewöhnlich. Die "Pixel" in einer Bitmap liegen "so schön" nebeneinander, da hättest du sicher kein zusätzliches Array gebraucht.
    Aber wenn es funktioniert, ist es ja gut :thumbup:

  • DLLCall etc.

    • Andy
    • 30. November 2013 um 20:15
    Zitat

    Ich wusste ganz einfach nicht was "The size of the structure, in bytes. You must set this member before calling GlobalMemoryStatusEx. " mir sagen soll.

    Naja, dass du die Größe der Struct in das erste Element schreiben musst, bevor du die Funktion aufrufst :D
    Aber mal Scherz beiseite, das ist doch bei JEDER Funktion einer x-beliebigen Computersprache so, dass man die "richtigen" Eingangsparameter setzen muss, um ein valides Ergebnis zu erhalten?!
    Schau dir mal in der Hilfe die Funktionen mit vorangestelltem _ an, das sind größtenteils nur Wrapper für die entsprechenden DLL-Calls

    [autoit]

    Func _GDIPlus_BrushClone($hBrush)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipCloneBrush", "handle", $hBrush, "ptr*", 0)
    If @error Then Return SetError(@error, @extended, 0)
    Return SetExtended($aResult[0], $aResult[2])
    EndFunc ;==>_GDIPlus_BrushClone

    [/autoit]

    wenn dort die "falschen" Parameter übergeben werden, ist doch klar, dass "hinten" nichts vernünftiges rauskommt.
    Also wieder was gelernt, nicht nur lesen, sondern auch umsetzen ist das Geheimnis :thumbup:

  • Mit StringFromASCIIArray ANSI-Zeichensatz erzeugen ?

    • Andy
    • 30. November 2013 um 20:02

    Hi,
    ändere mal in

    [autoit]

    $str2=StringFromASCIIArray($arr,1, UBound($array) - 1,1)

    [/autoit]

    also nicht von 0 bis 299, sondern von 1 bis 299, dann klappt es, scheint so, als hätte die Funktion ein Problem mit ANSI NULL.
    Darf ich fragen, was diese Tests für einen Hintergrund haben? Es gibt Funktionen, welche die Umwandlung von ANSI/ASCII/UTF8/UTF16 durchführen.

  • While Schleife beenden - wie Fehlermeldung von Windows benutzen

    • Andy
    • 30. November 2013 um 18:01

    Hi,
    wieso liest du nicht einfach die Textdatei ein, löschst in jeder Zeile alles ab dem \ und schreibst die Datei wieder?
    Das wird maximal ein 5-Zeiler und du musst dich nicht weiter um irgendwelche "Send"-Geschichten kümmern, welche in 90% aller Fälle genau dann NICHT funktionieren, wenn man sie am nötigsten braucht...

    [autoit]

    ;alles nach dem backslash bis zum zeilenende löschen und durch crlf ersetzen
    FileDelete("Test ohne Backslash.txt") ;Ergebnis löschen
    FileWrite("Test ohne Backslash.txt", StringRegExpReplace(FileRead(FileOpenDialog("Bitte Datei auswählen", @ScriptDir, "(*.txt)")), "(?m)(\\.*$)", @crlf)) ;schreiben
    ShellExecute("Test ohne Backslash.txt") ;anzeigen

    [/autoit]

    verkürzte Version als 3-Zeiler, bin zwar nicht der RegEx-Fan, aber bei solch einfachen Sachen bekomme selbst ich es gebacken^^

    In der "Langversion" wird eine Testdatei von 1.5MB Größe erstellt, und die Strings werden ersetzt

    Spoiler anzeigen
    [autoit]

    ;testdatei erstellen
    $text = "Wort1\blablub1" & @crlf & "Wort2\blablub2" & @crlf & "Wort3\blablub3" & @CRLF
    for $i = 1 to 15 ;"große" Textdatei erstellen, 1,5MB
    $text &= $text
    Next

    [/autoit] [autoit][/autoit] [autoit]

    FileDelete("test.txt") ;Datei löschen
    FileWrite("test.txt", $text) ;Datei erstellen
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $text = ' & StringLen($text) & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ;alles nach dem Backslash in der Textdatei in jeder Zeile löschen
    $inhalt = FileRead("test.txt") ;Datei lesen
    $inhalt = StringRegExpReplace($inhalt, "(?m)(\\.*$)", @crlf);alles nach dem backslash bis zum zeilenende löschen und durch crlf ersetzen
    FileDelete("Test ohne Backslash.txt") ;Ergebnis löschen
    FileWrite("Test ohne Backslash.txt", $inhalt) ;schreiben
    ShellExecute("Test ohne Backslash.txt") ;anzeigen

    [/autoit]

    //EDIT und noch eine Version, wie ich sie "zu Fuß" schreiben würde, wenn ich keinerlei Ahnung von RegEx hätte

    Spoiler anzeigen
    [autoit]

    $inhalt = FileRead("test.txt") ;Datei lesen
    $pos = StringInStr($inhalt, "", 1) ;position Backslash
    do
    $crlf = StringInStr($inhalt, @crlf, 1, 1, $pos);Zeilenende suchen ab position Backslash
    $mid = StringMid($inhalt, $pos, $crlf - $pos + 1) ;string dazwischen incl crlf
    $inhalt = StringReplace($inhalt, $mid, @crlf, 0, 1);ersetzen mit crlf
    $pos = StringInStr($inhalt, "", 1) ;nächste backslash position
    until $pos = 0

    [/autoit] [autoit][/autoit] [autoit]

    FileDelete("Test ohne Backslash.txt") ;Ergebnis löschen
    FileWrite("Test ohne Backslash.txt", $inhalt) ;schreiben
    ShellExecute("Test ohne Backslash.txt") ;anzeigen

    [/autoit]
  • DLLCall etc.

    • Andy
    • 30. November 2013 um 15:24

    Hi,
    allererste Aktion nach dem Aufrufen einer Funktion ist zu prüfen, ob die Funktion überhaupt Erfolg zurückgemeldet hat!
    Das sollte in jeder Programmiersprache mit jeder Funktion machbar sein und gilt insbesondere für DllCalls!

    Bei deinem DllCall() bekommt man als Ergebnis 0, MSDN sagt dazu

    Zitat

    If the function succeeds, the return value is nonzero.

    Aha...die Frage ist, wieso.

    Aber wie meistens gilt der Spruch: "Wer lesen kann, ist klar im Vorteil" :D

    MSDN sagt weiterhin bei der MEMORYSTATUSEX structure

    Zitat

    dwLength
    The size of the structure, in bytes. You must set this member before calling GlobalMemoryStatusEx.


    Aha, "set this member"...also machen wir das mal^^

    Spoiler anzeigen
    [autoit]

    #include <Array.au3>

    [/autoit] [autoit][/autoit] [autoit]

    $tagMemoryStatusEx = "dword dwLength;" & _
    "dword dwMemoryLoad;" & _
    "uint64 ullTotalPhys;" & _
    "uint64 ullAvailPhys;" & _
    "uint64 ullTotalPageFile;" & _
    "uint64 ullAvailPageFile;" & _
    "uint64 ullTotalVirtual;" & _
    "uint64 ullAvailVirtual;" & _
    "uint64 ullAvailExtendedVirtual"

    [/autoit] [autoit][/autoit] [autoit]

    $tBuffer = DllStructCreate($tagMemoryStatusEx)
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $tBuffer = ' & $tBuffer & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console

    [/autoit] [autoit][/autoit] [autoit]

    ;Große der Struct ermitteln
    $bufferlen=DllStructGetSize($tbuffer)
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $bufferlen = ' & $bufferlen & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console

    [/autoit] [autoit][/autoit] [autoit]

    ;Größe setzen
    DllStructSetData($tbuffer,"dwLength",$bufferlen)

    [/autoit] [autoit][/autoit] [autoit]

    $pBuffer = DllStructGetPtr($tBuffer)
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $pBuffer = ' & $pBuffer & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console

    [/autoit] [autoit][/autoit] [autoit]

    $hKernel32 = DllOpen("kernel32.dll")
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $hKernel32 = ' & $hKernel32 & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console

    [/autoit] [autoit][/autoit] [autoit]

    $ret=DllCall($hKernel32, "BOOLEAN", "GlobalMemoryStatusEx", "ptr", $pBuffer)
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $ret = ' & $ret & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
    _arraydisplay($ret)

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Local $aiReturn[9]

    [/autoit] [autoit][/autoit] [autoit]

    $aiReturn[0] = DllStructGetData($tBuffer, "dwLength")
    $aiReturn[1] = DllStructGetData($tBuffer, "dwMemoryLoad")
    $aiReturn[2] = DllStructGetData($tBuffer, "ullTotalPhys")
    $aiReturn[3] = DllStructGetData($tBuffer, "ullAvailPhys")
    $aiReturn[4] = DllStructGetData($tBuffer, "ullTotalPageFile")
    $aiReturn[5] = DllStructGetData($tBuffer, "ullAvailPageFile")
    $aiReturn[6] = DllStructGetData($tBuffer, "ullTotalVirtual")
    $aiReturn[7] = DllStructGetData($tBuffer, "ullAvailVirtual")
    $aiReturn[8] = DllStructGetData($tBuffer, "ullAvailExtendedVirtual")

    [/autoit] [autoit][/autoit] [autoit]

    _ArrayDisplay($aiReturn)

    [/autoit] [autoit][/autoit] [autoit][/autoit]

    Wenn du dir jetzt auch das Tut in meiner Signatur durchliest, wie man Scriptfehler findet und beseitigt, kennst du auch die Tastenkombination, um all die nützlichen Consolewrites() die per Alt-d eingefügt wurden, alle auf einmal aus dem Script zu entfernen^^

  • Awesome Teamspeak service

    • Andy
    • 30. November 2013 um 09:59

    Hi,
    die Idee ist gut, so bekommt man (von awesome´s Seite aus gesehen) einen wunderschönen und (fast) kostenlosen Einblick in die Serververwaltung :thumbup:
    Ich spiele ab und zu Guildwars(2), aber bei weitem nicht mehr so exzessiv wie früher. Da hatten wir den eigenen Teamspeakserver auf unserer Gilden-Homepage angebunden, ein Klick und man war "drin"...
    Die HP ist mittlerweile verwaist und nur noch sporadisch genutzt (muss mal gucken ob die überhaupt noch online ist^^ ) genauso wie das TS. Wenn ich nun einen TS-Channel brauche, erstelle ich einen im Wartower...ohne Anmeldung, PW und sonstige Stolpersteine.

    Zitat

    Filesharing

    Was hat das bitteschön mit TS zu tun? (die Frage war rhetorisch...)
    Ich würde das an deiner Stelle KOMPLETT unterbinden, man braucht kein Prophet zu sein um die Absicht zu erkennen einen TS-Server zu benutzen um Files zu sharen....

    Zitat

    Illegale Aktivitäten

    hast du damit nämlich sofort erschlagen ;)

  • Perseus 2.6 - Caffeinated Cat

    • Andy
    • 30. November 2013 um 09:42

    Hi,
    bitte, wie schon einmal angesprochen, die benötigten Files "unkomprimiert" (wegen mir in einer "Special-Edition" ) zur Verfügung stellen.
    1. ist es suboptimal, Virenscanner "umzubiegen" damit fremde Exe´n keine "Fehlalarme" :rolleyes: verursachen ("Alda, da is kein Virus oder Backdoor drin, ISCH SCHWÖR")
    2. ist die FASM.dll von Haus aus nicht gepackt
    Installer wäre nett, da gibt es eine Scriptsprache für....moment mal, gleich hab ichs...AutoIt :thumbup:

  • Ein kleines Tool für eine Optionsänderung

    • Andy
    • 30. November 2013 um 09:23

    Hi,
    In AutoIt gibt es AU3Record.exe, das ist ein Tool, welches Maus/Tastatureingaben "aufnimmt" und "auf Knopfdruck" wieder abspielt...
    Und nebenbei noch den AutoIt-Code erstellt ;)
    Imho genau das, was du brauchst.

  • SQLite Insert - 0 erscheint aus dem Nichts

    • Andy
    • 30. November 2013 um 09:08

    Hi,
    wenn du den Befehl "nicht falsch" von Hand eingibst, dann tritt auch kein Fehler auf, logisch...
    Wieso lässt du dir den String nicht einfach per Console oder Msgbox ausgeben und siehst dann sofort, wo das Problem liegt?!
    Dann ist die gesamte Fragerei und Posterei hinfällig, da du SOFORT siehst, was "falsch" ist.

    [autoit]

    _SQLite_Exec($db,"INSERT INTO RegisteredClients VALUES ('"&$hSocket&"','"&$sIP&"','"&$sName&"','False','"-"','"-"','""');") ;Klappt nicht

    [/autoit][autoit]

    _SQLite_Exec($db,"INSERT INTO RegisteredClients VALUES ('568','0','Jonas','-','-','-','17:41');") ;Klappt

    [/autoit][autoit]

    $hSocket = 426
    $sIP = 0
    $sName = "Jonas"
    MsgBox(0, "zusammen falsch", "'" & $hSocket & "','" & $sIP & "','" & $sName & "','False','" - "','" - "','""'")
    MsgBox(0, "einzeln falsch", "'" & $hSocket & "','" & @crlf & _
    $sIP & "','" & @crlf & _
    $sName & @crlf & _
    "','False','" - "','" - "','""'")
    ;aha...FALSE=0, stimmt, wird
    ;aber in deiner oberen Zeile falsch
    ;interpretiert, weil du die Anführungszeichen falsch setzt...
    ;sieht man in Scite übrigens schon im Quellcode, die waagrechten
    ;"Minuszeichen" sind rot, also Rechenzeichen statt, wie gewollt, Strings!

    [/autoit][autoit][/autoit][autoit]

    ;Anführungszeichen richtig gesetzt:
    Msgbox(0,"richtig"," '568','0','Jonas','-','-','-',' ")

    [/autoit][autoit][/autoit][autoit][/autoit][autoit][/autoit]

    ergo:
    Anführungszeichen richtig setzen, dann wird auch der Code "richtig" ausgeführt!

    Btw, aus dem "Nichts" erscheint garnichts, du hast die 0 eindeutig hingeschrieben....

    [autoit]

    Msgbox(0,0,"False="&False)

    [/autoit]
  • Grafik Schneefall

    • Andy
    • 29. November 2013 um 13:41

    HIER ist auch etwas....

  • Rechnen...

    • Andy
    • 28. November 2013 um 13:30

    Die Lösung ist, nicht einfach eine Formel hinzukrachen, sondern "Hilfe zur Selbsthilfe" :thumbup:
    Über das Prinzip der "Superposition" kommt man dann durch die Addition der von mir in Post 3 erstellten Gleichungen zu einer Gleichung, welche die Lösung aller 3 Gleichungen abdeckt.
    Auf diese Art und Weise werden vielfältige Probleme in Mathematik, Physik und Technik gelöst, die ansonsten viel zu kompliziert wären :rolleyes:

  • Happy Burtstag Der_Doc und BugFix

    • Andy
    • 28. November 2013 um 13:23

    Glücklichen Herzwunsch an alle Geburtstagskinder! :thumbup:

  • Rechnen...

    • Andy
    • 27. November 2013 um 21:51

    Hi,

    Zitat

    Währe super wnen mir hier jemand auf die Sprünge helfen könnte

    Dem Manne kann geholfen werden! 8o

    Es gibt 3 Fälle zur Ermittlung der Anzahl der Quartale:
    1) Jahr2 = Jahr1 => Ergebnis ist Differenz der Quartale
    2) Jahr2 = Jahr1+1 => Ergebnis ist Restquartale Jahr1 + Anzahl Quartale Jahr2
    3) Jahr2 = Jahr1+x => Ergebnis ist Restquartale Jahr1 + Anzahl Quartale Jahrx + 4*(Jahr2 - Jahr1 - 1)

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™