Jump to content

GDI+ sloping text graphics on picture control. and


Malkey
 Share

Recommended Posts

This is just a static example of the possibilities.

Points of interest.

- The GDIPlus graphics are displayed on a GUI picture control.

- The graphics do not appear to erase as GDI+ graphics normally do.

- The gradient background is created using variations in hue.

These above techniques have previously appeared on the AutoIt forums.

The name GDIPlus_SetAngledText(), has the GDIPlus_ prefix as a reminder that _GDIPlus_Startup() has to be called before using this function.

_GDIPlus_Shutdown() is called after.

The button and GUI label control are not part of the graphics. The saved image file saves only the graphics.

The last optional parameter, $iAnchor:-

- If set to 0 (default), the $iCentreX , $iCentreY positioning values refer to the centre of the text string.

- If other than 0 (zero), the $iCentreX , $iCentreY positioning values refer to the top left corner of the text string, or close to it.

For those interested in the mathematics, search on "Parametric equations for a circle" and search on "Rotation of Coordinate Axes formulae". And see comments in script.

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

Opt("GUIOnEventMode", 1) ;0=disabled, 1=OnEvent mode enabled
Global $ApW = 600, $ApH = 400
Global $Button[1]
Global Const $iPI = 3.1415926535897932384626433832795

$hGui = GUICreate("GDIPlus Graphics on Picture Control - OnEvent Mode", $ApW + 40, $ApH + 40)
GUISetOnEvent(-3, "_Quit")
GUISetBkColor(0xffA0A0, $hGui)

$Pic = GUICtrlCreatePic("", 20, 20, $ApW, $ApH)
GUICtrlSetState(-1, $GUI_DISABLE)

$Button[0] = GUICtrlCreateButton("Exit", 5, 5, 100, 45)
GUICtrlSetOnEvent($Button[0], "_Quit")
GUICtrlSetBkColor(-1, 0xF000FF)
GUICtrlSetColor(-1, 0xBadB0B)

GUICtrlCreateLabel("A GUICtrlCreateLabel", 120, 50, 200, 20)
GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT)

PicSetGraphics($Pic, $ApW, $ApH); <-- Draw GDIPlus graphics on Picture control.

GUISetState(@SW_SHOW, $hGui)

While 1
    Sleep(10)
WEnd

Func PicSetGraphics($cID, $iW, $iH)
    Local Const $STM_SETIMAGE = 0x0172
    Local Const $IMAGE_BITMAP = 0
    Local $hWnd, $hBitmap, $hImage, $hGraphic, $hBrush, $hBrush1, $hbmp, $aBmp
    $hWnd = GUICtrlGetHandle($cID)
    _GDIPlus_Startup()
    
    ;Buffer
    $hBitmap = _WinAPI_CreateSolidBitmap($hGui, 0xFFFFFF, $iW, $iH) ; or use next command
    ;$hBitmap = _WinAPI_CreateBitmap($iW, $iH, 1, 32);If this is used change $Pen1 tansparency from "0x80" to "0xFF"
    $hImage = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap)
    $hGraphic = _GDIPlus_ImageGetGraphicsContext($hImage)
    
    ;----->  All Graphics Here
    ;Rainbow background
    For $x = 0 To $ApW
        $hue = Color_SetHSL(Int($x / 2))
        $hPen1 = _GDIPlus_PenCreate( "0x80" & Hex($hue, 6), 1) ; "0xFF" & Hex($hue, 6), 1) ;
        _GDIPlus_GraphicsDrawLine($hGraphic, $x, 0, $x, $ApH, $hPen1)
        _GDIPlus_PenDispose($hPen1)
    Next
    
    ;Ellipse 
    $hBrush = _GDIPlus_BrushCreateSolid(0xFF0080FF)
    _GDIPlus_GraphicsFillEllipse($hGraphic, 230, 20, 50, 90, $hBrush)
    
    ;Diagonal red line
    $hPen = _GDIPlus_PenCreate(0xFFFF0000, 2)
    _GDIPlus_GraphicsDrawLine($hGraphic, 0, $ApH, $ApW, 0, $hPen)
    _GDIPlus_GraphicsDrawString ($hGraphic, "Hello world",$ApW/2, $ApH-15) ; From help file
     
    GDIPlus_SetAngledText($hGraphic, "Example text Incline", 415, 110, -ATan($ApH / $ApW) * 180 / $iPI, "", 16, 0xFF0080FF)
    ; Next command - Sometimes easier to have positioning point (anchor) at top left corner of text string.
    GDIPlus_SetAngledText($hGraphic, "Example text Decline", 0, 0, ATan($ApH / $ApW) * 180 / $iPI, "", 18, 0xFF8080FF, 1)
    GDIPlus_SetAngledText($hGraphic, "Example text Incline Inverted", 165, 305, 180 - ATan($ApH / $ApW) * 180 / $iPI)
    GDIPlus_SetAngledText($hGraphic, "Example text Decline Inverted", 435, 305, 180 + ATan($ApH / $ApW) * 180 / $iPI, "", "", "")
    GDIPlus_SetAngledText($hGraphic, "Example text zero Angle", $ApW / 2, 8, 0, "Times New Roman", 10, 0xFF801010)
    GDIPlus_SetAngledText($hGraphic, "Example text Vertical (270Deg Angle)", $ApW - 10, $ApH / 2, 270, "", 8, 0xFF801010)
    

    ; -----> End of all Graphics
    
    ; Keeps all GDIPlus graphics visible
    $hbmp = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
    $aBmp = DllCall("user32.dll", "hwnd", "SendMessage", "hwnd", $hWnd, "int", $STM_SETIMAGE, "int", $IMAGE_BITMAP, "int", $hbmp)
    _WinAPI_RedrawWindow($hGui, "", "", BitOR($RDW_INVALIDATE, $RDW_UPDATENOW, $RDW_FRAME))
    
    ; Save Graphics on picture control
    _GDIPlus_ImageSaveToFile($hImage, @DesktopDir & "\TestWrite1.png")
    ShellExecute(@DesktopDir & "\TestWrite1.png")
    
    If $aBmp[0] <> 0 Then _WinAPI_DeleteObject($aBmp[0])
    _GDIPlus_ImageDispose($hImage)
    _GDIPlus_BrushDispose($hBrush)
    _GDIPlus_PenDispose($hPen)
    _GDIPlus_GraphicsDispose($hGraphic)
    _WinAPI_DeleteObject($hbmp)
    _WinAPI_DeleteObject($hBitmap)
    _GDIPlus_Shutdown()
EndFunc   ;==>PicSetGraphics

Func _Quit()
    Local $iDeletePict = MsgBox(4, "Delete Saved Image File", "Do you wish to delete the saved image file, TestWrite1.png? Y/N")
    If $iDeletePict = 6 Then FileDelete(@DesktopDir & "\TestWrite1.png")
    Exit
EndFunc   ;==>_Quit

