Gedrehter Text

  • Hey Autoitter,
    ich hab mal wieder eine Frage.
    Momentan arbeite ich mit GDI+, was ich schön und gut finde, jedoch stehe ich vor einem Problem. ich muss einen gedrehten Text malen. Ich weiß bereits, dass man eine Matrix erstellen muss und diese drehen ...
    Mein Problem ist:
    1. Mein Script funktioniert nicht:
    Warum?
    (Script ist im Anhang)
    2. Hat wer ein Script?
    Wär geil ;)

    //Edit
    Warum funktioniert beim "[_Script_]" Tag kein Copy&Paste mehr? ([_Script_] natürlich ohne die " und _
    Habe den TAG jetzt gelöscht und das Script in den Anhang gepackt ...

    • Offizieller Beitrag

    Meinst du sowas?

    Spoiler anzeigen
    [autoit]

    ; ver 3.2.12.1
    #Include <WinAPI.au3>
    #include <GUIConstantsEx.au3>
    #include <StructureConstants.au3>
    #include <WindowsConstants.au3>

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

    Global $GUI = GUICreate('Test Rotation')
    GUICtrlCreateLabel('Text:', 10, 13, 50, 17)
    Global $In = GUICtrlCreateInput('Hallo!', 70, 10, 150, 20)
    Global $bt = GUICtrlCreateButton('Schreibe Text', 250, 10, 100, 20)
    Global $btDel = GUICtrlCreateButton('Lösche Text', 250, 40, 100, 20)
    GUICtrlCreateLabel('Pos. X:', 10, 43, 50, 17)
    Global $inX = GUICtrlCreateInput('80', 70, 40, 30, 20)
    GUICtrlCreateLabel('Pos. Y:', 110, 43, 50, 17)
    Global $inY = GUICtrlCreateInput('280', 170, 40, 30, 20)
    GUICtrlCreateLabel('Winkel:', 10, 73, 50, 17)
    Global $inDeg = GUICtrlCreateInput('30', 70, 70, 30, 20)
    GUICtrlCreateLabel('Höhe:', 110, 73, 50, 17)
    Global $inSize = GUICtrlCreateInput('60', 170, 70, 30, 20)
    GUICtrlCreateLabel('Breite:', 10, 103, 50, 17)
    Global $inWeight = GUICtrlCreateInput('400', 70, 100, 30, 20)
    GUICtrlCreateLabel('Font:', 110, 103, 50, 17)
    Global $inFont = GUICtrlCreateInput('Comic Sans MS', 170, 100, 200, 20)
    GUICtrlCreateGroup(' Stil ', 10, 130, 280, 40)
    Global $rDef = GUICtrlCreateRadio('Standard', 15, 145, 65)
    GUICtrlSetState(-1, $GUI_CHECKED)
    Global $rIt = GUICtrlCreateRadio('Italic', 85, 145, 45)
    Global $cbUn = GUICtrlCreateCheckbox('Underlined', 135, 145, 70)
    Global $cbSt = GUICtrlCreateCheckbox('StrikeOut', 215, 145, 70)
    GUICtrlCreateGroup("", -99, -99, 1, 1)
    GUICtrlCreateLabel('Farbe Schrift:', 10, 183, 80, 17)
    Global $inCol = GUICtrlCreateInput('', 90, 180, 60, 20)
    GUICtrlCreateLabel('Hintergrund:', 160, 183, 80, 17)
    Global $inbCol = GUICtrlCreateInput('', 230, 180, 60, 20)

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

    GUISetState()
    Global $Rect

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

    Do
    $msg = GUIGetMsg()
    If $msg = $bt Then
    Local $type = 1, $col = -1, $bkcol = -1
    If BitAND(GUICtrlRead($rIt), $GUI_CHECKED) Then $type = 2
    If BitAND(GUICtrlRead($cbUn), $GUI_CHECKED) Then $type += 4
    If BitAND(GUICtrlRead($cbSt), $GUI_CHECKED) Then $type += 8
    Local $readFont = GUICtrlRead($inFont)
    If $readFont = '' Then $readFont = -1
    Local $col = GUICtrlRead($inCol), $bkcol = GUICtrlRead($inbCol)
    If $col = '' Then $col = -1
    If $bkcol = '' Then $bkcol = -1
    _WriteRotateText($GUI, GUICtrlRead($In), GUICtrlRead($inX), GUICtrlRead($inY), GUICtrlRead($inDeg), _
    GUICtrlRead($inSize), GUICtrlRead($inWeight), $type, $readFont, $col, $bkcol)
    ElseIf $msg = $btDel Then
    _WinAPI_RedrawWindow($GUI)
    EndIf
    Until $msg = $GUI_EVENT_CLOSE

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

    ;==================================================================================================
    ; Function Name: _WriteRotateText($hWnd, $sWrite, $iX, $iY, $iDeg, $iSize [, $iWeight=400 _
    ; [, $iType=1 [, $sFont=-1 [, $iCol=-1 [, $iBkCol=-1 [,$bRedraw=True]]]]]])
    ; Description: Schreibt einen Text mit bestimmtem Winkel in das angegebene Fenster
    ; Parameter(s): $hWnd Handle des Fensters
    ; $sWrite der zu schreibende Text
    ; $iX x-Position auf dem Fenster
    ; $iY y-Position auf dem Fenster
    ; $iDeg Rotationswinkel des Textes
    ; $iSize Höhe des Textes
    ; optional: $iWeight Fontbreite 0 - 1000 (Standard 400)
    ; optional: $iType Fonttyp 1=normal (Standard); 2=Italic; 4=Underline; 8=StrikeOut
    ; 1 oder 2 können mit 4 und 8 kombiniert werden (5;9 od. 6;10)
    ; optional: $sFont Fontname -1=Font der Form (Standard)
    ; optional: $iCol Fontfarbe -1=schwarz (Standard)
    ; optional: $iBkCol Hintergrundfarbe -1=Hintergrundfarbe des Fensters (Standard)
    ; optional: $bRedraw True=Fenster vorher neu zeichnen (vorige Beschriftung löschen - Standard)
    ; Requirement(s): #Include <WinAPI.au3>; #include <StructureConstants.au3>; #include <WindowsConstants.au3>
    ;==================================================================================================
    Func _WriteRotateText($hWnd, $sWrite, $iX, $iY, $iDeg, $iSize, $iWeight=400, $iType=1, $sFont=-1, $iCol=-1, $iBkCol=-1, $bRedraw=True)
    If $bRedraw Then _WinAPI_RedrawWindow($hWnd)
    Local $tRect = DllStructCreate($tagRECT)
    DllStructSetData($tRect, 'Left', $iX)
    DllStructSetData($tRect, 'Top', $iY)
    Local $rotate = $iDeg *10
    If ($rotate = 900) Or ($rotate = 1800) Or ($rotate = 2700) Then $rotate += 1
    Local $RotateMe = DllStructCreate($tagLOGFONT)
    DllStructSetData($RotateMe, 'Escapement', $rotate)
    DllStructSetData($RotateMe, 'Height', ($iSize * -20)/_WinAPI_TwipsPerPixelY())
    If $iWeight <> 400 Then DllStructSetData($RotateMe, 'Weight', $iWeight)
    If BitAND($iType, 2) Then DllStructSetData($RotateMe, 'Italic', True)
    If BitAND($iType, 4) Then DllStructSetData($RotateMe, 'Underline', True)
    If BitAND($iType, 8) Then DllStructSetData($RotateMe, 'StrikeOut', True)
    If $sFont <> -1 Then DllStructSetData($RotateMe, 'FaceName', $sFont)
    Local $rFont = _WinAPI_CreateFontIndirect($RotateMe)
    Local $hDC = _WinAPI_GetDC($hWnd)
    If $iCol <> -1 Then _WinAPI_SetTextColor($hDC, $iCol)
    If $iBkCol <> -1 Then _WinAPI_SetBkColor($hDC, $iBkCol) ; wenn Transparenz gewünscht, Folgezeile aktivieren
    ;~ _WinAPI_SetBkMode($hDC, $TRANSPARENT)
    _WinAPI_SelectObject($hdc, $rFont)
    _WinAPI_DrawText($hDC, $sWrite, $tRect, BitOR($DT_NOCLIP,$DT_NOPREFIX))
    _WinAPI_ReleaseDC($hWnd, $hDC)
    EndFunc ;==>_WriteRotateText

    [/autoit]

    Man muß sich ja nicht unbedingt mit GDI+ quälen. :D

  • Es ist schwierig zu verstehen was du eigentlich erreichen möchtest...
    Ich habe mal ale Fehler entfernt und kommentiert. Allerdings bin ich mir nicht sicher ob es jetzt so funktioniert wie du das wolltest. :S

    Spoiler anzeigen
    [autoit]

    #include <WindowsConstants.au3>
    #include <GuiConstantsEx.au3>
    #include <array.au3>
    #include <string.au3>
    #include <GDIPlus.au3>
    #include <WinAPI.au3>

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

    Opt("GuiOnEventMode", 1)

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

    $hwnd = GUICreate("Mathe", 800, 900)
    GUISetState(@SW_SHOW)

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

    _GDIPlus_Startup()

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

    $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hwnd)
    $hBitmap = _GDIPlus_BitmapCreateFromGraphics(800, 900, $hGraphics)
    $hBuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    _GDIPlus_GraphicsSetSmoothingMode($hBuffer, 2)
    _GDIPlus_GraphicsClear($hGraphics, 0xFFFFFFFF)

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

    $hPen_All=_GDIPlus_PenCreate(0xFF000000, 2)
    $hPen_Arrow=_GDIPlus_PenCreate(0xFF000000, 2)
    $hCap = _GDIPlus_ArrowCapCreate (3, 6)
    _GDIPlus_PenSetCustomEndCap ($hPen_Arrow, $hCap)
    ;~ _GDIPlus_PenSetCustomCap ($hPen_Arrow, $hCap)

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

    AdlibRegister("_DrawFrame", 100) ;Ich kann die Timer UDF nicht leiden, und in diesem Fall ist AdlibRegister wirklich einfacher ;)

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

    GUISetOnEvent($GUI_EVENT_CLOSE, "_Close")
    GUIRegisterMsg($WM_PAINT, "WM_PAINT") ;Sobald Windows ein Neuzeichnen des Fensters verlangt, wird der Backbuffer in den Frontbuffer gezeichnet

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

    While Sleep(1000) ;Eine leere Endlosschleife belastet den Prozessor, daher ist ein Sleep angebracht.
    WEnd

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

    Func WM_PAINT()
    _GDIPlus_GraphicsDrawImage($hGraphics, $hBitmap, 0, 0) ;Zeichnet den Backbuffer in den Frontbuffer
    EndFunc

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

    Func _DrawFrame()
    _GDIPlus_GraphicsClear($hBuffer, 0xFFFFFFFF)

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

    _GDIPlus_GraphicsDrawRect($hBuffer, 250, 300, 25, 600, $hPen_All)
    _GDIPlus_GraphicsDrawRect($hBuffer, 350, 100, 25, 800, $hPen_All)
    _GDIPlus_GraphicsDrawLine($hBuffer, 350, 880, 275, 880, $hPen_Arrow)
    _GDIPlus_GraphicsDrawLine($hBuffer, 275, 880, 350, 880, $hPen_Arrow)
    _GDIPlus_GraphicsDrawString($hBuffer, "100 Fuß", 275, 860, "Arial", 12)
    _GDIPlus_GraphicsDrawLine($hBuffer, 225, 300, 225, 900, $hPen_Arrow)
    _GDIPlus_GraphicsDrawLine($hBuffer, 225, 900, 225, 300, $hPen_Arrow)
    _DrawSpinnedText($hBuffer, "60 Fuß", 200, 425, 270)

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

    _GDIPlus_GraphicsDrawImage($hGraphics, $hBitmap, 0, 0) ;Zeichnet den Backbuffer in den Frontbuffer
    EndFunc

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

    Func _DrawSpinnedText($hGraphics_s, $hText,$x, $y, $nAngle)
    $hMatrix = _GDIPlus_MatrixCreate()
    $hBMP = _GDIPlus_BitmapCreateFromGraphics(StringLen($hText)*12, 16, $hGraphics_s)
    $hG = _GDIPlus_ImageGetGraphicsContext($hBMP)
    _GDIPlus_GraphicsSetSmoothingMode($hG, 2)

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

    _GDIPlus_GraphicsDrawString($hG, $hText, 0, 0, "Arial", 12)
    _GDIPlus_MatrixRotate($hMatrix, $nAngle, "False")
    _GDIPlus_GraphicsSetTransform($hG, $hMatrix)
    _GDIPlus_GraphicsDrawImage($hGraphics_s, $hBMP, $x, $y)

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

    _GDIPlus_MatrixDispose($hMatrix) ;Ressourcen Aufräumen ist wichtig, sonst wird der Arbeitsspeicher unnötig zugemüllt.
    EndFunc

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

    Func _Close()
    _GDIPlus_GraphicsDispose($hGraphics) ;Das gleiche gilt hier, die erzeugten Grafiken; Bitmaps etc. werden nicht nur mit _GDIPlus_Shutdown gelöscht.
    _GDIPlus_GraphicsDispose($hBuffer)
    _GDIPlus_BitmapDispose($hBitmap)
    _GDIPlus_PenDispose($hPen_All)
    _GDIPlus_PenDispose($hPen_Arrow)
    _GDIPlus_ArrowCapDispose($hCap)
    _GDIPlus_Shutdown()
    exit 0
    EndFunc

    [/autoit]


    Ich glaube das mit dem Backbuffer hast du irgendwie falsch verstanden. ^^

  • Ja, sieht gut aus ...
    Aber ich möchte die Schrift in ein HBITMAP Handle schreiben, welches ich per Parameter übergebe.
    Aber trotzdem danke für die schnelle Antwort
    Der Text soll Parallel zu der Linie entlaufen. Dies will ich mit der einfachen Angabe eines Winkels haben. Die Funktion funktioniert immer noch nicht-

    Meine Werke


    EasyScreen (teilweise Crocoframe): <EasyScreen>
    Spotify2Title: <Spotify2Title> (zur Info, dies ist KEIN Spotify-Downloader! Wer das dachte... :rofl: sowas gibts hier nicht :thumbdown: )

  • So, ich hab jetzt mal eine Funktion geschrieben die im Prinzip das machst was du willst. Nur musst du dann die Bitmap außerhalb der Funktion erzeugen. (Wozu überhaupt die extra Bitmap? Und Wieso willst du das alle 100ms neuzeichnen lassen? Da reicht doch schon WM_PAINT.).

    Spoiler anzeigen
    [autoit]

    #include <WindowsConstants.au3>
    #include <GuiConstantsEx.au3>
    #include <array.au3>
    #include <string.au3>
    #include <GDIPlus.au3>
    #include <WinAPI.au3>

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

    Opt("GuiOnEventMode", 1)

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

    $hwnd = GUICreate("Mathe", 800, 900)
    GUISetState(@SW_SHOW)

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

    _GDIPlus_Startup()

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

    $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hwnd)
    $hBitmap = _GDIPlus_BitmapCreateFromGraphics(800, 900, $hGraphics)
    $hBuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    _GDIPlus_GraphicsSetSmoothingMode($hBuffer, 2)
    _GDIPlus_GraphicsClear($hGraphics, 0xFFFFFFFF)

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

    $hBrushText = _GDIPlus_BrushCreateSolid(0xFF000000)
    $hFormat = _GDIPlus_StringFormatCreate()
    $hFamily = _GDIPlus_FontFamilyCreate("Arial")
    $hFont = _GDIPlus_FontCreate($hFamily, 12)

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

    $hPen_All=_GDIPlus_PenCreate(0xFF000000, 2)
    $hPen_Arrow=_GDIPlus_PenCreate(0xFF000000, 2)
    $hCap = _GDIPlus_ArrowCapCreate (3, 6)
    _GDIPlus_PenSetCustomEndCap ($hPen_Arrow, $hCap)
    ;~ _GDIPlus_PenSetCustomCap ($hPen_Arrow, $hCap)

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

    AdlibRegister("_DrawFrame", 100) ;Ich kann die Timer UDF nicht leiden, und in diesem Fall ist AdlibRegister wirklich einfacher ;)

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

    GUISetOnEvent($GUI_EVENT_CLOSE, "_Close")
    GUIRegisterMsg($WM_PAINT, "WM_PAINT") ;Sobald Windows ein Neuzeichnen des Fensters verlangt, wird der Backbuffer in den Frontbuffer gezeichnet

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

    While Sleep(1000) ;Eine leere Endlosschleife belastet den Prozessor, daher ist ein Sleep angebracht.
    WEnd

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

    Func WM_PAINT()
    _GDIPlus_GraphicsDrawImage($hGraphics, $hBitmap, 0, 0) ;Zeichnet den Backbuffer in den Frontbuffer
    EndFunc

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

    Func _DrawFrame()
    _GDIPlus_GraphicsClear($hBuffer, 0xFFFFFFFF)

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

    _GDIPlus_GraphicsDrawRect($hBuffer, 250, 300, 25, 600, $hPen_All)
    _GDIPlus_GraphicsDrawRect($hBuffer, 350, 100, 25, 800, $hPen_All)
    _GDIPlus_GraphicsDrawLine($hBuffer, 350, 880, 275, 880, $hPen_Arrow)
    _GDIPlus_GraphicsDrawLine($hBuffer, 275, 880, 350, 880, $hPen_Arrow)
    _GDIPlus_GraphicsDrawString($hBuffer, "100 Fuß", 275, 860, "Arial", 12)
    _GDIPlus_GraphicsDrawLine($hBuffer, 225, 300, 225, 900, $hPen_Arrow)
    _GDIPlus_GraphicsDrawLine($hBuffer, 225, 900, 225, 300, $hPen_Arrow)

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

    _GDIPlus_GraphicsDrawTextRotated($hBuffer, "60 Fuß", $hFont, $hFormat, $hBrushText, 200, 245, 270)

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

    _GDIPlus_GraphicsDrawImage($hGraphics, $hBitmap, 0, 0) ;Zeichnet den Backbuffer in den Frontbuffer
    EndFunc

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

    Func _GDIPlus_GraphicsDrawTextRotated($hGraphic, $sString, $hFont, $hFormat, $hBrush, $iX_Text, $iY_Text, $nAngle)
    $tStringMeasure = _GDIPlus_GraphicsMeasureString($hGraphic, $sString, $hFont, _GDIPlus_RectFCreate(), $hFormat)
    $iStringWidth = DllStructGetData($tStringMeasure, "width")
    $iStringHeight = DllStructGetData($tStringMeasure, "height")
    $hMatrixR = _GDIPlus_MatrixCreate()
    $hMatrixReset = _GDIPlus_MatrixCreate()

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

    _GDIPlus_MatrixTranslate($hMatrixR, $iX_Text + $iStringWidth / 2, $iY_Text + $iStringHeight / 2)
    _GDIPlus_MatrixRotate($hMatrixR, $nAngle)
    _GDIPlus_GraphicsSetTransform($hGraphic, $hMatrixR)
    _GDIPlus_GraphicsDrawStringEx($hGraphic, $sString, $hFont, _GDIPlus_RectFCreate($iStringWidth / -2, $iStringHeight / -2), $hFormat, $hBrush)
    _GDIPlus_GraphicsSetTransform($hGraphic, $hMatrixReset)

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

    _GDIPlus_MatrixDispose($hMatrixR)
    _GDIPlus_MatrixDispose($hMatrixReset)
    EndFunc

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

    Func _Close()
    _GDIPlus_GraphicsDispose($hGraphics) ;Das gleiche gilt hier, die erzeugten Grafiken; Bitmaps etc. werden nicht nur mit _GDIPlus_Shutdown gelöscht.
    _GDIPlus_GraphicsDispose($hBuffer)
    _GDIPlus_BitmapDispose($hBitmap)
    _GDIPlus_FontDispose($hFont)
    _GDIPlus_FontFamilyDispose($hFamily)
    _GDIPlus_StringFormatDispose($hFormat)
    _GDIPlus_BrushDispose($hBrushText)
    _GDIPlus_PenDispose($hPen_All)
    _GDIPlus_PenDispose($hPen_Arrow)
    _GDIPlus_ArrowCapDispose($hCap)
    _GDIPlus_Shutdown()
    exit 0
    EndFunc

    [/autoit]