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

Beiträge von eukalyptus

  • BugFix hat Geburtstag.

    • eukalyptus
    • 29. November 2012 um 09:25

    Alles Gute, Bugfix! :party:

  • Der_Doc hat Geburtstag.

    • eukalyptus
    • 29. November 2012 um 08:47

    Doc, Doc!
    Wer ist da?
    Der Geburtstagsglückwunsch! :party:

  • GDI+ Countdown

    • eukalyptus
    • 24. November 2012 um 06:39

    Ich hab dein Script etwas verändert:

    Spoiler anzeigen
    [autoit]

    #include <GDIPlus.au3>
    #include <Date.au3>
    #include <GUIConstantsEx.au3>
    #include <WindowsConstants.au3>

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

    Opt('MustDeclareVars', 1)
    Opt('GUIOnEventMode', 1)

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

    _GDIPlus_Startup()

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

    Global $iWidth = 500
    Global $iHeight = 140

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

    Global $days, $hour, $hour2, $Mins, $secs

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

    Global $iColor_BG = 0xFF008000
    Global $iColor_TextFill = 0xFFFFAA00
    Global $iColor_TextFill2 = 0xFFFF0000
    Global $iColor_TextFill3 = 0xFF0000FF
    Global $iColor_TextFill4 = 0xFF353535
    Global $iColor_TextBorder = 0xFFA00000

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

    Global $hGui = GUICreate("GDI+", $iWidth, $iHeight)
    GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit")
    Global $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGui)
    Global $hBmpBuffer = _GDIPlus_BitmapCreateFromGraphics($iWidth, $iHeight, $hGraphics)
    Global $hGfxBuffer = _GDIPlus_ImageGetGraphicsContext($hBmpBuffer)
    _GDIPlus_GraphicsSetSmoothingMode($hGfxBuffer, 2)
    _GDIPlus_GraphicsClear($hGfxBuffer, $iColor_BG)

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

    Global $hPen = _GDIPlus_PenCreate($iColor_TextBorder, 3)
    DllCall($ghGDIPDll, "uint", "GdipSetPenLineJoin", "hwnd", $hPen, "int", 2)
    Global $hBrush = _GDIPlus_BrushCreateSolid($iColor_TextFill)
    Global $day, $hour, $hour2, $Mins, $secs

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

    GUIRegisterMsg($WM_PAINT, "WM_PAINT")
    GUIRegisterMsg($WM_ERASEBKGND, "WM_ERASEBKGND")

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

    GUISetState()

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

    Global $hMatrix = _GDIPlus_MatrixCreate()
    Global $tLayout = _GDIPlus_RectFCreate(0, 0, 0, 0)
    Global $hFormat = _GDIPlus_StringFormatCreate()
    Global $hFamily = _GDIPlus_FontFamilyCreate("Arial")
    Global $hPath = _CreatePath("88 - 88:88:88")

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

    Global $sText, $sTextOld
    Global $fStep = 0

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

    While 1
    _TicksToTime(_DateDiff('s', _NowCalc(), "2013/01/01 00:00:00") * 1000, $hour, $Mins, $secs)
    If $hour >23 Then
    $days = StringFormat("%02i", $hour / 24); volle Tage
    $hour = $hour - ($days*24); volle Tage abziehen
    Else
    $days = 0
    EndIf
    $sText = StringFormat("%02i - %02i:%02i:%02i", $days, $hour, $Mins, $secs)

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

    If $sText <> $sTextOld Then
    $sTextOld = $sText
    DllCall($ghGDIPDll, "uint", "GdipResetPath", "hwnd", $hPath)
    DllCall($ghGDIPDll, "uint", "GdipAddPathString", "hwnd", $hPath, "wstr", $sText, "int", -1, "hwnd", $hFamily, "int", 1, "float", 100, "ptr", DllStructGetPtr($tLayout), "hwnd", $hFormat)
    DllCall($ghGDIPDll, "uint", "GdipTransformPath", "hwnd", $hPath, "hwnd", $hMatrix)
    EndIf

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

    $fStep += 0.01
    _Draw(Abs(Sin($fStep)))
    Sleep(10)
    WEnd

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

    Func _Draw($fScale)
    _GDIPlus_GraphicsClear($hGfxBuffer, $iColor_BG)

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

    DllCall($ghGDIPDll, "uint", "GdipTranslateWorldTransform", "hwnd", $hGfxBuffer, "float", -$iWidth / 2, "float", -$iHeight / 2, "int", False)
    DllCall($ghGDIPDll, "uint", "GdipScaleWorldTransform", "hwnd", $hGfxBuffer, "float", $fScale, "float", $fScale, "int", True)
    DllCall($ghGDIPDll, "uint", "GdipTranslateWorldTransform", "hwnd", $hGfxBuffer, "float", $iWidth / 2, "float", $iHeight / 2, "int", True)

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

    DllCall($ghGDIPDll, "uint", "GdipDrawPath", "hwnd", $hGfxBuffer, "hwnd", $hPen, "hwnd", $hPath)
    DllCall($ghGDIPDll, "uint", "GdipFillPath", "hwnd", $hGfxBuffer, "hwnd", $hBrush, "hwnd", $hPath)

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

    DllCall($ghGDIPDll, "uint", "GdipResetWorldTransform", "hwnd", $hGfxBuffer)

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

    _GDIPlus_GraphicsDrawImage($hGraphics, $hBmpBuffer, 0, 0)
    EndFunc ;==>_Draw

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

    Func _CreatePath($sText)

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

    Local $tBounds = _GDIPlus_RectFCreate(0, 0, 0, 0)

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

    Local $aResult = DllCall($ghGDIPDll, "uint", "GdipCreatePath", "int", 0, "int*", 0)
    If @error Or Not IsArray($aResult) Then Return SetError(1, 1, False)
    Local $hPath = $aResult[2]

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

    DllCall($ghGDIPDll, "uint", "GdipAddPathString", "hwnd", $hPath, "wstr", $sText, "int", -1, "hwnd", $hFamily, "int", 1, "float", 100, "ptr", DllStructGetPtr($tLayout), "hwnd", $hFormat)
    DllCall($ghGDIPDll, "uint", "GdipGetPathWorldBounds", "hwnd", $hPath, "ptr", DllStructGetPtr($tBounds), "hwnd", 0, "hwnd", 0)

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

    _GDIPlus_MatrixTranslate($hMatrix, -DllStructGetData($tBounds, "X"), -DllStructGetData($tBounds, "Y"))
    _GDIPlus_MatrixScale($hMatrix, $iWidth / DllStructGetData($tBounds, "Width"), $iHeight / DllStructGetData($tBounds, "Height"), True)
    DllCall($ghGDIPDll, "uint", "GdipTransformPath", "hwnd", $hPath, "hwnd", $hMatrix)

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

    Return $hPath
    EndFunc ;==>_CreatePath

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

    Func WM_PAINT($hWnd, $uMsgm, $wParam, $lParam)
    _GDIPlus_GraphicsDrawImage($hGraphics, $hBmpBuffer, 0, 0)
    Return $GUI_RUNDEFMSG
    EndFunc ;==>WM_PAINT

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

    Func WM_ERASEBKGND($hWnd, $uMsgm, $wParam, $lParam)
    _GDIPlus_GraphicsDrawImage($hGraphics, $hBmpBuffer, 0, 0)
    Return True
    EndFunc ;==>WM_ERASEBKGND

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

    Func _Exit()
    _GDIPlus_FontFamilyDispose($hFamily)
    _GDIPlus_StringFormatDispose($hFormat)
    DllCall($ghGDIPDll, "uint", "GdipDeletePath", "hwnd", $hPath)
    _GDIPlus_PenDispose($hPen)
    _GDIPlus_BrushDispose($hBrush)
    _GDIPlus_GraphicsDispose($hGfxBuffer)
    _GDIPlus_BitmapDispose($hBmpBuffer)
    _GDIPlus_GraphicsDispose($hGraphics)
    _GDIPlus_Shutdown()
    Exit
    EndFunc

    [/autoit]

    Und zwar hab ich folgende Unschönheiten beseitigt:
    .) Du erstellst bei jedem Schleifendurchgang einen neuen Pfad, ohne dass du diesen wieder aus dem Speicher freigibst.
    entweder immer wieder freigeben (GdipDeletePath), oder wie in meinem Sript nur einmal erstellen und diesen einen Pfad verwenden

    .) Die Matrix, welche die Schrift zentriert, muss nur einmal berechnet werden

    .) Du hast eine Endlosschleife in deiner Update-Funktion und rufst diese trotzdem jede Sekunde neu auf
    Ich hab es so verändert, dass der Text nur dann neu geschrieben wird, wenn dieser sich verändert hat

    .) Du solltest in Zukunft auch diese 2 Dinge berücksichtigen:
    - deklariere niemals innerhalb einer Function eine Variable Global
    - deklariere niemals innerhalb einer Schleife eine Variable, sondern immer davor


    Evtl interessiert dich das noch: einen schönen Effekt ergibt es, wenn du als Hintergrund ein Foto verwendest (_GdiPlus_ImageLoadFromFile) und den Alphakanal von $hBrush auf leicht transparent setzt...

    E

  • Text automatisch vergrößern

    • eukalyptus
    • 21. November 2012 um 12:26

    Ich würde einen Pfad verwenden.
    Damit kann man die Bewegung wirklich smooth machen:
    (Und außerdem die Schrift umranden, was bei DrawString auch nicht geht)

    Spoiler anzeigen
    [autoit]

    #include <GDIPlus.au3>
    #include <GUIConstantsEx.au3>
    #include <WindowsConstants.au3>

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

    Opt('MustDeclareVars', 1)
    Opt('GUIOnEventMode', 1)

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

    _GDIPlus_Startup()

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

    Global $iWidth = 400
    Global $iHeight = 200

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

    Global $hGui = GUICreate("GDI+", $iWidth, $iHeight)
    GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit")
    Global $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGui)
    Global $hBmpBuffer = _GDIPlus_BitmapCreateFromGraphics($iWidth, $iHeight, $hGraphics)
    Global $hGfxBuffer = _GDIPlus_ImageGetGraphicsContext($hBmpBuffer)
    _GDIPlus_GraphicsSetSmoothingMode($hGfxBuffer, 2)
    _GDIPlus_GraphicsClear($hGfxBuffer, 0xFFFFFFFF)

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

    Global $hPen = _GDIPlus_PenCreate(0xFF0000FF, 3)
    Global $hBrush = _GDIPlus_BrushCreateSolid(0xFFFFAA00)

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

    GUIRegisterMsg($WM_PAINT, "WM_PAINT")
    GUIRegisterMsg($WM_ERASEBKGND, "WM_ERASEBKGND")

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

    GUISetState()

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

    Global $hPath = _CreatePath("Text ;)")
    Global $fStep = 0
    While 1
    $fStep += 0.025
    _Draw(Abs(Sin($fStep)))
    Sleep(10)
    WEnd

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

    Func _Draw($fScale)
    _GDIPlus_GraphicsClear($hGfxBuffer, 0xFFFFFFFF)

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

    DllCall($ghGDIPDll, "uint", "GdipTranslateWorldTransform", "hwnd", $hGfxBuffer, "float", -$iWidth / 2, "float", -$iHeight / 2, "int", False)
    DllCall($ghGDIPDll, "uint", "GdipScaleWorldTransform", "hwnd", $hGfxBuffer, "float", $fScale, "float", $fScale, "int", True)
    DllCall($ghGDIPDll, "uint", "GdipTranslateWorldTransform", "hwnd", $hGfxBuffer, "float", $iWidth / 2, "float", $iHeight / 2, "int", True)

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

    DllCall($ghGDIPDll, "uint", "GdipDrawPath", "hwnd", $hGfxBuffer, "hwnd", $hPen, "hwnd", $hPath)
    DllCall($ghGDIPDll, "uint", "GdipFillPath", "hwnd", $hGfxBuffer, "hwnd", $hBrush, "hwnd", $hPath)

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

    DllCall($ghGDIPDll, "uint", "GdipResetWorldTransform", "hwnd", $hGfxBuffer)

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

    _GDIPlus_GraphicsDrawImage($hGraphics, $hBmpBuffer, 0, 0)
    EndFunc ;==>_Draw

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

    Func _CreatePath($sText)
    Local $hFormat = _GDIPlus_StringFormatCreate()
    Local $hFamily = _GDIPlus_FontFamilyCreate("Arial Black")

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

    Local $tLayout = _GDIPlus_RectFCreate(0, 0, 0, 0)
    Local $tBounds = _GDIPlus_RectFCreate(0, 0, 0, 0)

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

    Local $aResult = DllCall($ghGDIPDll, "uint", "GdipCreatePath", "int", 0, "int*", 0)
    If @error Or Not IsArray($aResult) Then Return SetError(1, 1, False)
    Local $hPath = $aResult[2]

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

    DllCall($ghGDIPDll, "uint", "GdipAddPathString", "hwnd", $hPath, "wstr", $sText, "int", -1, "hwnd", $hFamily, "int", 1, "float", 100, "ptr", DllStructGetPtr($tLayout), "hwnd", $hFormat)
    DllCall($ghGDIPDll, "uint", "GdipGetPathWorldBounds", "hwnd", $hPath, "ptr", DllStructGetPtr($tBounds), "hwnd", 0, "hwnd", 0)

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

    Local $hMatrix = _GDIPlus_MatrixCreate()
    _GDIPlus_MatrixTranslate($hMatrix, -DllStructGetData($tBounds, "X"), -DllStructGetData($tBounds, "Y"))
    _GDIPlus_MatrixScale($hMatrix, $iWidth / DllStructGetData($tBounds, "Width"), $iHeight / DllStructGetData($tBounds, "Height"), True)
    DllCall($ghGDIPDll, "uint", "GdipTransformPath", "hwnd", $hPath, "hwnd", $hMatrix)
    _GDIPlus_MatrixDispose($hMatrix)

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

    _GDIPlus_FontFamilyDispose($hFamily)
    _GDIPlus_StringFormatDispose($hFormat)

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

    Return $hPath
    EndFunc ;==>_CreatePath

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

    Func WM_PAINT($hWnd, $uMsgm, $wParam, $lParam)
    _GDIPlus_GraphicsDrawImage($hGraphics, $hBmpBuffer, 0, 0)
    Return $GUI_RUNDEFMSG
    EndFunc ;==>WM_PAINT

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

    Func WM_ERASEBKGND($hWnd, $uMsgm, $wParam, $lParam)
    _GDIPlus_GraphicsDrawImage($hGraphics, $hBmpBuffer, 0, 0)
    Return True
    EndFunc ;==>WM_ERASEBKGND

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

    Func _Exit()
    DllCall($ghGDIPDll, "uint", "GdipDeletePath", "hwnd", $hPath)
    _GDIPlus_PenDispose($hPen)
    _GDIPlus_BrushDispose($hBrush)
    _GDIPlus_GraphicsDispose($hGfxBuffer)
    _GDIPlus_BitmapDispose($hBmpBuffer)
    _GDIPlus_GraphicsDispose($hGraphics)
    _GDIPlus_Shutdown()
    Exit
    EndFunc ;==>_Exit

    [/autoit]

    Um die Schrift zu zoomen, verändere ich hier den Graphicscontext.
    Man kann jedoch auch den Pfad selber zoomen (bzw. auch den Backbuffer).
    Welche Variante man wählt, hängt vom gewünschten Ergebnis ab

    E

  • eintrag beim "rechtsklickmenü" von datein hinzufügen

    • eukalyptus
    • 21. November 2012 um 11:49

    Um den Eintrag für alle Dateien zum erstellen, reicht diese Zeile:

    [autoit]

    RegWrite("HKEY_CLASSES_ROOT\*\shell\TestAutoItScript\command","","REG_SZ",'"' & @ScriptDir & "\Script.exe" & '" "%1"')

    [/autoit]

    Ein Problem gibt es, wenn man mehrere Dateien auf einmal selektiert hat - dann wird für jede Datei eine eigene Instanz der Exe gestartet.
    Wenn man das nicht will, dann hab ich hier eine Lösung: Prog übergibt Parameter an seine 1 Instanz (mehrere Dateien via Kontext-Menü)

    E

  • Seltsamer DllCallback/DllCall Error

    • eukalyptus
    • 21. November 2012 um 11:18

    Wenn man das Script etwas verändert, dann gibt es unter XP auch manchmal diese seltsamen Abstürze:

    Spoiler anzeigen
    [autoit]

    Global Const $WT_EXECUTEDEFAULT = 0x00000000
    Global Const $WT_EXECUTEINIOTHREAD = 0x00000001
    Global Const $WT_EXECUTEINTIMERTHREAD = 0x00000020
    Global Const $WT_EXECUTEINPERSISTENTTHREAD = 0x00000080
    Global Const $WT_EXECUTELONGFUNCTION = 0x00000010
    Global Const $WT_EXECUTEONLYONCE = 0x00000008
    Global Const $WT_TRANSFER_IMPERSONATION = 0x00000100

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

    $hDll_Kernel32 = DllOpen("kernel32.dll")

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

    $hCallBack = DllCallbackRegister("_Callback", "NONE", "LPARAM;INT")
    $hTimer = _CreateTimerQueueTimer($hCallBack, 12345, 200, 200, Default, Default, $hDll_Kernel32)

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

    ConsoleWrite("Before Callback" & @CRLF)
    $iCnt = 0
    For $i = 1 To 2000
    $iCnt += 1
    _Print($iCnt)
    Sleep(10)
    Next

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

    ConsoleWrite("Deleting: " & _DeleteTimerQueueTimer($hTimer, 0, 0, $hDll_Kernel32) & @CRLF)

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

    Sleep(1000)

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

    ConsoleWrite("After Callback" & @CRLF)
    DllClose($hDll_Kernel32)
    DllCallbackFree($hCallBack)

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

    Func _Callback($lParam, $TimerOrWaitFired)
    ConsoleWrite("Callback Parameter: " & $lParam & @CRLF)
    EndFunc ;==>_Callback

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

    Func _CreateTimerQueueTimer($hTimer_Callback, $iParameter, $iDueTime, $iPeriod = 0, $iFlags = $WT_EXECUTEDEFAULT, $hTimerQueue = 0, $hDll_Kernel32 = "kernel32.dll")
    Local $thTimerHandle = DllStructCreate("HANDLE")
    Local $aRes = DllCall($hDll_Kernel32, "BOOL", "CreateTimerQueueTimer", "PTR", DllStructGetPtr($thTimerHandle), "HANDLE", 0, "PTR", DllCallbackGetPtr($hTimer_Callback), "INT", $iParameter, "DWORD", $iDueTime, "DWORD", $iPeriod, "ULONG", $iFlags)
    If @error Then Return SetError(@error, @extended, 0)
    If Not $aRes[0] Then Return SetError(2, 0, 0)
    Return DllStructGetData($thTimerHandle, 1)
    EndFunc ;==>_CreateTimerQueueTimer

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

    Func _DeleteTimerQueueTimer($hTimer, $hCompletionEvent = 0, $hTimerQueue = 0, $hDll_Kernel32 = "kernel32.dll")
    Local $aRes = DllCall($hDll_Kernel32, "BOOL", "DeleteTimerQueueTimer", "HANDLE", $hTimerQueue, "HANDLE", $hTimer, "HANDLE", $hCompletionEvent)
    If @error Then Return SetError(@error, @extended, 0)
    Return $aRes[0]
    EndFunc ;==>_DeleteTimerQueueTimer

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

    Func _Print($sText)
    Local $sPrint = "! "
    $sPrint = $sPrint & $sText & @CRLF
    ConsoleWrite($sPrint)
    EndFunc ;==>_Print

    [/autoit]

    Dieses Verhalten ist mir schon lange bekannt, weshalb ich bei meinen Scripten die CallBackfunktionen immer in eine Dll "auslagere" (z.B.: Bass UDF)
    Es scheint, als würde die Callbackfunktion zu einem ungünstigen Zeitpunkt aufgerufen und AutoIt damit auf dem falschen Fuß erwischt werden...
    Wo genau das Problem liegt, kann ich aber nicht sagen.

    Zum experimentieren hab ich hier noch ein Script: Der Inhalt kann nicht angezeigt werden, da er nicht mehr verfügbar ist.
    Manchmal stimmt auch der Rückgabewert an die Dll nicht!

    E

    Dateien

    CallBackTest.zip 13,12 kB – 387 Downloads
  • Alles Gute! progandy wird 22!

    • eukalyptus
    • 11. Oktober 2012 um 07:17

    Alles Gute!

    Danke für deine großartige Arbeit! :rock:

  • FreeBASIC DLL Rückgabe String

    • eukalyptus
    • 4. Oktober 2012 um 21:14
    Zitat von progandy

    Wenn du in FreeBasci ZString Ptr verwendest, dann kannst du in AutoIt als Typ "str" verwenden ohne _GetStringFromPointer.

    Hahaha!
    Das ist wieder mal typisch für mich 8o

    Hier also die einfache Lösung :thumbup: :

    Code
    Extern "Windows-MS"
    
    
    Function Text()As ZString Ptr Export
    	Return @"Text"
    End Function
    
    
    End Extern
    [autoit]

    $hDll = DllOpen("Test.dll")

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

    $aResult = DllCall($hDll, "str", "Text")
    MsgBox(0, "", $aResult[0])

    [/autoit]
  • FreeBASIC DLL Rückgabe String

    • eukalyptus
    • 4. Oktober 2012 um 19:11

    Ich mach das meistens so:

    Code
    Extern "Windows-MS"
    
    
    Function Text(zText As ZString Ptr)As UInteger Export
        *zText = "Text"
        Return Len(*zText)
    End Function
    
    
    End Extern
    [autoit]

    $hDll = DllOpen("Test.dll")
    $tText = DllStructCreate("char[256];")
    $aResult = DllCall($hDll, "uint", "Text", "ptr", DllStructGetPtr($tText))
    MsgBox(0, "", "Text: " & DllStructGetData($tText, 1) & @CRLF & "Len: " & $aResult[0])

    [/autoit]

    E


    Edit: Alternativ hätte ich ncoh diese Lösung anzubieten:

    Code
    Extern "Windows-MS"
    
    
    Function Text()As ZString Ptr Export
    	Return @"Text"
    End Function
    
    
    End Extern
    [autoit]

    $hDll = DllOpen("Test.dll")

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

    $aResult = DllCall($hDll, "ptr", "Text")
    MsgBox(0, "", _GetStringFromPointer($aResult[0]))

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

    Func _GetStringFromPointer($pPtr)
    Local $aResult = DllCall("kernel32.dll", "int", "lstrlen", "ptr", $pPtr)
    If @error Or Not IsArray($aResult) Then Return SetError(1, 1, False)
    Local $iLen = $aResult[0]
    Local $tString = DllStructCreate("char[" & ($iLen + 1) & "];", $pPtr)
    Return DllStructGetData($tString, 1)
    EndFunc

    [/autoit]
  • Deutsche Sprache - Schwere Sprache (?)

    • eukalyptus
    • 20. September 2012 um 07:09
    Zitat von Mars

    Aber es darf nicht dahin laufen, dass einfach das halbe Englische Wörterbuch (teils auch noch Sinnentfremdet) in den Deutschen Duden aufgenommen wird.

    Manchmal gefallen mir die englischen Bezeichnungen aber besser.
    Der beste Hörpunkt in einer 5.1-Anlage heißt im Deutschen Referenzhörpunkt, die englische (und auch im Deutschen verwendete) Bezeichnung lautet Sweetspot.
    Referenzhörpunkt klingt eher wie eine uralte Kohlemikroaufnahme aus den 30ern ;)

    Weiters interessiert sich heute auch keiner mehr, dass z.B.: Kekse ursprünglich aus dem englischen stammen.
    Ahhh, Kekse *sabber*

  • Alles Gute, Gun-Food :)

    • eukalyptus
    • 20. September 2012 um 06:45

    Alles Gute! :party:

  • Dll erstellen und mit AutoIt nutzen - FreeBasic Tutorial

    • eukalyptus
    • 9. September 2012 um 18:05

    Update im ersten Post

    und zwar ein Multithreading-Beispiel für Fortgeschrittene

    Die Sourcecodes und die vorkomilierten Dll´s sind im Anhang in GreyScale.zip

    E

  • Struct via "Struct.Element" ansprechen - Beta 3.3.9.5

    • eukalyptus
    • 9. September 2012 um 11:29

    Beim Experimentieren mit AutoIt Beta 3.3.9.5 hab ich zufällig bemerkt, dass man die einzelnen Elemente einer Struct folgendermaßen ansprechen kann:

    [autoit]

    $tStruct = DllStructCreate("int X;")
    $tStruct.X = 12

    [/autoit]

    Auch der Zugriff auch den SubIndex ist möglich, allerdings nur hardcoded, wie folgendes Beispiel zeigt:

    [autoit]


    $tStruct = DllStructCreate("int X; int Y; int Z; int A[4];")
    $tStruct.X = 12
    $tStruct.Y = 34

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

    $tStruct.X += 1
    $tStruct.Z = $tStruct.X + $tStruct.Y

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

    ConsoleWrite("+ " & $tStruct.X & " + " & $tStruct.Y & " = " & $tStruct.Z & @CRLF)

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

    For $i = 1 To 4
    $tStruct.A($i) = $i ;not working
    ConsoleWrite("! " & DllStructGetData($tStruct, "A", $i) & @CRLF)
    Next

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

    $tStruct.A(1) = 11
    $tStruct.A(2) = 22
    $tStruct.A(3) = 33
    $tStruct.A(4) = 44

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

    For $i = 1 To 4
    ConsoleWrite("+ " & DllStructGetData($tStruct, "A", $i) & @CRLF)
    Next

    [/autoit]

    Das wäre für mich eine der wichtigsten und besten Neuerungen gewesen, die eine neue AutoIt Version mit sich gebracht hätte, aber...
    nun bin ich auf das hier gestossen: http://www.autoitscript.com/trac/autoit/ticket/2220

    Bedeuted das nun, dass ich meine Freude gleich wieder dämpfen kann und dieses Feature etwa doch nicht umgesetzt wird?!

    Weiß jemand mehr?

    E

  • Dll erstellen und mit AutoIt nutzen - FreeBasic Tutorial

    • eukalyptus
    • 7. September 2012 um 17:45

    Das das so funktioniert, hab ich gar nicht gewusst ;)

    Dennoch ist es einfacher ohne ByRef zu arbeiten und in FB die Pointerschreibweise zu benutzen, dann behält man besser den Überblick - zumindest ich

    Code
    Type testtype
        x1 AS DOUBLE
        x2 AS DOUBLE
        x3 AS DOUBLE
        x4 AS DOUBLE
    END Type
    
    
    Extern "Windows-MS"
    
    
    SUB f_inTest(BYVAL y1 AS DOUBLE, BYVAL y2 AS DOUBLE, BYVAL y3 AS DOUBLE, BYVAL y4 AS DOUBLE, ByVal z AS testtype Ptr) Export
        z->x1 = y1 + 1
        z->x2 = y2 + 1
        z->x3 = y3 + 1
        z->x4 = y4 + 1
        'RETURN z
    END Sub 
    
    
    SUB f_Test(ByVal z1 As testtype Ptr, ByVal z2 AS testtype Ptr)   Export
        z2->x1 = z1->x1 - 1
        z2->x2 = z1->x2 - 1
        z2->x3 = z1->x3 - 1
        z2->x4 = z1->x4 - 1
        'RETURN z2
    END Sub 
    
    
    END Extern
    Alles anzeigen
  • Kommentare aus Skriptzeile entfernen

    • eukalyptus
    • 3. September 2012 um 15:02

    Oder via RegExp:

    [autoit]

    StringRegExpReplace($sScript, '(?x)(?:\r?\n?\s*;.*)|' & '((?>"[^"]*")+|' & "(?>'[^']*')+)", "\1")

    [/autoit]

    bzw. um alle Kommentare aus dem kompletten Code zu entfernen:

    [autoit]

    Func _RemoveComments(ByRef $sScript)
    $sScript = StringRegExpReplace($sScript, '(?x)(?:\r?\n?\s*;.*)|' & '((?>"[^"]*")+|' & "(?>'[^']*')+)", "\1") ;entferne ;-Komments
    $sScript = StringRegExpReplace($sScript, '(?i)(?:[\r\n]\s*)(\#ce|\#comments-end)(.*)', '$1') ;manche #ce haben noch Text dahinter
    $sScript = StringRegExpReplace($sScript, '(?x)(?:\r?\n?\s*;.*)|(?s)\r?\n?\s*\#c(?>s|omments-start)(?>(?>"[^"]*")+|' & "(?>'[^']*')+|.)*?\#c(?>e|omments-end)(?-s)|" & '((?>"[^"]*")+|' & "(?>'[^']*')+)", "\1")
    EndFunc ;==>_RemoveComments

    [/autoit]


    :D

  • Extrahiere alle Frames eines animierten GIFs

    • eukalyptus
    • 31. August 2012 um 12:31

    Hier bitte:

    Spoiler anzeigen
    [autoit]

    #include <GDIPlus.au3>

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

    _GDIPlus_Startup()
    Global $hImage = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\Test.gif")
    _ExtractFrames($hImage)
    _GDIPlus_ImageDispose($hImage)
    _GDIPlus_Shutdown()

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

    ShellExecute(@ScriptDir & "\AllFrames.bmp")

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

    Func _ExtractFrames($hImage)
    Local $iImgW = _GDIPlus_ImageGetWidth($hImage)
    Local $iImgH = _GDIPlus_ImageGetHeight($hImage)
    Local $iImgF = _GDIPlus_ImageGetPixelFormat($hImage)

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

    Local $aResult = DllCall($ghGDIPDll, "uint", "GdipImageGetFrameDimensionsCount", "hwnd", $hImage, "uint*", 0)
    If @error Then Return SetError(1, 1, False)
    Local $iDim = $aResult[2]

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

    Local $tDim = DllStructCreate("byte[" & $iDim * 16 & "];")
    $aResult = DllCall($ghGDIPDll, "uint", "GdipImageGetFrameDimensionsList", "hwnd", $hImage, "ptr", DllStructGetPtr($tDim), "int", $iDim)
    If @error Then Return SetError(1, 2, False)

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

    Local $iFramesMax = 0
    For $i = 1 To $iDim
    $aResult = DllCall($ghGDIPDll, "uint", "GdipImageGetFrameCount", "hwnd", $hImage, "ptr", DllStructGetPtr($tDim) + ($i - 1) * 16, "uint*", 0)
    If @error Then Return SetError(1, 2, False)
    If $aResult[3] > $iFramesMax Then $iFramesMax = $aResult[3]
    Next

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

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

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

    Local $iFrames, $hBmpFrame
    For $i = 1 To $iDim
    $aResult = DllCall($ghGDIPDll, "uint", "GdipImageGetFrameCount", "hwnd", $hImage, "ptr", DllStructGetPtr($tDim) + ($i - 1) * 16, "uint*", 0)
    If @error Then Return SetError(1, 2, False)
    $iFrames = $aResult[3]
    For $j = 1 To $iFrames
    DllCall($ghGDIPDll, "uint", "GdipImageSelectActiveFrame", "hwnd", $hImage, "ptr", DllStructGetPtr($tDim) + ($i - 1) * 16, "uint", $j - 1)
    $hBmpFrame = _GDIPlus_BitmapCloneArea($hImage, 0, 0, $iImgW, $iImgH, $iImgF)
    _GDIPlus_ImageSaveToFile($hBmpFrame, @ScriptDir & "\Frame_" & StringFormat("%03s", $i) & "-" & StringFormat("%03s", $j) & ".bmp")

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

    _GDIPlus_GraphicsDrawImageRect($hContext, $hBmpFrame, ($j - 1) * $iImgW, ($i - 1) * $iImgH, $iImgW, $iImgH)

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

    _GDIPlus_BitmapDispose($hBmpFrame)
    Next
    Next

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

    _GDIPlus_GraphicsDispose($hContext)
    _GDIPlus_ImageSaveToFile($hBitmap, @ScriptDir & "\AllFrames.bmp")
    _GDIPlus_BitmapDispose($hBitmap)
    EndFunc ;==>_ExtractFrames

    [/autoit]

    E

  • Text filtern

    • eukalyptus
    • 22. August 2012 um 12:43

    Dafür sind die "|" da - du kannst ganz einfach StringSplit verwenden:

    [autoit]

    $aSplit = StringSplit($aRow[$i], "|")

    [/autoit]

    Schau dir mal die Funktion _Load in meinem Script an ;)

    E

  • Dll erstellen und mit AutoIt nutzen - FreeBasic Tutorial

    • eukalyptus
    • 22. August 2012 um 12:31

    Läuft dein AutoIt Script im 64Bit Modus?
    Probiers mal mit:

    [autoit]

    #AutoIt3Wrapper_UseX64=n

    [/autoit]

    E

  • _GDIPlus_ImageLoadFromFile auch anderes?

    • eukalyptus
    • 22. August 2012 um 02:26

    In dem Beispiel <Rotating Cube 2 + Textures.au3> von UEZ findest du die Funktion Load_BMP_From_Mem:
    GDI+ Rotating Cubes

    E

  • Dll erstellen und mit AutoIt nutzen - FreeBasic Tutorial

    • eukalyptus
    • 20. August 2012 um 12:51

    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:

    Code
    Extern "Windows-MS"
    
    
    Function _ASM_ADD(iX As Integer, iY As Integer)As Integer Export
    	Dim As Integer iZ
    	Asm
    		mov eax, [iX]
    		mov ebx, [iY]
    		Add eax, ebx
    		mov [iZ], eax
    	End Asm
    	Return iZ
    End Function
    
    
    End Extern
    Alles anzeigen


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

    Code
    Type t_CircleData
    	iMX As Integer
    	iMY As Integer
    	aX(0 To 359) As Single
    	aY(0 To 359) As Single
    End Type
    
    
    Public Const Pi = 3.14159265358979
    Public Const Deg2Rad = Pi / 180
    
    
    Extern "Windows-MS"
    
    
    Sub _Circle(iX As Integer, iY As Integer, iR As Integer, tCirlce As t_CircleData Ptr) Export
    	Dim As Single fRad
    
    	For i As UInteger = 0 To 359
    		fRad = i * Deg2Rad
    		tCirlce->aX(i) = Cos(fRad) * iR + iX
    		tCirlce->aY(i) = Sin(fRad) * iR + iY
    	Next
    
    	tCirlce->iMX = iX
    	tCirlce->iMY = iY
    End Sub
    
    
    End Extern
    Alles anzeigen


    [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
    Code
    Type t_Param
    	pPixelData As UInteger Ptr
    	iPixelCnt As Integer
    End Type
    
    
    
    
    Sub _GreyScaleFunc(pParam As t_Param Ptr)
    	Dim As UByte Ptr pARGB
    	Dim As UByte iLuma
    
    	For i As UInteger = 0 To pParam->iPixelCnt -1
    		pARGB = @pParam->pPixelData[i]
    
    		'Luma = BlauAnteil * 0.11 + GrünAnteil * 0.59 + RotAnteil * 0.3 
    		iLuma = (pARGB[0] * 0.11) + (pARGB[1] * 0.59) + (pARGB[2] * 0.3) 
    
    		pARGB[0] = iLuma
    		pARGB[1] = iLuma
    		pARGB[2] = iLuma
    	Next
    
    End Sub
    
    
    
    
    Extern "Windows-MS"
    
    
    Sub _GreyScale(pPixelData As UInteger Ptr, iPixelCnt As Integer) Export
    	Dim As t_Param tParam(0 To 3)
    	Dim As Integer iPixel_4 = iPixelCnt / 4
    
    	'Einer Threadfunktion kann man nur einen Pointer übergeben, deshalb erstellen wir 4 Variablen vom Typ t_Param und befüllen diese mit den entsprechenden Werten
    	For i As UInteger = 0 To 3
    		tParam(i).pPixelData = pPixelData + (iPixel_4 * i) ' Startposition des ersten zu berechnenden Pixels
    		tParam(i).iPixelCnt = iPixel_4 ' Anzahl der Pixel pro Thread
    	Next
    
    	Dim As Any Ptr pThread(0 To 3)
    	For i As Integer = 0 To 3
    		If i = 2 Then Continue For ' zu Testzwecken: 3 Thread überspringen
    		pThread(i) = ThreadCreate(@_GreyScaleFunc, @tParam(i)) 'starte Threads
    	Next
    
    	For i As Integer = 0 To 3 
    		ThreadWait(pThread(i)) 'warten bis alle Threads fertig
    	Next
    
    End Sub
    
    
    End Extern
    Alles 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
    Code
    Sub ASM_GREYSCALE(iAddr As UInteger, iPixels As UInteger)
    
    	Dim As UInteger iCnt, iMod
    	iMod = iPixels Mod 4
    	iCnt = iPixels - iMod
    
    	Asm
    		jmp .GS_Start
    
    		.align 16
    		_GS_11: .float 0.11, 0.11, 0.11, 0.11
    		_GS_59: .float 0.59, 0.59, 0.59, 0.59
    		_GS_3: .float 0.3, 0.3, 0.3, 0.3
    		_GS_Blue: .long 255, 255, 255, 255
    
    		.GS_Start:
    			mov edi,dword[iAddr]             'Startadress Bitmapdata (Pixel)
    			mov ecx,dword[iCnt]           	'number of Pixel
    
    			movaps xmm7, [_GS_11]
    			movaps xmm6, [_GS_59]
    			movaps xmm5, [_GS_3]
    			movaps xmm4, [_GS_Blue]
    
       		.align 16
    			.GS_Loop:											'until ecx=0
    
    				movdqu xmm0,[edi]								'load 4 pixels to xmm0
    				movdqa xmm3, xmm0								'Pixels to xmm3
    				Pand xmm3, xmm4								'And 000000FF
    				cvtdq2ps xmm3, xmm3							'Int To Float
    
    				movdqa xmm2, xmm0								'Pixels to xmm2
    				PSRLD xmm2, 8									'Green
    				Pand xmm2, xmm4								'And 000000FF
    				cvtdq2ps xmm2, xmm2							'Int To Float
    
    				movdqa xmm1, xmm0								'Pixels to xmm1
    				PSRLD xmm1, 16									'Red
    				Pand xmm1, xmm4								'And 000000FF
    				cvtdq2ps xmm1, xmm1							'Int To Float
    
    				PSRLD xmm0, 24									'Alpha
    				'Pand xmm0, xmm4								'And 000000FF
    				PSLLD xmm0, 24									'Alpha
    
    				'7=0.11 6=0.59 5=0.3 4=BlueMask 3=Blue 2=Green 1=Red 0=Alpha
    				mulps xmm3, xmm5								'Blue * 0.11
    				mulps xmm2, xmm6								'Green * 0.59
    				mulps xmm1, xmm7								'Red * 0.3
    
    				addps xmm3, xmm2								'Blue + Green
    				addps xmm3, xmm1								'BlueGreen + Red 
    				CVTPS2DQ xmm3, xmm3							'float to int
    				Pand xmm3, xmm4								'And 000000FF
    
    				movdqa xmm2, xmm3
    				PSLLD xmm2, 8
    				por xmm3, xmm2									'Luma to 0000FF00
    
    				movdqa xmm1, xmm3
    				PSLLD xmm1, 16
    				por xmm3, xmm1									'Luma to 00FF0000
    
    				por xmm3, xmm0									'Alpha to FF000000
    
    
    				movdqu [edi], xmm3							'write 4 pixels
    
    				Add edi,16                           	'address next pixel: 4 Byte = 1 dword = 1 Pixel
    				Sub ecx,4                           	'counter (next pixel)
    
    			ja .GS_Loop                              'until ecx=0
    
    			mov eax, [iMod]									'Falls Pixelanzahl nicht durch 4 teilbar, dann hier restliche Pixel berechnen:
    			cmp eax, 0
    			je .GS_End
    			shl eax, 2											'mal 4
    			Add edi, eax										'letzter Pixel
    			Sub edi, 16											'minus 4 Pixel
    			Xor eax, eax										'Reset
    			mov [iMod], eax									'Reset iMod
    			jmp .GS_Loop										'Nochmals Loop für die letzten 4 Pixel (evtl. werden Pixel doppelt berechnet, aber der Geschwindigkeitsvorteil überwiegt)	
    
    			.GS_End:
    
    	End Asm
    
    End Sub
    
    
    
    
    Extern "Windows-MS"
    
    
    Sub _GreyScale(pPixelData As UInteger Ptr, iPixelCnt As Integer) Export
    	ASM_GREYSCALE(pPixelData, iPixelCnt)
    End Sub
    
    
    End Extern
    Alles 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

    Dateien

    AutoIt_FB_DLL.zip 15,99 kB – 857 Downloads GreyScale.zip 11,98 kB – 829 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™