; #FUNCTION# ================================================================
; Name...........: GDIPlus_SetAngledText
; Description ...: Adds text to a graphic object at any angle.
; Syntax.........: GDIPlus_SetAngledText($hGraphic, $nText, [$iCentreX, [$iCentreY, [$iAngle , [$nFontName , _
;                                       [$nFontSize, [$iARGB, [$iAnchor]]]]]]] )
; Parameters ....: $hGraphic   - The Graphics object to receive the added text.
;                  $nText      - Text string to be displayed
;                  $iCentreX       - Horizontal coordinate of horixontal centre of the text rectangle        (default =  0 )
;                  $iCentreY        - Vertical coordinate of vertical centre of the text rectangle             (default = 0 )
;                  $iAngle     - The angle which the text will be place in degrees.         (default = "" or blank = 0 )
;                  $nFontName  - The name of the font to be used                      (default = "" or Blank = "Arial" )
;                  $nFontSize  - The font size to be used                                  (default = "" or Blank = 12 )
;                  $iARGB      - Alpha(Transparency), Red, Green and Blue color (0xAARRGGBB) (Default= "" = random color
;                                                                                      or Default = Blank = 0xFFFF00FF )
;                  $iAnchor    - If zero (default) positioning $iCentreX, $iCentreY values refer to centre of text string.
;                                If not zero positioning $iCentreX, $iCentreY values refer to top left corner of text string.
; Return values .: 1
; Author ........: Malkey
; Modified.......:
; Remarks .......: Call _GDIPlus_Startup() before starting this function, and call _GDIPlus_Shutdown()after function ends.
;                  Can enter calculation for Angle Eg. For incline, -ATan($iVDist / $iHDist) * 180 / $iPI , where
;                  $iVDist is Vertical Distance,  $iHDist is Horizontal Distance, and, $iPI is Pi, (an added Global Const).
;                  When used with other graphics, call this function last. The MatrixRotate() may affect following graphics.
; Related .......: _GDIPlus_Startup(), _GDIPlus_Shutdown(), _GDIPlus_GraphicsDispose($hGraphic)
; Link ..........;
; Example .......; Yes
; ========================================================================================
Func GDIPlus_SetAngledText($hGraphic, $nText, $iCentreX = 0, $iCentreY = 0, $iAngle = 0, $nFontName = "Arial", _
        $nFontSize = 12, $iARGB = 0xFFFF00FF, $iAnchor = 0)
    Local $x, $y, $iX, $iY, $iWidth, $iHeight
    Local $hMatrix, $iXt, $iYt, $hBrush, $hFormat, $hFamily, $hFont, $tLayout
    
    ; Default values
    If $iAngle = "" Then $iAngle = 0
    If $nFontName = "" Or $nFontName = -1 Then $nFontName = "Arial" ; "Microsoft Sans Serif"
    If $nFontSize = "" Then $nFontSize = 12
    If $iARGB = "" Then ; Randomize ARGB color
        $iARGB = "0xFF" & Hex(Random(0, 255, 1), 2) & Hex(Random(0, 255, 1), 2) & Hex(Random(0, 255, 1), 2)
    EndIf
    
    $hFormat = _GDIPlus_StringFormatCreate(0)
    $hFamily = _GDIPlus_FontFamilyCreate($nFontName)
    $hFont = _GDIPlus_FontCreate($hFamily, $nFontSize, 1, 3)
    $tLayout = _GDIPlus_RectFCreate($iCentreX, $iCentreY, 0, 0)
    $aInfo = _GDIPlus_GraphicsMeasureString($hGraphic, $nText, $hFont, $tLayout, $hFormat)
    $iWidth = Ceiling(DllStructGetData($aInfo[0], "Width"))
    $iHeight = Ceiling(DllStructGetData($aInfo[0], "Height"))
    
    ;Later calculations based on centre of Text rectangle.
    If $iAnchor = 0 Then ; Reference to middle of Text rectangle
        $iX = $iCentreX
        $iY = $iCentreY
    Else ; Referenced centre point moved to top left corner of text string.
        $iX = $iCentreX + (($iWidth - Abs($iHeight * Sin($iAngle * $iPI / 180))) / 2)
        $iY = $iCentreY + (($iHeight + Abs($iWidth * Sin($iAngle * $iPI / 180))) / 2)
    EndIf
    
    ;Rotation Matrix
    $hMatrix = _GDIPlus_MatrixCreate()
    _GDIPlus_MatrixRotate($hMatrix, $iAngle, 1)
    _GDIPlus_GraphicsSetTransform($hGraphic, $hMatrix)
    
    ;x, y are display coordinates of center of width and height of the rectanglular text box.
    ;Top left corner coordinates rotate in a circular path with radius = (width of text box)/2.
    ;Parametric equations for a circle, and adjustments for centre of text box
    $x = ($iWidth / 2) * Cos($iAngle * $iPI / 180) - ($iHeight / 2) * Sin($iAngle * $iPI / 180)
    $y = ($iWidth / 2) * Sin($iAngle * $iPI / 180) + ($iHeight / 2) * Cos($iAngle * $iPI / 180)
    
    ;Rotation of Coordinate Axes formulae - To display at x and y after rotation, we need to enter the
    ;x an y position values of where they rotated from. This is done by rotating the coordinate axes.
    ;Use $iXt, $iYt in  _GDIPlus_RectFCreate. These x, y values is the position of the rectangular
    ;text box point before rotation. (before translation of the matrix)
    $iXt = ($iX - $x) * Cos($iAngle * $iPI / 180) + ($iY - $y) * Sin($iAngle * $iPI / 180)
    $iYt = -($iX - $x) * Sin($iAngle * $iPI / 180) + ($iY - $y) * Cos($iAngle * $iPI / 180)
    
    $hBrush = _GDIPlus_BrushCreateSolid($iARGB)
    $tLayout = _GDIPlus_RectFCreate($iXt, $iYt, $iWidth, $iHeight)
    _GDIPlus_GraphicsDrawStringEx($hGraphic, $nText, $hFont, $tLayout, $hFormat, $hBrush)
    
    ; Clean up resources
    _GDIPlus_MatrixDispose($hMatrix)
    _GDIPlus_FontDispose($hFont)
    _GDIPlus_FontFamilyDispose($hFamily)
    _GDIPlus_StringFormatDispose($hFormat)
    _GDIPlus_BrushDispose($hBrush)
    $tLayout = ""
    Return 1
