Dll erstellen und mit AutoIt nutzen - FreeBasic Tutorial

  • Ich hab hier mal ein rudimentäres Tutorial zusammengeklopft, welches zeigen soll, wie man in FreeBasic eine Dll für AutoIt erstellt.

    Dieses Tutorial richtet sich in erster Linie an all diejenigen, die mit AutoIt begonnen haben zu programmieren und nun so langsam an die Geschwindigkeitsgrenze von AutoIt stoßen.

    Ich habe mich für FreeBasic entschieden, weil es Free ist, eine ähnliche Syntax wie AutoIt hat, sehr klein und ohne unnötige Extras daherkommt und bei zahlreichen Test kleinere und schnellere Dll´s gezaubert hat als andere Compiler.
    Wer AutoIt beherscht sollte damit relativ leicht zurechtkommen!


    Einrichten von FreeBasic:

    Zunächst benötigen wir den Compiler, welcher u.a. hier zu finden ist: http://www.freebasic-portal.de/downloads/aktu…indows-199.html
    Als Editor verwende ich FBEdit: http://www.freebasic-portal.de/downloads/ides…dit-ide-30.html

    EDIT: Dank BugFix kann man nun auch SciTE als Editor verwenden: FreeBasic läßt sich auch rudimentär in SciTE einbinden :rock:


    1) FreeBasic installieren:
    Einfach FreeBASIC-0.23.0-win32.exe ausführen und den Anweisungen folgen

    2) FBEdit.zip in den FreeBasic-Ordner enpacken (z.B.: C:\Programme\FreeBASIC\FbEdit)

    3) FBEdit starten:
    Beim ersten Start muss man die Pfade eingeben:
    Compiler Path: C:\Programme\FreeBASIC
    Help Path: C:\Programme\FreeBASIC\FbEdit\Help

    Activate FbEdit Lite for beginners mit "Nein" beantworten.

    4) Hilfe einrichten:
    Um die Hilfe in FbEdit benutzen zu können, muss noch das hier geladen werden: http://www.freebasic-portal.de/downloads/refe…0-23-0-198.html
    Nach dem Entpacken in FB.chm umbenennen und in den Hilfe-Ordner kopieren.
    Ich selber habe noch "win32.hlp" im Hilfe-Ordner liegen
    Diese 4 Hilfen (FB.chm, FbEdit.chm, Windows_Styles.chm u win32.hlp) sind standartmässig bereits eingetragen und können via Options-Help Menu editiert werden


    Erstellen einer DLL:

    1) FbEdit starten
    2) File - New Project
    3) Project Name und Description eingeben
    4) "Project Type" = "Windows dll" auswählen und OK klicken

    5) Folgenden Code ins Editorfenster eintippen:

    Code
    Extern "Windows-MS"
    
    
    Function _Add(iX As Integer, iY As Integer)As Integer Export
    	Return iX + iY	
    End Function
    
    
    End Extern

    6) Make - Compile im Menü aufrufen oder F5 drücken
    Fertig ist die erste Dll

    Zum testen benötigen wir noch ein AutoIt-Script:

    [autoit]

    $hDll = DllOpen("Add.dll")
    $aResult = DllCall($hDll, "int", "_Add", "int", 1234, "int", 1234)
    ConsoleWrite("Ergebnis = " & $aResult[0] & @CRLF)

    [/autoit]

    Kurze Beschreibung der DLL:
    Funktionen, welche man mit AutoIt aufrufen möchte, sollten zwischen <Extern "Windows-MS"> und <End Extern> stehen
    Dadurch kann man die Funktionen dann mit demselben Namen aufrufen, wie er im Editor auch angegeben ist.
    Andernfalls müsste man bei DllCall "_ADD@8" schreiben, und sollte man 3 Parameter übergeben dann: "_ADD@12", bei 4 "_ADD@16" usw...

    Die Funktion selber sollte eigentlich selbserklärend sein.
    Für jeden Parameter und auch den Rückgabewert muss man einen Datentyp angeben (As Integer)
    Das "Export" am Ende der Zeile macht die Funktion "nach aussen hin sichtbar" und muss nur für Funktionen angegeben werden, welche man direkt via AutoIt aufrufen möchte.


    Parameter können auch ByRef übergeben werden.
    Das funktioniert ungefähr so:

    Code
    Extern "Windows-MS"
    
    
    Sub _ByRef(iX As Integer, iY As Integer, ByRef iZ As Integer) Export
    	iZ = iX + iY
    End Sub
    
    
    End Extern


    [autoit]

    $hDll = DllOpen("ByRef.dll")
    $aResult = DllCall($hDll, "none", "_ByRef", "int", 1234, "int", 1234, "int*", 0)
    ConsoleWrite("+ Ergebnis = " & $aResult[3] & @CRLF)

    [/autoit]



    Hier noch ein kurzes Beispiel, wie man den Inlineassembler von FreeBasic benutzt:


    [autoit]

    $hDll = DllOpen("ASM.dll")
    $aResult = DllCall($hDll, "int", "_ASM_ADD", "int", 1234, "int", 1234)
    ConsoleWrite("+ Ergebnis = " & $aResult[0] & @CRLF)

    [/autoit]


    Verwenden von Arrays:
    Um eine große Anzahl von Daten an die Dll zu übergeben bzw. zu erhalten, erstellt man in AutoIt zunächst eine DllStruct und deren Pointer wird an die Dll übergeben.

    Beispiel:
    2 Arrays vom Typ integer und Singlefloat mit jeweils 100 Einträgen werden benötigt:
    In AutoIt erstellt man nun eine DllStruct:

    [autoit]

    $tStruct = DllStructCreate("int X[100]; float Y[100];")

    [/autoit]


    In FreeBasic muss man zunächst einen Type definieren, damit der Compiler weiß wie die Daten im Speicher liegen:

    Code
    Type t_Struct
    	X(1 To 100) As Integer
    	Y(0 To 99) As Single
    End Type
    
    
    Sub _Test(pStruct As t_Struct Ptr)


    (Hier kann man je nach belieben 1-100 oder 0-99 verwenden)

    Der Parameter heisst hier pStruct und ist ein Pointer zu einem Speicherbereich in welchem die Daten lt. t_Struct liegen.

    Wie man nun damit arbeitet, soll folgendes Beispiel zeigen:


    [autoit]

    $tCircle = DllStructCreate("int iMX; int iMY; float aX[360]; float aY[360];")
    $pCircle = DllStructGetPtr($tCircle)

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

    $hDll = DllOpen("Array.dll")
    DllCall($hDll, "none", "_Circle", "int", 400, "int", 400, "int", 180, "ptr", $pCircle)

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

    For $i=1 To 360
    $iX = DllStructGetData($tCircle, "aX", $i)
    $iY = DllStructGetData($tCircle, "aY", $i)
    MouseMove($iX, $iY, 1)
    ConsoleWrite($iX & " " & $iY & @CRLF)
    Next

    [/autoit]


    Am Schluss noch ein paar Infos:
    Wenn man die Datei mit der Endung .fbp mit einem normalen Text-Editor öffnet, dann kann man die Compileroptionen verändern:
    Die Zeile sieht in unseren Beispielen so aus:
    1=Windows dll,fbc -s gui -dll -export
    Wir fügen nun -R hinzu:
    1=Windows dll,fbc -s gui -dll -export -R
    Wenn wir die Datei nun mit FbEdit öffnen und neu kompilieren, dann entsteht eine neue Datei mit der Endung .asm
    Darin finden wir unsere Funktionen als Assembler Code und das kann manchmal ganz nützlich sein.

    Die Parameter -fpmode FAST -fpu SSE legen in bestimmten Fällen noch den Turbo ein.
    Wenn die Dll fertig ist, dann am besten 2mal komiplieren, einmal ohne und einmal mit diesen Parametern; und überprüfen welche Version schneller ist ;)
    (bei einer meinen Tests konnte ich so eine Funktion von etwa 600ms auf 450ms beschleunigen)


    Das wars für´s Erste mal...
    Bei Interesse an weiteren, spezielleren Beispielen (z.B.: Bildbearbeitung) einfach melden.

    Im Anhang sind noch alle obigen Beispiele als Quallcode und comiliert


    EDIT 1
    Hier zwei Beispiele für Fortgeschrittene:

    Anhand eines einfachen Greyscale-Algorithmuses zeige ich hier, wie man in FreeBasic Multithreading realisiert:

    GreyScale.bas:

    Spoiler anzeigen


    Und das dazugehörige AutoIt Script zum Testen:

    Spoiler anzeigen
    [autoit]

    #include <GDIPlus.au3>

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

    Global $sPath = FileOpenDialog("open image", "", "(*.jpg;*.bmp;*.png;*.tif;*.gif)")
    If @error Or Not FileExists($sPath) Then Exit

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

    _GDIPlus_Startup()

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

    Global $hImage = _GDIPlus_ImageLoadFromFile($sPath)
    Global $aData = _CreatePixelData($hImage)
    _GDIPlus_ImageDispose($hImage)

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

    Global $hDll = DllOpen(@ScriptDir & "\GreyScale.dll")
    Global $iTimer = TimerInit()
    DllCall($hDll, "none", "_GreyScale", "ptr", $aData[0], "int", $aData[3] * $aData[4])
    Global $iTime = TimerDiff($iTimer)
    ConsoleWrite(@error & " " & @extended & @CRLF)

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

    _GDIPlus_ImageSaveToFile($aData[2], @ScriptDir & "\GreyScale.bmp")

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

    _DisposePixelData($aData)
    _GDIPlus_Shutdown()
    DllClose($hDll)

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

    MsgBox(0, "Fertig", "GreyScale fertig in : " & Round($iTime, 3) & "ms" & @CRLF & " 3 Thread wurde übersprungen, deshalb ist das fertige Bild nicht komplett im Grauton!")
    ShellExecute(@ScriptDir & "\GreyScale.bmp")

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

    Func _CreatePixelData($hImage)
    Local $iImgW = _GDIPlus_ImageGetWidth($hImage)
    Local $iImgH = _GDIPlus_ImageGetHeight($hImage)

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

    Local $tPixelData = DllStructCreate("uint[" & $iImgW * $iImgH & "];")

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

    Local $aResult = DllCall($ghGDIPDll, "uint", "GdipCreateBitmapFromScan0", "int", $iImgW, "int", $iImgH, "int", $iImgW * 4, "int", 0x0026200A, "ptr", DllStructGetPtr($tPixelData), "int*", 0)
    If @error Then Return SetError(1, 1, False)
    Local $hBitmap = $aResult[6]

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

    Local $hContext = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    _GDIPlus_GraphicsDrawImageRect($hContext, $hImage, 0, 0, $iImgW, $iImgH)
    _GDIPlus_GraphicsDispose($hContext)

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

    Local $aReturn[5]
    $aReturn[0] = DllStructGetPtr($tPixelData)
    $aReturn[1] = $tPixelData
    $aReturn[2] = $hBitmap
    $aReturn[3] = $iImgW
    $aReturn[4] = $iImgH

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

    Return $aReturn
    EndFunc ;==>_CreatePixelData

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

    Func _DisposePixelData(ByRef $aData)
    If Not IsArray($aData) Then Return
    _GDIPlus_BitmapDispose($aData[2])
    $aData[1] = 0
    $aData = 0
    EndFunc ;==>_DisposePixelData

    [/autoit]


    Hier derselbe Algo, allerdings in Assembler:

    Spoiler anzeigen
    Spoiler anzeigen
    [autoit]

    #include <GDIPlus.au3>

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

    Global $sPath = FileOpenDialog("open image", "", "(*.jpg;*.bmp;*.png;*.tif;*.gif)")
    If @error Or Not FileExists($sPath) Then Exit

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

    _GDIPlus_Startup()

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

    Global $hImage = _GDIPlus_ImageLoadFromFile($sPath)
    Global $aData = _CreatePixelData($hImage)
    _GDIPlus_ImageDispose($hImage)

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

    Global $hDll = DllOpen(@ScriptDir & "\GreyScale.dll")
    Global $iTimer = TimerInit()
    DllCall($hDll, "none", "_GreyScale", "ptr", $aData[0], "int", $aData[3] * $aData[4])
    Global $iTime = TimerDiff($iTimer)
    ConsoleWrite(@error & " " & @extended & @CRLF)

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

    _GDIPlus_ImageSaveToFile($aData[2], @ScriptDir & "\GreyScale.bmp")

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

    _DisposePixelData($aData)
    _GDIPlus_Shutdown()
    DllClose($hDll)

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

    MsgBox(0, "Fertig", "GreyScale fertig in : " & Round($iTime, 3) & "ms")
    ShellExecute(@ScriptDir & "\GreyScale.bmp")

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

    Func _CreatePixelData($hImage)
    Local $iImgW = _GDIPlus_ImageGetWidth($hImage)
    Local $iImgH = _GDIPlus_ImageGetHeight($hImage)

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

    Local $tPixelData = DllStructCreate("uint[" & $iImgW * $iImgH & "];")

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

    Local $aResult = DllCall($ghGDIPDll, "uint", "GdipCreateBitmapFromScan0", "int", $iImgW, "int", $iImgH, "int", $iImgW * 4, "int", 0x0026200A, "ptr", DllStructGetPtr($tPixelData), "int*", 0)
    If @error Then Return SetError(1, 1, False)
    Local $hBitmap = $aResult[6]

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

    Local $hContext = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    _GDIPlus_GraphicsDrawImageRect($hContext, $hImage, 0, 0, $iImgW, $iImgH)
    _GDIPlus_GraphicsDispose($hContext)

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

    Local $aReturn[5]
    $aReturn[0] = DllStructGetPtr($tPixelData)
    $aReturn[1] = $tPixelData
    $aReturn[2] = $hBitmap
    $aReturn[3] = $iImgW
    $aReturn[4] = $iImgH

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

    Return $aReturn
    EndFunc ;==>_CreatePixelData

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

    Func _DisposePixelData(ByRef $aData)
    If Not IsArray($aData) Then Return
    _GDIPlus_BitmapDispose($aData[2])
    $aData[1] = 0
    $aData = 0
    EndFunc ;==>_DisposePixelData

    [/autoit]


    lg
    E

    • Offizieller Beitrag

    Prima Sache, ist gebookmarked. 8o
    Nun brauch ich mich nicht mehr mit C++ quälen. Das Prozedere ist hier doch wesentlich einfacher.

    EDIT
    Also das geht ja wirklich super!
    Dank eukalyptus als Tutor habe ich nun meine erste DLL erstellt.
    - Damit wird geprüft ob ein Punkt (absolute Koordinate) innerhalb eines RECT (relative Koordinate auf GUI) auf einer GUI liegt, die GUI muß dabei aktiv sein.
    - Statt der Punkt-Koordinaten kann "-1" übergeben werden - dann wird die aktuelle Cursor-Position verwendet.

    Dll-Code
    Verwendung in AutoIt
    [autoit]

    $hDll = DllOpen("PFAD_zur_DLL")

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

    $gui = GUICreate('Test')
    GUICtrlCreateLabel('', 25, 20, 250, 200)
    GUICtrlSetBkColor(-1, 0x006400)
    GUISetState()

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

    While 1
    Switch GUIGetMsg()
    Case -3
    DllClose($hDll)
    Exit
    Case $GUI_EVENT_PRIMARYDOWN
    ;~ $aMouse = MouseGetPos()
    ;~ $ret = DllCall($hDll, 'int', '_PtInRectRelative', 'hwnd', $gui, 'int', $aMouse[0], 'int', $aMouse[1], 'int', 25, 'int', 20, 'int', 250, 'int', 200)
    $ret = DllCall($hDll, 'int', '_PtInRectRelative', 'hwnd', $gui, 'int', -1, 'int', -1, 'int', 25, 'int', 20, 'int', 250, 'int', 200)
    ConsoleWrite($ret[0] & @CRLF)
    EndSwitch
    WEnd

    [/autoit]


    Für reale Controls, wie im Bsp. das Label, gibt es auch andere Möglicgkeiten für diesen Check. Aber wenn man gezeichnete Flächen prüfen will ist diese Variante optimal.

  • Folgendes:


    Ich habe die Codes 1 zu 1 übernommen.


    Den FreeBASIC Code hab ich in den Editor reinkopiert und dann F5 gedrückt. Genau wie es dort steht.
    Dann habe ich den AutoIt Code ebenfalls Kopiert und eingefügt.


    Auch F5 gedrückt, aber es gab eine Fehlermeldung aus.



    Ich habe beziehe mich auf die ersten Beiden Codes im Tutorial.





    Muss ich im FreeBASIC Editor noch irgendwas umstellen? Oder warum geht das nicht :o
    --> Ich bekomm da immer eine .exe raus und keine .dll ^^

    Ach, schon gut ^^
    Am besten downloade ich mir mal die richtige IDE ...

    Einmal editiert, zuletzt von Yjuq (20. August 2012 um 17:04)

  • Sieht schon mal gut aus, auch, dass Freebasic recht einfach zu schreiben ist ( soweit ich mir das angeguckt habe ), doch ich krieg das nicht hin. Selbst deine Beispiele gehen nicht :(

    Code
    [PFAD] (3) : ==> Subscript used with non-Array variable.:
    ConsoleWrite("Ergebnis = " & $aResult[0] & @CRLF)
    ConsoleWrite("Ergebnis = " & $aResult^ ERROR

    Das kommt bei DEINEM Add Beispiel Raus ( hab auch ein eigenes mal gemacht, das ging auch nicht )

    Woran liegt das? Geht das nur mit der neusten AutoIt Version? Oder nicht unter Win7?

    mfg
    Hauke

    • Offizieller Beitrag

    Das kommt bei DEINEM Add Beispiel Raus ( hab auch ein eigenes mal gemacht, das ging auch nicht )

    Woran liegt das? Geht das nur mit der neusten AutoIt Version? Oder nicht unter Win7?


    WAS hast du denn genau gemacht? Ich habe unter Win 7 die Dll's erstellt - funktioniert tadellos.
    Schau z.B. meinen editierten ersten Post hier an - dort habe ich ein eigenes Bsp. erstellt.

  • Eben. Ich hab mir die Beispiele von eukalyptus runtergeladen und - als Beispiel - Add.au3 ausgeführt und da krieg ich halt den oben genannten Error. FreeBasic hab ich auch installiert ( neuste Version ).

    Wenn ich eine eigene DLL nach der Anleitung im 1.Post baue, dann krieg ich auch einen Error.
    Hab mal geguckt wo das seinen Ursprung hat:

    [autoit]

    $hDll = DllOpen("Add.dll") ; $hDll ist -1 (!!)
    $aResult = DllCall($hDll, "int", "_Add", "int", 1234, "int", 1234) ; $aResult ist kein Array und hat den Wert 0
    ConsoleWrite("Ergebnis = " & $aResult[0] & @CRLF) ; ==> ERROR

    [/autoit]

    mfg
    Hauke

  • Moin,

    Vor geraumer Zeit habe ich mir schonmal FreeBasic angesehen und es wieder verworfen, weil ich keinen Anschluss gefunden habe.
    Mal schauen ob das jetzt gelingt.

    So wie es aussieht ist die Anbindung an AutoIt sehr einfach.

    Zum "Use64=N"
    Kann man auch 64Bit Dlls erstellen ?
    (hat das überhaupt einen Geschwindigkeitsvorteil, wenn man z.B. sowieso nur mit "kleinen" Zahlen hantiert ?)

    lg
    M

  • Hi,

    Zitat

    Zum "Use64=N"
    Kann man auch 64Bit Dlls erstellen ?
    (hat das überhaupt einen Geschwindigkeitsvorteil, wenn man z.B. sowieso nur mit "kleinen" Zahlen hantiert ?)

    Nein, jedenfalls keinen spürbarern Geschwindigkeitsvorteil. Den bekommt man erst, wenn man explizit 64-Bitbefehle verwendet .

    Btw. die zzt. im Forum aktuelle "Fraktal"-Geschichte schreit doch geradezu nach der Überführung in eine FB-DLL!
    Bitmap erstellen, Pointer auf die Bitmap, Höhe und Breite und einige Parameter übergeben und die 5 Zeilen Basic-Code in FreeBasic erledigen...Hau rein :thumbup:

  • Andy: hehe

    Der Erste Schritt in FreeBasic ist getan :)
    Vermutlich extrem verbesserungsbedürftig, aber es funktioniert.
    (ASM um in die Bitmap zu schreiben in einer Schleife = Armutszeugnis :D )

    Spoiler anzeigen
    [autoit]

    ; Hopalong Fraktal

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

    #include <WinAPI.au3>
    #include <Misc.au3>
    #include <Array.au3>

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

    Opt('GUIOnEventMode', 1)

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

    ; Einstellungen:
    Global $a = Round(Random(-10, 10),2)
    Global $b = Round(Random(-10, 10),2)
    Global $c = Round(Random(-10, 10),2)

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

    ; Weiteres
    Global $n = 1250000
    Global $s = 20000
    Global Const $iW = 512
    Global Const $iH = 512

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

    ; Globale Variablen
    Global $hGUI, $hDC_GUI, $vIMG, $hDLL_GDI32, $hDLL_MARS, $hDC_BUF, $vSTR, $aSLI[4], $hLAB, $hBTN[3]

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

    ; Programmstart
    $hDLL_GDI32 = DllOpen('GDI32.dll')
    $hDLL_MARS = DllOpen('MARS.dll')
    $hGUI = GUICreate('Hopalong Fraktal', $iW + 185, $iH)
    $hDC_GUI = _WinAPI_GetDC($hGUI)
    $vIMG = _Image_Create($iW, $iH)
    $hDC_BUF = DllStructGetData($vIMG, 1, 1)
    $vSTR = DllStructCreate('double x; double y; double xx; double yy')
    GUICtrlCreateLabel('a b c n', $iW + 25, 5)
    $hLAB = GUICtrlCreateLabel('a = ' & $a & @CRLF & 'b = ' & $b & @CRLF &'c = ' & $c & @CRLF &'n = ' & $n, $iW + 15, 275, 120, 75)
    GUICtrlSetFont(-1, 12, 400, 0, 'Arial', 5)
    $hBTN[0] = GUICtrlCreateButton('Zufall', $iW + 15, 360, 155, 30)
    GUICtrlSetFont(-1, 12, 400, 0, 'Arial', 5)
    GUICtrlSetOnEvent(-1, 'Event')

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

    For $i = 0 To 3 Step 1
    $aSLI[$i] = GUICtrlCreateSlider($iW + 20+ 40*$i, 20, 40, 250, 2+0x10)
    GUICtrlSetLimit(-1, 1000, -1000)
    GUICtrlSetOnEvent(-1, 'Event')
    Next
    GUICtrlSetLimit(-1, 500, 1)
    _SetRnd()

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

    GUISetOnEvent(-3, '_Exit', $hGUI)
    GUIRegisterMsg(0xF, 'WM_PAINT')
    OnAutoItExitRegister('_Freigeben')
    GUISetState(@SW_SHOW, $hGUI)

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

    _Draw()

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

    While Sleep(1000)
    WEnd

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

    Func Event()
    Switch @GUI_CtrlId
    Case $hBTN[0]
    _SetRnd()
    EndSwitch
    _Draw()
    EndFunc

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

    Func _SetRnd()
    GUICtrlSetData($aSLI[0], Round(Random(-10, 10),2)*100)
    GUICtrlSetData($aSLI[1], Round(Random(-10, 10),2)*100)
    GUICtrlSetData($aSLI[2], Round(Random(-10, 10),2)*100)
    GUICtrlSetData($aSLI[3], Random(1,500,1))
    EndFunc

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

    Func _Draw()
    $a = GUICtrlRead($aSLI[0])/100
    $b = GUICtrlRead($aSLI[1])/100
    $c = GUICtrlRead($aSLI[2])/100
    $n = GUICtrlRead($aSLI[3])*2500
    GUICtrlSetData($hLAB, 'a = ' & $a & @CRLF & 'b = ' & $b & @CRLF &'c = ' & $c & @CRLF &'n = ' & $n)
    _WinAPI_BitBlt($hDC_BUF, 0, 0, $iW, $iH, 0, 0, 0, 0x42)
    DllCall($hDLL_MARS, 'none', 'Hopalong', 'double', $a, 'double', $b, 'double', $c, 'int', 0, 'int', DllStructGetData($vIMG, 1, 4), 'int', $iW, 'int', $iH, 'int', $n, 'ptr', DllStructGetPtr($vSTR))
    WM_PAINT()
    EndFunc

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

    Func _Freigeben()
    _WinAPI_ReleaseDC($hGUI, $hDC_GUI)
    _Image_Delete($vIMG)
    DllClose($hDLL_GDI32)
    DllClose($hDLL_MARS)
    EndFunc ;==>_Freigeben

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

    Func _Exit()
    Exit
    EndFunc ;==>_Exit

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

    Func _FPS($s)
    Static $z = TimerInit(), $y
    Local $x = TimerDiff($z), $w = (1000 / $s - $x)
    $y += $w
    If $y < 0 Then $y = 0
    If $w < 0 Then $w = 0
    Sleep(Int($y / 10) * 10)
    $y -= Int($y / 10) * 10
    $z = TimerInit()
    Return $x / ($x + $w)
    EndFunc ;==>_FPS

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

    Func WM_PAINT()
    Local Static $iFPS, $iFPS_Timer = TimerInit()
    If TimerDiff($iFPS_Timer) > 1000 Then
    WinSetTitle($hGUI, '', 'Lava-Fraktal: ' & $iFPS & ' FPS')
    $iFPS = 0
    $iFPS_Timer = TimerInit()
    EndIf
    _WinAPI_BitBlt($hDC_GUI, 0, 0, $iW, $iH, $hDC_BUF, 0, 0, 0xCC0020)
    $iFPS += 1
    EndFunc ;==>WM_PAINT

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

    Func _Image_Create($iW, $iH)
    Local $Ptr, $hDC, $hBmp, $tBMI, $aDIB, $vStruct
    $hDC = _WinAPI_CreateCompatibleDC(0)
    $tBMI = DllStructCreate($tagBITMAPINFO)
    DllStructSetData($tBMI, "Size", DllStructGetSize($tBMI) - 4)
    DllStructSetData($tBMI, "Width", $iW)
    DllStructSetData($tBMI, "Height", -$iH)
    DllStructSetData($tBMI, "Planes", 1)
    DllStructSetData($tBMI, "BitCount", 32)
    $aDIB = DllCall($hDLL_GDI32, 'ptr', 'CreateDIBSection', 'hwnd', 0, 'ptr', DllStructGetPtr($tBMI), 'uint', 0, 'ptr*', 0, 'ptr', 0, 'uint', 0)
    $hBmp = $aDIB[0]
    $Ptr = $aDIB[4]
    _WinAPI_SelectObject($hDC, $hBmp)
    $vStruct = DllStructCreate('int[5]')
    DllStructSetData($vStruct, 1, $hDC, 1)
    DllStructSetData($vStruct, 1, $iW, 2)
    DllStructSetData($vStruct, 1, $iH, 3)
    DllStructSetData($vStruct, 1, $Ptr, 4)
    DllStructSetData($vStruct, 1, $hBmp, 5)
    Return $vStruct
    EndFunc ;==>_Image_Create

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

    Func _Image_Delete(ByRef $vStruct)
    _WinAPI_DeleteObject(DllStructGetData($vStruct, 1, 5))
    _WinAPI_DeleteDC(DllStructGetData($vStruct, 1, 1))
    $vStruct = 0
    EndFunc ;==>_Image_Delete

    [/autoit]

    Bei mir wird die dll leider als Virus "erkannt" (Antivir). Hab deshalb das Virenprogramm abgeschaltet, um nicht andauernd genervt zu werden.
    .
    .

  • Hi,
    so manchmal hauts mich ja echt weg hier :rofl::rofl::rofl::rofl:
    "Richtige" Programmiersprachen haben eine Vorzeichen-Funktion

  • Ich habe inzwischen die halbe Referenz drauf.
    Interessant finde ich vor allem die typischen Dos Befehle.
    Sceen, Color, Cls usw. Alles sachen die mir mein Vater beibringen wollte als ich in die Grundschule ging :D
    Da fühlt man sich gleich wohl :)

    Und Goto. Mein Lieblingsbefehl 8)
    Wenn es das in AutoIt gäbe bräuchte man keinen Obfuscator mehr^^

    Vllt könnte man statt einen AutoIt -> C++ (oä) einen AutoIt -> FB Übersetzer bauen.
    Es erscheint mir wesentlich toleranter als C++ (wo eine Zeile Grundschulmathematik 50 Zeilen Errors verursachen kann^^),
    dabei aber ähnlich Umfangreich. Und die Geschwindigkeit ist auch sehr hoch (was man am drittklassig programmierten und trotzdem schnellen FB von mir sehen kann 8))

    • Offizieller Beitrag

    FreeBasic läßt sich auch rudimentär in SciTE einbinden. (Autovervollständigung, Befehlsliste etc. sind hier noch nicht dabei - mache ich evtl. später mal) Man muß etwas umbauen aber das ist nicht so wild:

    Basierend auf der beschriebenen Installation von FreeBasic und FbEdit und den empfohlenen Hilfe-Dateien habe ich jetzt mal die Integration in SciTE erweitert. Alle API's sind erfasst und somit funktioniert auch die Autovervollständigung.

    Folgende Kommentare beseitigen (# am Zeilenanfang entfernen)
    In der Datei "..\AutoIt3\SciTE\SciTEGlobal.properties"

    ca. Zeile 520:

    Code
    menu.language=\
    FreeBasic|bas||\


    ca. Zeile 615:

    Code
    import properties\freebasic

    Ersetzt die Datei "..\AutoIt3\SciTE\properties\freebasic.properties" mit der folgenden Version und speichert die Run_FB.au3 u. Help_FB.au3 ab (Pfade in #3 und #4 anpassen). Die Help_FB.au3 ermöglicht die gewohnte Kontext-sensitive Hilfe (Cursor auf Befehl - F1 - zugehöriger Part wird in Hilfedatei geöffnet).

    freebasic.properties


    Die Pfade im Bereich #Pathes (path.programs, Run_FB.au3 u. Help_FB.au3) ggf. anpassen.

    "Run" kann nur ausgeführt werden, wenn vorher das Skript kompiliert wurde. (Ihr erhaltet eine Fehlermeldung, wenn kein kompiliertes Skript vorliegt.)

    Um Code zu testen macht es sich ganz gut, diesen als Konsolenanwendung zu erstellen und Testwerte mit "Print" auszugeben. Aber auf jeden Fall am Ende ein "Sleep" ohne weitere Parameter setzen. Dann bleibt die Konsole bis zum Betätigen einer Taste geöffnet und somit kann man auch die Ausgaben lesen. Dran denken: Nach jeder Änderung erst kompilieren, dann ausführen.
    Vermutlich läßt sich auch die Ausgabe in die SciTE-Konsole übergeben, aber das habe ich noch nicht probiert und da es so funktioniert sehe ich das auch nicht als essentiell an. ;)

  • Bin grade an einer Dll am basteln (Überraschung^^)

    Wenn ich in der Dll per Print etwas ausgebe erscheint das automatisch in SciTE in der Konsole.
    Das ist super genial ! :D

    • Offizieller Beitrag

    Wenn ich in der Dll per Print etwas ausgebe erscheint das automatisch in SciTE in der Konsole.


    Ja, weil du die Dll im AutoIt-Skript aufrufst und die Ausgaben der Dll somit in der SciTE-Konsole aufgefangen werden. ;)
    Das ist natürlich sehr brauchhbar um Fehler zu suchen. :thumbup: