[GDI+] Rotierende Kreisausschnittsegmente

  • Moin,

    Motiviert durch die gestrigen Animationen habe ich heute eine kleine Animation gebastelt.
    Auf meinem Minirechner (hat keine Graka und nur einen IntelAtom) läuft der Spaß mehr oder weniger flüssig, wenns bei euch schneller ist könnt ihr die Größe erhöhen und die Anzahl hochschrauben.

    Edit: 28.09.18: Das skript hat es (wahrscheinlich vor langer Zeit) zerschossen, habe es repariert.

    lg

    Mars

  • Klasse! Vor allem als Lockscreen gefällt's mir :D

    Edit: Wobei's ja nichtmal wirklich ein Lockscreen ist, da man's einfach über den TaskManager schließen kann und wenn man 2 Bildschirme hat, ist der 2. ja trotzdem noch voll aktiv ;)
    Edit 2: Wenn du noch eine Tastaturabfrage reinhaust, dann ist es wirklich ein Lockscreen ;)

    Da es hier doch einige falsch machen:

    Zitat von einem User dieses Forums

    Die Standard-Standart eines Flamingos ist einbeinig. ;)

  • Hier nochmal auch mit Mausabfrage:

    Spoiler anzeigen
    [autoit]

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

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

    Opt('GUIOnEventMode', 1)

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

    Global Const $W = @DesktopWidth, $H = @DesktopHeight
    Global Const $Anzahl = 20

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

    Global $PEN, $GFX, $BUF, $BMP, $GUI, $TWI[$Anzahl], $IMG, $BRU
    Global Enum $CNT, $COL, $ANZ, $OFF, $DIS, $ROT, $DIA, $WID, $RAN, _
    $ROT_End, $ROT_DisMul, $ROT_OffMul, $ROT_Dir, $DIR, $COL_Add

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

    Local $MouseX = MouseGetPos(0), $MouseY = MouseGetPos(1)

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

    _GDIPlus_Startup()
    $GUI = GUICreate('Test', $W, $H, 0, 0, $WS_POPUP, $WS_EX_TOPMOST)
    $IMG = _Image_Create($W, $H)
    $BUF = DllStructGetData($IMG, 1)
    $DC = _WinAPI_GetDC($GUI)
    $GFX = _GDIPlus_GraphicsCreateFromHDC($BUF)
    $PEN = _GDIPlus_PenCreate()
    $BRU = _GDIPlus_BrushCreateSolid(0x30000000)
    _GDIPlus_GraphicsSetSmoothingMode($GFX, 2)

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

    For $i = 1 To $Anzahl Step 1
    $TWI[$i-1] = _CreateTwister(60 + $i^1.4 * 15, 6 + $i^0.8 * Random(2,4))
    Next

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

    OnAutoItExitRegister('_Dispose')
    GUISetOnEvent(-3, '_Event', $GUI)
    GUISetState(@SW_SHOW, $GUI)

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

    While Sleep(10)

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

    _GDIPlus_GraphicsFillRect($GFX, 0, 0, $W, $H, $BRU)

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

    For $i = 0 To $Anzahl - 1 Step 1
    _Twister($TWI[$i])
    Next

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

    _WinAPI_BitBlt($DC, 0, 0, $W, $H, $BUF, 0, 0, 0xCC0020)

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

    If MouseGetPos(0) <> $MouseX or MouseGetPos(1) <> $MouseY Then _event()

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

    WEnd

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

    Func _CreateTwister($_DIA, $_WID)
    Local $a[15]
    $a[$ANZ] = Random(6,15,1)
    $a[$CNT] = Random(-555555, 555555)
    $a[$COL] = 0
    $a[$OFF] = 0
    $a[$DIS] = 0
    $a[$ROT] = 0
    $a[$DIA] = $_DIA
    $a[$WID] = $_WID
    $a[$ROT_End] = 0
    $a[$ROT_OffMul] = 0
    $a[$ROT_DisMul] = 0
    $a[$ROT_Dir] = 0
    $a[$RAN] = Random(10, 20, 1)
    $a[$DIR] = Random(-2.5, 2.5)
    $a[$COL_Add] = Random(0, 10000)
    Return $a
    EndFunc

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

    Func _Twister(ByRef $a)

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

    $a[$CNT] += $a[$DIR]
    $a[$COL_Add] += 2
    $a[$COL] = '0xAA' & Hex(Int(Sin(($a[$COL_Add] +$a[$CNT]) / 100) * 127.9 + 128), 2) & Hex(Int(Sin(($a[$COL_Add] +$a[$CNT]) / 150) * 127.9 + 128), 2) & Hex(Int(Cos(($a[$COL_Add] +$a[$CNT]) / 120) * 127.9 + 128), 2)

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

    If $a[$ROT] Then
    If Not $a[$ROT_End] Then
    $a[$ROT_End] = Random(240,480)
    $a[$ROT_DisMul] = Random(0.7, 2)
    $a[$ROT_OffMul] = Random(0.4, 2)
    $a[$ROT_Dir] = Random(0, 1, 1)
    EndIf
    If $a[$ROT] > $a[$ROT_End] Then
    $a[$ROT] /= 1.5
    $a[$ROT_End] /= 1.5
    If Round($a[$ROT],0) = 0 Then
    $a[$ROT_End] = 0
    $a[$ROT] = 0
    $a[$RAN] = Random(10, 20, 1)
    EndIf
    Else
    $a[$ROT] += $a[$ROT]^0.3
    EndIf
    $a[$DIS] = ($a[$DIS]*6 + $a[$DIS] / $a[$ROT_DisMul])/7
    $a[$OFF] = ($a[$OFF]*7 + $a[$OFF] / $a[$ROT_OffMul])/8
    If Not Random(0, 100, 1) Then
    $a[$ANZ] += Random(-1, 1, 1)
    If $a[$ANZ] < 5 Then $a[$ANZ] = 5
    If $a[$ANZ] > 16 Then $a[$ANZ] = 16
    EndIf
    Else
    If IsInt(Int($a[$CNT])/$a[$RAN]) Then $a[$ROT] += 2
    EndIf

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

    If Not Random(0, 100, 1) Then $a[$DIR] = Random(-2.5, 2.5)

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

    $a[$DIS] = ($a[$DIS]*9 + $a[$WID])/10
    $a[$OFF] = ($a[$OFF]*8 + $a[$DIA])/9

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

    For $i = 0 To $a[$ANZ] - 1 Step 1
    _PieSegment($GFX, $W / 2, $H / 2, $a[$OFF], $a[$OFF], $a[$DIS], $i * 360 / $a[$ANZ] + $a[$CNT] + ($a[$ROT_Dir] = 0 ) * $a[$ROT] * 2 - $a[$ROT], 300 / $a[$ANZ], $a[$COL])
    Next

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

    EndFunc

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

    Func _PieSegment($GFX, $mX, $mY, $W, $H, $D, $fStart, $fSweep, $iCol)
    DllCall($ghGDIPDll, 'int', 'GdipSetPenColor', 'handle', $PEN, 'dword', $iCol)
    DllCall($ghGDIPDll, 'int', 'GdipSetPenWidth', 'handle', $PEN, 'float', $D)
    DllCall($ghGDIPDll, 'int', 'GdipDrawArc', 'handle', $GFX, 'handle', $PEN, 'float', $mX + $D / 2 - $W / 2, 'float', $mY + $D / 2 - $H / 2, 'float', $W - $D, 'float', $H - $D, 'float', $fStart, 'float', $fSweep)
    EndFunc ;==>_PieSegment

    [/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('GDI32.DLL', '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] [autoit][/autoit] [autoit]

    Func _Event()
    _WinEX_LockWorkStation()
    Exit
    EndFunc ;==>_Event

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

    Func _Dispose()
    _Image_Delete($Img)
    _WinAPI_ReleaseDC($GUI, $DC)
    _GDIPlus_BrushDispose($BRU)
    _GDIPlus_GraphicsDispose($GFX)
    _GDIPlus_PenDispose($PEN)
    _GDIPlus_Shutdown()
    EndFunc ;==>_Dispose

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

    Func _WinEX_LockWorkStation()
    Local $vRetVal = DllCall("user32.dll", "int", "LockWorkStation")
    If @error > 0 Then Return SetError(1, @error, 0)
    Return $vRetVal[0]
    EndFunc

    [/autoit]

    Mars Cooler Trick zum Zeichnen der Elemente :D

    Einmal editiert, zuletzt von minx (31. März 2013 um 21:55)

  • Mars Cooler Trick zum Zeichnen der Elemente :D

    Genau die Funktion (Zeichnen eines PieSegments mit GDI+) habe ich gesucht.
    Nachdem Google und Konsorten keine Antwort liefern konnten musste der Pen herhalten.
    Ist leider nicht optimal, da man so keine Ausschnitte "zeichnen" (also mit einer Linie) kann. Dazu würden 2 DrawArc + 2x DrawLine gebraucht.
    Im Endeffekt würde es in _GDIPlus_GraphicsFillPieSegment und _DrawPieSegment enden. Wobei beide seltsamerweise mit einem Pen funktionieren würden.

    Edit: Mit 20 Stück im Vollbild bekommt man ja n epilleptischen Anfall^^

  • Hab grade noch eine Kleinigkeit geändert, usprünglich war die Segmentfunktion nicht für viele gleichfarbige gleichdicke Segmente gedacht.
    In diesem Speziellen Fall kann man also das Dicke und Farbe einstellen aus der Schleife rausziehen, wodurch sich die Geschwindigkeit stark erhöht.
    Bei mir läufts jetzt ca. 40% schneller als vorher. (Auf der Schrottmühle läuft das was ich im ersten Post eingefügt habe noch annehmbar flüssig)
    Als Sperrbildschirm brauchts somit eine ganze Ecke weniger CPU,