EndFunc   ;==>GDIPlus_SetAngledText

Func Color_SetHSL($iHue, $Saturation = 180, $Brightness = 160)
    If IsArray($iHue) Then
        $aInput = $iHue
    Else
        Local $aInput[3] = [$iHue, $Saturation, $Brightness]
    EndIf
    Local $aiRGB = _ColorConvertHSLtoRGB($aInput)
    Return "0x" & Hex(Round($aiRGB[0]), 2) & Hex(Round($aiRGB[1]), 2) & Hex(Round($aiRGB[2]), 2)
EndFunc   ;==>_Color_SetHSL

See next post for placing a string on ellipse boundary.

Edit: 30/11/2008 The GDIPlus_SetAngledText() function was also used on the "CAPTCHA" script at

http://www.autoitscript.com/forum/index.ph...st&p=610926

Edited by Malkey
Link to comment
Share on other sites

I was just about to post the above post when I thought of a possibility.

Have you ever wanted to place text on a curve in AutoIt? Well, neither have I. But now you can.

The idea was to place each character in a string perpendicular to a curve.

Geometry of how it works

Using parametic equations for an ellipse, and function parameter, $iStartAngle, the first point on the boundary of the ellipse can be established.

The 2nd point in a clockwise direction is established by being a "single character font rectangle width" distance from the 1st point and also on the boundary of the

ellipse. This is done in the Do / While loop in the TextDataClockwiseEllipse() function.

Note:- Script could bomb out here. Eg. If the font width is close to or greater than the Axis length of the ellipse, the 2nd point will not be established.

The 1st and 2nd points on the ellipse, a font width apart, is a chord of the curve.

A perpendiculer from the mid-point of the chord at a distance (font height )/2 in a direction away from the centre of the ellipse, gives the x, y values of the centre of the

single character rectangle. This x and y values, together with the angle of the perpendicular to the chord are entered as parameters of the GDIPlus_SetAngledText()

function, to rotate the text.

This is repeated for each character in the string. Although the starting angle of the next character is the angle to the 2nd point of the previous character. That is, an

angle from the x-axis to a line which is from the centre of the ellipse to the 2nd point on the boundary of the ellipse.

Added Features

I can see possible added features by adding rewrites of the TextDataClockwiseEllipse() function.

The only two added features are :-

An array of colours - (optional) The colours in the array are looped through which colours each character sequencially in the string; and,

Spacing of characters - (optional) A plus or minus value to increase or decrease the spacing between characters of the string when displayed on the curve.

#include <GuiConstantsEx.au3>
#include <GDIPlus.au3>
#include <WinAPI.au3>

Opt('MustDeclareVars', 1)
Global $hGUI, $hGraphic, $hGraphicGUI, $hBMPBuff, $hPen
Global Const $iPI = 3.1415926535897932384626433832795

_Main()

Func _Main()
    Local $iGuiX = 350, $iGuiY = 250, $hBrush
    Local $hMatrix, $iXt, $iYt, $hBrush, $hFormat, $hFamily, $hFont, $tLayout, $aInfo
    
    ; Create GUI
    $hGUI = GUICreate("GDI+ Text 2 Curve", $iGuiX, $iGuiY)
    ;$hWnd = WinGetHandle("GDI+")
    GUISetState()

    _GDIPlus_Startup()
    
    $hGraphicGUI = _GDIPlus_GraphicsCreateFromHWND($hGUI)
    $hBMPBuff = _GDIPlus_BitmapCreateFromGraphics($iGuiX, $iGuiY, $hGraphicGUI)
    $hGraphic = _GDIPlus_ImageGetGraphicsContext($hBMPBuff)
    
    GDIPlus_AntiAlias($hGraphic)
    
    ;---- Start of Drawing Graphics
    $hPen = _GDIPlus_PenCreate(0xFF000000, 1)
    _GDIPlus_GraphicsClear($hGraphic, 0xFFf0FFF0)
    
    GDIPlus_Text2Curve($hGraphic, "An AutoIt Text to Curve Example.", 50, 50, 250, 150, 201, -1, "Arial", 12, 0xFF101010)
    
    ; Using an array of colours for each character
    Local $aARGB[4] = [0xFFF000F0, 0xFF00A000, 0xFFFF0000, 0xFF0000FF]
    GDIPlus_Text2Curve($hGraphic, "An AutoIt Text to Curve Example.", 50, 50, 250, 150, 200, -1, "Arial", 12, $aARGB)
    
    GDIPlus_Text2Curve($hGraphic, "AutoIt", 165, 115, 20, 20, 180, -9, "Arial", 13, 0xFF0000FF)
    ;---- End of Graphics
    
    GUIRegisterMsg(0xF, "MY_PAINT"); Register PAINT-Event 0x000F = $WM_PAINT (WindowsConstants.au3)
    _WinAPI_RedrawWindow($hGUI, 0, 0, 2) ;PAINT the window Flag $RDW_INTERNALPAINT = 0x0002
    ; Loop until user exits
    Do
    Until GUIGetMsg() = $GUI_EVENT_CLOSE

    ; Clean up resources
    _GDIPlus_GraphicsDispose($hGraphicGUI)
    _GDIPlus_PenDispose($hPen)
    _WinAPI_DeleteObject($hBMPBuff)
    
    _GDIPlus_Shutdown()

EndFunc   ;==>_Main


;Parameters
;       $hGraphics  - Handle to a Graphics object
;       $sText      - The string of text to be displayed around the ellipse.
;       $iX         - The X coordinate of the upper left corner of the rectangle that bounds the ellipse
;                     in which todraw the arc on which the text will be placed.
;       $iY         - The Y coordinate of the upper left corner of the rectangle that bounds the ellipse in which to
;                     draw the arc on which the text will be placed.
;       $iWidth     - The width of the rectangle that bounds the ellipse in which to draw the arc
;       $iHeight    - The height of the rectangle that bounds the ellipse in which to draw the arc
;       $nStartAngle - The angle between the X axis and the starting point of the arc
;       $iSpacing    - A plus or minus value to increase or decrease the spacing between the displayed characters.
;       $nFontName   - Name of the font to use for drawing
;       $nFontSize   - Font size to use for drawing
;       $iARGB       - A colour that is used to colour the text. Default is a  black.  If an array of colours is used,
;                      the colours will be used sequencially on each character, again and again to end of string.

Func GDIPlus_Text2Curve($hGraphics, $sText, $iX, $iY, $iWidth, $iHeight, $iStartAngle = 200, $iSpacing = -1, _
        $nFontName = "Arial", $nFontSize = 12, $iARGB = 0xFF000000)
    Local $aChar, $hFormat, $hFamily, $hFont, $tLayout, $aInfo, $iRectWidth, $iRectHeight, $iMaxRectWidth = 0
    Local $hPen1, $aTextDat, $aARGB
    If IsArray($iARGB) Then $aARGB = $iARGB
    $aChar = StringSplit($sText, "")
    Local $aCharAll[$aChar[0] + 1][3]
    For $n = 1 To $aChar[0]
        ;ConsoleWrite($n & "  " & $aChar[$n] & "  Width = ")
        $hFormat = _GDIPlus_StringFormatCreate(0)
        $hFamily = _GDIPlus_FontFamilyCreate($nFontName)
        $hFont = _GDIPlus_FontCreate($hFamily, $nFontSize, 3, 3)
        $tLayout = _GDIPlus_RectFCreate(50, 50, 0, 0)
        $aInfo = _GDIPlus_GraphicsMeasureString($hGraphic, $aChar[$n], $hFont, $tLayout, $hFormat)
        $aCharAll[$n][1] = Ceiling(DllStructGetData($aInfo[0], "Width"))
        $aCharAll[$n][2] = Ceiling(DllStructGetData($aInfo[0], "Height"))
        If $aCharAll[$n][1] > $iMaxRectWidth Then $iMaxRectWidth = $aCharAll[$n][1]
        ;ConsoleWrite($aCharAll[$n][1 ]& " Height =  " & $aCharAll[$n][2] & @CRLF)
    Next
    
    ; Draw Ellipses
    $hPen1 = _GDIPlus_PenCreate(0xFF800000, 2)
    ;GDIPlus_AntiAlias($hGraphic)
    _GDIPlus_GraphicsDrawArc($hGraphic, $iX - $iMaxRectWidth - 2, $iY - $iMaxRectWidth - 2, _
    $iWidth + 4 + $iMaxRectWidth * 2, $iHeight + 4 + $iMaxRectWidth * 2, $iStartAngle, 360, $hPen1)
    _GDIPlus_GraphicsDrawArc($hGraphic, $iX, $iY, $iWidth, $iHeight, $iStartAngle, 360, $hPen1)
    ;ConsoleWrite( "$iMaxRectWidth =  " &$iMaxRectWidth & @CRLF)
    
    ; For each character get positioning data, then use GDIPlus_SetAngledText() to draw rotated text.
    Local $index
    For $n = 1 To $aChar[0]
        $aTextDat = TextDataClockwiseEllipse($iStartAngle, $iMaxRectWidth, $aCharAll[$n][2], $iX, $iY, $iWidth, $iHeight, $iSpacing)
        $iStartAngle = $aTextDat[3]
        ;ConsoleWrite("$aChar[$n] = " & $aChar[$n] & "  $iStartAngle = " & $iStartAngle & @CRLF)
        If IsArray($aARGB) Then
            $index = Mod($n, UBound($aARGB))
            $iARGB = $aARGB[$index]
        EndIf
        GDIPlus_SetAngledText($hGraphic, $aChar[$n], $aTextDat[0], $aTextDat[1], $aTextDat[2], "", "", $iARGB, 0)
    Next
    If $hPen1 <> "" Then _GDIPlus_PenDispose($hPen1)
EndFunc   ;==>GDIPlus_Text2Curve

; Used in conjuction with and called from GDIPlus_Text2Curve().
Func TextDataClockwiseEllipse($iStartAngle, $iRectWidth, $iRectHeight, $iX, $iY, $iWidth, $iHeight, $iSpacing)
    Local $x2, $y2, $dist, $xT, $yT, $dist1, $xfact, $yfact, $direct, $aRet[4], $iQuadrant, $t, $x, $y
    Local $SmallAxis
    Local $h = $iX + ($iWidth / 2) ; X coordinate of centre of ellipse
    Local $k = $iY + ($iHeight / 2) ; Y coordinate of centre of ellipse
    Local $a = $iWidth / 2 ; a axis length of ellipse
    Local $b = $iHeight / 2 ; other axis of ellipse
    If $a < $b Then
        $SmallAxis = $a
    Else
        $SmallAxis = $a
    EndIf
    $iRectWidth += $iSpacing
    
    $t = $iStartAngle
    $x = $h + $a * Cos($t * $iPI / 180); 1st point on ellipse boundary
    $y = $k + $b * Sin($t * $iPI / 180)
    
    ;Initializing ready for Do/Until loop
    Local $Ang = Int(($iRectWidth / ($SmallAxis * 2)) * 360 / $iPI) + 10
    Local $increm = 5
    Local $counter = 0
    $t = $iStartAngle + $Ang
    $x2 = $h + $a * Cos($t * $iPI / 180) ; 2nd point on ellipse
    $y2 = $k + $b * Sin($t * $iPI / 180)
    $dist = Sqrt(($x - $x2) ^ 2 + ($y - $y2) ^ 2)
    
    ; Finds the 2nd point on the ellipse boundary that is $iRectWidth distance from 1st point
    Do
        $dist1 = $dist
        $t = $iStartAngle + $Ang ;The angle from centre of ellipse to 2nd point on ellipse boundary
        $x2 = $h + $a * Cos($t * $iPI / 180) ; keep adjusting the angle for new 2nd point
        $y2 = $k + $b * Sin($t * $iPI / 180)
        $dist = Sqrt(($x - $x2) ^ 2 + ($y - $y2) ^ 2) ; new distance between 1st and 2nd points.
        If $dist < $iRectWidth Then $Ang += $increm
        If $dist > $iRectWidth Then $Ang -= $increm
        If $dist1 < $dist Then $increm = $increm * 0.75
        $counter += 1
        If $counter > 300 Then
            MsgBox(0, "Error", "Stuck in Do / Until loop in TextDataClockwiseEllipse()")
            Exit
        EndIf
        ;ConsoleWrite("  $counter = " &  $counter &"  $iRectWidth = " &  $iRectWidth & "  $x2 = " & _
        ;$x2 & "  $y2 = " & $y2 & "$t = " & $t & "  Near $dist = " & $dist & @CRLF)
    Until $dist + 0.000001 > $iRectWidth And $dist - 0.000001 < $iRectWidth
    
    Local $AngPerp = ATan(-($x2 - $x) / ($y2 - $y)) * 180 / $iPI + 180;Angle perpendicular to chord, $iRectWidth long
    ;ConsoleWrite( "  $AngPerp = " & $AngPerp & @CRLF)
    Local $xc = ($x2 - $x) / 2 + $x ;Midpoint of chord
    Local $yc = ($y2 - $y) / 2 + $y
    
    ; Chech which quadrant the angle of the line from the centre of ellipse through centre of $iRectWidth (chord on ellipse)
    $iQuadrant = Mod(Int((($t - $iStartAngle) / 2 + $iStartAngle) / 90), 4) + 1
    Switch $iQuadrant
        Case 1 ; 1st quadrant between zero and 90 degrees
            $xfact = -1
            $yfact = -1
            $direct = -90
        Case 2 ; 2nd quadrant between 90 and 180 degrees
            $xfact = 1
            $yfact = 1
            $direct = 90
        Case 3 ; 3rd quadrant between 180 and 270 degrees
            $xfact = 1
            $yfact = 1
            $direct = 90
        Case 4 ; 4th quadrant between 270 and 360 degrees
            $xfact = -1
            $yfact = -1
            $direct = -90
    EndSwitch
    
    ; The point that is half the font height ($iRectHeight) distance away from, and is perpendicular to
    ; the midpoint of the font width($iRectWidth). $iRectWidth is a chord on the curved ellipse boundary.
    $xT = $xc + $iRectHeight / 2 * Cos($AngPerp * $iPI / 180) * $xfact
    $yT = $yc + $iRectHeight / 2 * Sin($AngPerp * $iPI / 180) * $yfact
    
    $aRet[0] = $xT
    $aRet[1] = $yT
    $aRet[2] = $AngPerp + $direct
    ; $t is the angle off X-axis of line from centre oy ellipse to 2nd point on ellipse boundary. Will become
    ; starting angle for next character.
    $aRet[3] = $t
    Return $aRet
EndFunc   ;==>TextDataClockwiseEllipse

;Func to redraw the BMP on PAINT MSG
Func MY_PAINT($hWnd, $MSG, $wParam, $lParam)
    ; Check, if the GUI with the Graphic should be repainted
    If $hWnd = $hGUI Then _GDIPlus_GraphicsDrawImage($hGraphicGUI, $hBMPBuff, 0, 0)
EndFunc   ;==>MY_PAINT

;See 1st post at http://www.autoitscript.com/forum/index.php?s=&showtopic=81443&view=findpost&p=584436 
Func GDIPlus_SetAngledText($hGraphic, $nText, $iCentreX = 0, $iCentreY = 0, $iAngle = 0, $nFontName = "Arial", _
        $nFontSize = 12, $iARGB = 0xFFFF00FF, $iAnchor = 0)
    Local $x, $y, $iX, $iY, $iWidth, $iHeight
    Local $hMatrix, $iXt, $iYt, $hBrush, $hFormat, $hFamily, $hFont, $tLayout, $aInfo
    If $iAngle = "" Then $iAngle = 0
    If $nFontName = "" Or $nFontName = -1 Then $nFontName = "Arial" ; "Microsoft Sans Serif"
    If $nFontSize = "" Then $nFontSize = 12
    If $iARGB = "" Then ; Randomize ARGB color
        $iARGB = "0xFF" & Hex(Random(0, 255, 1), 2) & Hex(Random(0, 255, 1), 2) & Hex(Random(0, 255, 1), 2)
    EndIf
    $hFormat = _GDIPlus_StringFormatCreate(0)
    $hFamily = _GDIPlus_FontFamilyCreate($nFontName)
    $hFont = _GDIPlus_FontCreate($hFamily, $nFontSize, 1, 3)
    $tLayout = _GDIPlus_RectFCreate($iCentreX, $iCentreY, 0, 0)
    $aInfo = _GDIPlus_GraphicsMeasureString($hGraphic, $nText, $hFont, $tLayout, $hFormat)
    $iWidth = Ceiling(DllStructGetData($aInfo[0], "Width"))
    $iHeight = Ceiling(DllStructGetData($aInfo[0], "Height"))
    If $iAnchor = 0 Then ; Reference to middle of Text rectangle
        $iX = $iCentreX
        $iY = $iCentreY
    Else ; Referenced centre point moved to top left corner of text string.
        $iX = $iCentreX + (($iWidth - Abs($iHeight * Sin($iAngle * $iPI / 180))) / 2)
        $iY = $iCentreY + (($iHeight + Abs($iWidth * Sin($iAngle * $iPI / 180))) / 2)
    EndIf
    $hMatrix = _GDIPlus_MatrixCreate()
    _GDIPlus_MatrixRotate($hMatrix, $iAngle, 1)
    _GDIPlus_GraphicsSetTransform($hGraphic, $hMatrix)
    $x = ($iWidth / 2) * Cos($iAngle * $iPI / 180) - ($iHeight / 2) * Sin($iAngle * $iPI / 180)
    $y = ($iWidth / 2) * Sin($iAngle * $iPI / 180) + ($iHeight / 2) * Cos($iAngle * $iPI / 180)
    $iXt = ($iX - $x) * Cos($iAngle * $iPI / 180) + ($iY - $y) * Sin($iAngle * $iPI / 180)
    $iYt = -($iX - $x) * Sin($iAngle * $iPI / 180) + ($iY - $y) * Cos($iAngle * $iPI / 180)
    $hBrush = _GDIPlus_BrushCreateSolid($iARGB)
    $tLayout = _GDIPlus_RectFCreate($iXt, $iYt, $iWidth, $iHeight)
    _GDIPlus_GraphicsDrawStringEx($hGraphic, $nText, $hFont, $tLayout, $hFormat, $hBrush)
    _GDIPlus_MatrixDispose($hMatrix)
    _GDIPlus_FontDispose($hFont)
    _GDIPlus_FontFamilyDispose($hFamily)
    _GDIPlus_StringFormatDispose($hFormat)
    _GDIPlus_BrushDispose($hBrush)
    $tLayout = ""
    Return 1
EndFunc   ;==>GDIPlus_SetAngledText

Func GDIPlus_AntiAlias($hGraphics)
    Local $aResult
    $aResult = DllCall($ghGDIPDll, "int", "GdipSetSmoothingMode", "hwnd", $hGraphics, "int", 2)
    If @error Then Return SetError(@error, @extended, False)
    Return SetError($aResult[0], 0, $aResult[0] = 0)
EndFunc   ;==>GDIPlus_AntiAlias

Enjoy

Link to comment
Share on other sites

Great! I wanted to do this, too, but it was too much work for my spare time ...

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Link to comment
Share on other sites

  • 2 months later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...