Results 1 to 22 of 22

Thread: SetWorldTransform - TextOut apis ... 3D text Rotation ?

  1. #1

    Thread Starter
    Fanatic Member
    Join Date
    Nov 2013
    Posts
    658

    SetWorldTransform - TextOut apis ... 3D text Rotation ?

    Hi,

    I use SetWorldTransform to rotate a text string onto a DC but when TextingOut the string, the rotation axis is always at the start of the string.

    I would like to have the rotation axis set at the middle of the string.

    Does anybody know how to set the location of the rotation axis ?

    Code:
    Call SetWorldTransform(hDC, XForm)
    Call TextOut(hDC, 0, 0, sText, Len(sText))
    Changing the value of the TextOut X,Y arguments doesn' work.

    Thanks.

  2. #2
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: SetWorldTransform - TextOut apis ... 3D text Rotation ?

    I think you'll have to bump the origin by -1/2 of the text width and height.

  3. #3

    Thread Starter
    Fanatic Member
    Join Date
    Nov 2013
    Posts
    658

    Re: SetWorldTransform - TextOut apis ... 3D text Rotation ?

    Quote Originally Posted by dilettante View Post
    I think you'll have to bump the origin by -1/2 of the text width and height.

    I have tried this (and other combinations) before calling TextOut but, it still doesn't shift the rotation axis to the center of the rotating text.
    Code:
    Dim p As POINTAPI
    
    Call GetViewportOrgEx(hDc, p)
    Call GetWindowOrgEx(hDc, p)
    Call SetWindowOrgEx(hDc, p.x + TextWidth / 2, p.y + TextHeight / 2, 0)
    Call SetViewportOrgEx(hDc, p.x + TextWidth / 2, p.y + TextHeight / 2, 0)

  4. #4
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: SetWorldTransform - TextOut apis ... 3D text Rotation ?

    Maybe I should have said translation, via the eDx and eDy members of XFORM.

  5. #5
    Hyperactive Member
    Join Date
    Dec 2008
    Location
    Argentina
    Posts
    439

    Re: SetWorldTransform - TextOut apis ... 3D text Rotation ?

    many apis that i didn't know, this seems to work fine
    https://stackoverflow.com/questions/...worldtransform

    Code:
    Option Explicit
    Private Declare Function SetWorldTransform Lib "gdi32.dll" (ByVal hdc As Long, ByRef lpXform As XFORM) As Long
    Private Type XFORM
        eM11 As Single
        eM12 As Single
        eM21 As Single
        eM22 As Single
        eDx As Single
        eDy As Single
    End Type
    Private Declare Function DrawText Lib "user32.dll" Alias "DrawTextA" (ByVal hdc As Long, ByVal lpStr As String, ByVal nCount As Long, ByRef lpRect As RECT, ByVal wFormat As Long) As Long
    Private Declare Function TextOut Lib "gdi32.dll" Alias "TextOutA" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, ByVal lpString As String, ByVal nCount As Long) As Long
    Private Declare Function SetGraphicsMode Lib "gdi32.dll" (ByVal hdc As Long, ByVal iMode As Long) As Long
    Private Declare Function SetMapMode Lib "gdi32.dll" (ByVal hdc As Long, ByVal nMapMode As Long) As Long
    Private Declare Function SetWindowExtEx Lib "gdi32.dll" (ByVal hdc As Long, ByVal nX As Long, ByVal nY As Long, ByRef lpSize As Any) As Long
    Private Declare Function SetViewportExtEx Lib "gdi32.dll" (ByVal hdc As Long, ByVal nX As Long, ByVal nY As Long, ByRef lpSize As Any) As Long
    Private Declare Function MoveToEx Lib "gdi32.dll" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, ByRef lpPoint As Any) As Long
    Private Declare Function LineTo Lib "gdi32.dll" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long) As Long
    Private Const DT_CALCRECT As Long = &H400
    Private Const DT_TOP As Long = &H0
    Private Const DT_CENTER As Long = &H1
    
    Private Const GM_ADVANCED As Long = 2
    Private Const MM_ISOTROPIC As Long = 7
    
    Private Type RECT
        Left As Long
        Top As Long
        Right As Long
        Bottom As Long
    End Type
    Const PI = 3.14
    
    Private Sub Form_Load()
        Me.AutoRedraw = True
        Dim RECT As RECT
        Dim XFORM As XFORM
        Dim DC As Long
        Dim Text As String
        Dim rotation As Single
        Dim radians As Single
        Dim x, y
        Dim Width As Long, Height As Long
        x = 100
        y = 50
        Text = "HOLA MUNDO"
        DC = Me.hdc
        rotation = 40
        
        Call SetGraphicsMode(DC, GM_ADVANCED)
        Call SetMapMode(DC, MM_ISOTROPIC)
        Call SetWindowExtEx(DC, 1000, 1000, 0&)
        Call SetViewportExtEx(DC, 1000, 1000, 0&)
        
        radians = rotation * PI / 180
        
        XFORM.eM11 = Cos(radians)
        XFORM.eM12 = Sin(radians)
        XFORM.eM21 = -XFORM.eM12
        XFORM.eM22 = XFORM.eM11
        XFORM.eDx = x
        XFORM.eDy = y
        Call SetWorldTransform(DC, XFORM)
        
    
        Call DrawText(DC, Text, -1, RECT, DT_CALCRECT)
        
        Width = RECT.Right - RECT.Left
        Height = RECT.Bottom - RECT.Top
        
        RECT.Left = x - Width / 2
        RECT.Right = RECT.Left + Width
        RECT.Top = y - Height / 2
        RECT.Bottom = RECT.Top + Height
        'Call DrawText(DC, Text, -1, RECT, DT_TOP Or DT_CENTER)
        Call TextOut(DC, x - Width / 2, y - Height / 2, Text, Len(Text))
    End Sub
    leandroascierto.com Visual Basic 6 projects

  6. #6

    Thread Starter
    Fanatic Member
    Join Date
    Nov 2013
    Posts
    658

    Re: SetWorldTransform - TextOut apis ... 3D text Rotation ?

    Quote Originally Posted by dilettante View Post
    Maybe I should have said translation, via the eDx and eDy members of XFORM.
    Setting eDx and eDy only affects the start position of the output string NOT the rotation axis.

    Thanks.

  7. #7

    Thread Starter
    Fanatic Member
    Join Date
    Nov 2013
    Posts
    658

    Re: SetWorldTransform - TextOut apis ... 3D text Rotation ?

    Quote Originally Posted by LeandroA View Post
    many apis that i didn't know, this seems to work fine
    https://stackoverflow.com/questions/...worldtransform

    Code:
    Option Explicit
    Private Declare Function SetWorldTransform Lib "gdi32.dll" (ByVal hdc As Long, ByRef lpXform As XFORM) As Long
    Private Type XFORM
        eM11 As Single
        eM12 As Single
        eM21 As Single
        eM22 As Single
        eDx As Single
        eDy As Single
    End Type
    Private Declare Function DrawText Lib "user32.dll" Alias "DrawTextA" (ByVal hdc As Long, ByVal lpStr As String, ByVal nCount As Long, ByRef lpRect As RECT, ByVal wFormat As Long) As Long
    Private Declare Function TextOut Lib "gdi32.dll" Alias "TextOutA" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, ByVal lpString As String, ByVal nCount As Long) As Long
    Private Declare Function SetGraphicsMode Lib "gdi32.dll" (ByVal hdc As Long, ByVal iMode As Long) As Long
    Private Declare Function SetMapMode Lib "gdi32.dll" (ByVal hdc As Long, ByVal nMapMode As Long) As Long
    Private Declare Function SetWindowExtEx Lib "gdi32.dll" (ByVal hdc As Long, ByVal nX As Long, ByVal nY As Long, ByRef lpSize As Any) As Long
    Private Declare Function SetViewportExtEx Lib "gdi32.dll" (ByVal hdc As Long, ByVal nX As Long, ByVal nY As Long, ByRef lpSize As Any) As Long
    Private Declare Function MoveToEx Lib "gdi32.dll" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, ByRef lpPoint As Any) As Long
    Private Declare Function LineTo Lib "gdi32.dll" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long) As Long
    Private Const DT_CALCRECT As Long = &H400
    Private Const DT_TOP As Long = &H0
    Private Const DT_CENTER As Long = &H1
    
    Private Const GM_ADVANCED As Long = 2
    Private Const MM_ISOTROPIC As Long = 7
    
    Private Type RECT
        Left As Long
        Top As Long
        Right As Long
        Bottom As Long
    End Type
    Const PI = 3.14
    
    Private Sub Form_Load()
        Me.AutoRedraw = True
        Dim RECT As RECT
        Dim XFORM As XFORM
        Dim DC As Long
        Dim Text As String
        Dim rotation As Single
        Dim radians As Single
        Dim x, y
        Dim Width As Long, Height As Long
        x = 100
        y = 50
        Text = "HOLA MUNDO"
        DC = Me.hdc
        rotation = 40
        
        Call SetGraphicsMode(DC, GM_ADVANCED)
        Call SetMapMode(DC, MM_ISOTROPIC)
        Call SetWindowExtEx(DC, 1000, 1000, 0&)
        Call SetViewportExtEx(DC, 1000, 1000, 0&)
        
        radians = rotation * PI / 180
        
        XFORM.eM11 = Cos(radians)
        XFORM.eM12 = Sin(radians)
        XFORM.eM21 = -XFORM.eM12
        XFORM.eM22 = XFORM.eM11
        XFORM.eDx = x
        XFORM.eDy = y
        Call SetWorldTransform(DC, XFORM)
        
    
        Call DrawText(DC, Text, -1, RECT, DT_CALCRECT)
        
        Width = RECT.Right - RECT.Left
        Height = RECT.Bottom - RECT.Top
        
        RECT.Left = x - Width / 2
        RECT.Right = RECT.Left + Width
        RECT.Top = y - Height / 2
        RECT.Bottom = RECT.Top + Height
        'Call DrawText(DC, Text, -1, RECT, DT_TOP Or DT_CENTER)
        Call TextOut(DC, x - Width / 2, y - Height / 2, Text, Len(Text))
    End Sub
    I had already seen that code but it doesn't make the drawn text to rotate around itself from the center.

    Thanks.

  8. #8

    Thread Starter
    Fanatic Member
    Join Date
    Nov 2013
    Posts
    658

    Re: SetWorldTransform - TextOut apis ... 3D text Rotation ?

    As you can see from the below clip, the rotation axis is at the start of the drawn text (H letter) ... I want the axis to be at the the center of the text (somewhere before the 'W' letter) so that the text rotates around itself from the center and doesn't go outside the initial text region.


  9. #9
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: SetWorldTransform - TextOut apis ... 3D text Rotation ?

    SetWorldTransform does a 2D rotation in the XY plane, it doesn't do 3D rotations.

    What you are showing doesn't look like a Rotation but, to me, looks rather like a skew or scaling of the X axis, so you are shrinking and expanding the text in one dimension.

    I think you are going to have to emulate what you want, by offsetting the start of the text by a varying amount, e.g. multiplying the X offset of the text by the negative of 1/2 the width of the text * the Cos of the Angle, assuming you're using an angle to control the amount of skew you're inducing.
    "Anyone can do any amount of work, provided it isn't the work he is supposed to be doing at that moment" Robert Benchley, 1930

  10. #10
    Frenzied Member
    Join Date
    May 2014
    Location
    Kallithea Attikis, Greece
    Posts
    1,289

    Re: SetWorldTransform - TextOut apis ... 3D text Rotation ?

    Something like this (look attachment)? I made this with VB6, but using script in M2000, the language which I wrote in Vb6. The statement Legend perform the rendering to screen, and use a sub nPlain which you can find here https://github.com/M2000Interpreter/...n/Mod_Util.bas
    search sub nplain (current line is 2510).

    Here is the code to produce this in M2000 Environment.
    https://georgekarras.blogspot.com/2020/07/52-99.html

    Attachment 183299

  11. #11
    Addicted Member
    Join Date
    Feb 2015
    Posts
    158

    Re: SetWorldTransform - TextOut apis ... 3D text Rotation ?

    Fairly easy to do with GDI+ paths:

    Name:  gdip_text_rotate.jpg
Views: 383
Size:  16.5 KB

    Attached is a small demo project
    Look inside of the "DrawPathShape" subroutine for the meat of the code.
    Attached Files Attached Files

  12. #12

    Thread Starter
    Fanatic Member
    Join Date
    Nov 2013
    Posts
    658

    Re: SetWorldTransform - TextOut apis ... 3D text Rotation ?

    Quote Originally Posted by SomeYguy View Post
    Fairly easy to do with GDI+ paths:

    Name:  gdip_text_rotate.jpg
Views: 383
Size:  16.5 KB

    Attached is a small demo project
    Look inside of the "DrawPathShape" subroutine for the meat of the code.
    Does that do 3D ?

    Thanks

  13. #13

    Thread Starter
    Fanatic Member
    Join Date
    Nov 2013
    Posts
    658

    Re: SetWorldTransform - TextOut apis ... 3D text Rotation ?

    Quote Originally Posted by georgekar View Post
    Something like this (look attachment)? I made this with VB6, but using script in M2000, the language which I wrote in Vb6. The statement Legend perform the rendering to screen, and use a sub nPlain which you can find here https://github.com/M2000Interpreter/...n/Mod_Util.bas
    search sub nplain (current line is 2510).

    Here is the code to produce this in M2000 Environment.
    https://georgekarras.blogspot.com/2020/07/52-99.html

    Attachment 183299
    Thanks... I will take a look.

  14. #14

    Thread Starter
    Fanatic Member
    Join Date
    Nov 2013
    Posts
    658

    Re: SetWorldTransform - TextOut apis ... 3D text Rotation ?

    Quote Originally Posted by passel View Post
    SetWorldTransform does a 2D rotation in the XY plane, it doesn't do 3D rotations.

    What you are showing doesn't look like a Rotation but, to me, looks rather like a skew or scaling of the X axis, so you are shrinking and expanding the text in one dimension.

    I think you are going to have to emulate what you want, by offsetting the start of the text by a varying amount, e.g. multiplying the X offset of the text by the negative of 1/2 the width of the text * the Cos of the Angle, assuming you're using an angle to control the amount of skew you're inducing.
    You are right. the 3D rotation illusion that we see is actually squeezing the text till the text width reaches 0 then inflating its mirror image and so on.

  15. #15
    Addicted Member
    Join Date
    Feb 2015
    Posts
    158

    Re: SetWorldTransform - TextOut apis ... 3D text Rotation ?

    Quote Originally Posted by JAAFAR View Post
    Does that do 3D ?

    Thanks
    Sorry, it does not .

  16. #16

    Thread Starter
    Fanatic Member
    Join Date
    Nov 2013
    Posts
    658

    Re: SetWorldTransform - TextOut apis ... 3D text Rotation ?

    I am still unable to make a text rotate around its center in a 3D fashion... The closest I have come to is what I have in post#8.

    I have searched the web but no luck.

    Does anyone have a working code example that achieves the required result ?

  17. #17
    Frenzied Member
    Join Date
    May 2014
    Location
    Kallithea Attikis, Greece
    Posts
    1,289

    Re: SetWorldTransform - TextOut apis ... 3D text Rotation ?

    You have the code. In Post#8 you change the width say W of the text, but you hold the starting position, so you have to alter the starting position. Each problem solved by excluding some weight from it, and when the smaller problem solved then you add what you left previously.
    So for your issue, lets thing how to center a small line in one axis only. So here are the problems for you:
    1. define a line as 1/4 of width of your form and center it in the form
    2. define a sin curve which move from top to bottom, centered in the form.
    3. extracting the width from center point to current sin curve point you get the 1/2 of line (o width of text). Say this value F(t)
    So next time you move -F(t) from center scale.x/2 and print text at a size of 2*F(t)
    4. Applying a second sin function you can handle the 3d because its half can be start in a F(t)+c and end to c-F(t) (c>>F(t)). But you don't have a "rendering" function for text for put text in an irregular tetrahedron.

    You are lucky there is a way to transform an image. So first you draw the text, in a hidden picture box and then you get this code to transform it according instructions above.
    https://www.vbforums.com/showthread....ight=transform

  18. #18
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: SetWorldTransform - TextOut apis ... 3D text Rotation ?

    Quote Originally Posted by JAAFAR View Post
    You are right. the 3D rotation illusion that we see is actually squeezing the text till the text width reaches 0 then inflating its mirror image and so on.
    Since you are not using an Angle, then simply offset the Left based on the amount being squeezed and perhaps the mirroring.
    It might be easier with the SetWorldTransform you're using, but since you haven't posted example code of what you're doing that we could play with, I'm just using PaintPicture to give an example of offsetting the Left along with the squeeze.
    Just a quickly put together example, so probably not the most efficient or directly relatable.

    Just place a Timer, a Label and a Picturebox on the form, then paste in the example code and run.
    Code:
    Private maxVal As Integer
    Private curVal As Integer
    Private direction As Integer
    Private mirror As Integer
    
    Private Sub Form_Load()
      Me.ScaleMode = vbPixels
      Me.AutoRedraw = True
      With Label1
        .AutoSize = True
        .Visible = False
        .FontSize = 24
        .Caption = "This is a test"
      End With
      With Picture1
        .BorderStyle = vbBSNone
        .AutoRedraw = True
        .Visible = False
        .ScaleMode = vbPixels
        .Width = Label1.Width + 10
        .Height = Label1.Height
        .FontSize = 24
        .CurrentX = 5
        Picture1.Print Label1.Caption
      
        Timer1.Interval = 1
        maxVal = Picture1.Width \ 2
      End With
      
      curVal = 1
      direction = 1
      mirror = 1
    End Sub
    
    Private Sub Timer1_Timer()
      With Picture1
        
        If (curVal >= maxVal) Or (curVal = 0) Then
          If curVal = maxVal Then
            mirror = -mirror
          End If
          direction = -direction
          curVal = curVal + direction
        End If
        curVal = curVal + direction
        
        Me.Line (.Left, .Top)-Step(.Width, .Height), Me.BackColor, BF
        Dim dW As Integer
        dW = mirror * (.Width - curVal * 2)
        If dW = 0 Then
          dW = 1
        End If
        
        If mirror < 0 Then
          Me.PaintPicture .Image, .Left + .Width - curVal, .Top, dW, .Height
        Else
          Me.PaintPicture .Image, .Left + curVal, .Top, dW, .Height
        End If
      End With
    End Sub
    "Anyone can do any amount of work, provided it isn't the work he is supposed to be doing at that moment" Robert Benchley, 1930

  19. #19

    Thread Starter
    Fanatic Member
    Join Date
    Nov 2013
    Posts
    658

    Re: SetWorldTransform - TextOut apis ... 3D text Rotation ?

    @Passel

    Thanks for the code but I will need to see if I can somehow adapt the idea to vba as there is no PictureBox\PaintPicture in vba.

  20. #20
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,253

    Re: SetWorldTransform - TextOut apis ... 3D text Rotation ?

    To give a practical example (based on a "separate Text-Surface-Bitmap"), below is something RC6-based
    (which also explains the right order, a transform-matrix has to be influenced, before the Blitting):

    The "Text-Bitmap" (in the example below TSrf) can be a normal (hidden) PicBox with AutoReraw=True
    And the Redraw-Routine contains comments for the matching GDI-calls (and the 3 Transform-Matrix influencing lines)

    Code:
    Option Explicit
    
    Private CC As cCairoContext, TSrf As cCairoSurface, WithEvents tmrNewW As cTimer
    
    Private Sub Form_Load()
      Caption = "Resize Me"
      Set TSrf = CreateTextSurface("Some Text")
      Set tmrNewW = New_c.Timer(15, True, TSrf.Width)
    End Sub
    
    Private Sub Form_Resize()
      ScaleMode = vbPixels
      Set CC = Cairo.CreateSurface(ScaleWidth, ScaleHeight).CreateContext
      Redraw
    End Sub
    
    Private Sub Redraw()
      CC.Paint 1, Cairo.CreateCheckerPattern 'clear the background
     
      CC.Save 'SaveDC
        CC.TranslateDrawings CC.Surface.Width / 2, CC.Surface.Height / 2 'translate to the center of the form
        CC.ScaleDrawings tmrNewW.Tag / TSrf.Width + 0.001, 1 'then apply the scaling in x-Direction
        CC.TranslateDrawings -TSrf.Width / 2, -TSrf.Height / 2 'after the scaling, translate back by half the dimensions of the  Text-Surface-Bitmap
    
        CC.RenderSurfaceContent TSrf, 0, 0 'basically a Blt-Op like e.g. PaintPicture (using normal 0, 0 Offsets)
      CC.Restore 'RestoreDC
    
      CC.Surface.DrawToDC hDC 'render to the Form
    End Sub
    
    Function CreateTextSurface(S As String) As cCairoSurface 'draw the Text-String onto a separate (properly sized) Surface-Bitmap
      Dim FH As Double
      With Cairo.CreateSurface(1000, 200).CreateContext
          .SelectFont "Arial", 25
          .TextOut 0, 0, S, , , True
          .Fill , Cairo.CreateSolidPatternLng(vbRed)
          Set CreateTextSurface = .Surface.CropSurface(0, 0, .GetTextExtents(S, FH), FH)
      End With
    End Function
    
    Private Sub tmrNewW_Timer()
      Static Direction
        If tmrNewW.Tag >= TSrf.Width Then Direction = -1
        If tmrNewW.Tag <= -TSrf.Width Then Direction = 1
        tmrNewW.Tag = tmrNewW.Tag + Direction
      Redraw
    End Sub
    Olaf

  21. #21

    Thread Starter
    Fanatic Member
    Join Date
    Nov 2013
    Posts
    658

    Re: SetWorldTransform - TextOut apis ... 3D text Rotation ?

    Quote Originally Posted by Schmidt View Post
    To give a practical example (based on a "separate Text-Surface-Bitmap"), below is something RC6-based
    (which also explains the right order, a transform-matrix has to be influenced, before the Blitting):

    The "Text-Bitmap" (in the example below TSrf) can be a normal (hidden) PicBox with AutoReraw=True
    And the Redraw-Routine contains comments for the matching GDI-calls (and the 3 Transform-Matrix influencing lines)
    Olaf
    I was looking to do this without the need for external libraries (RC6.dll) but thanks for the input.

  22. #22

    Thread Starter
    Fanatic Member
    Join Date
    Nov 2013
    Posts
    658

    Re: SetWorldTransform - TextOut apis ... 3D text Rotation ?

    I seem to have managed to make the scrolling turn around the central axis by offsetting the Window and ViewPort origins.. Not the best good looking output text but close as I can't properly control the character sizes.

    Download Example



    Here is the code i came to (bas module)
    Code:
    Option Explicit
    
    Public Enum eSpeed
        Slow
        Medium
        Fast
    End Enum
    
    Private Type XFORM
        eM11 As Single
        eM12 As Single
        eM21 As Single
        eM22 As Single
        eDx As Single
        eDy As Single
    End Type
    
    Private Type Size
        cx As Long
        cy As Long
    End Type
    
    Private Declare Function IUnknown_GetWindow Lib "shlwapi" Alias "#172" (ByVal pIUnk As IUnknown, ByVal hUf As Long) As Long
    Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
    Private Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hDC As Long) As Long
    Private Declare Function SetGraphicsMode Lib "gdi32" (ByVal hDC As Long, ByVal iMode As Long) As Long
    Private Declare Function GetWorldTransform Lib "gdi32" (ByVal hDC As Long, lpXform As XFORM) As Long
    Private Declare Function SetWorldTransform Lib "gdi32" (ByVal hDC As Long, lpXform As XFORM) As Long
    Private Declare Function SetViewportOrgEx Lib "gdi32" (ByVal hDC As Long, ByVal nX As Long, ByVal nY As Long, ByVal lpPoint As Long) As Long
    Private Declare Function SetWindowOrgEx Lib "gdi32" (ByVal hDC As Long, ByVal nX As Long, ByVal nY As Long, ByVal lpPoint As Long) As Long
    Private Declare Function SetBkMode Lib "gdi32" (ByVal hDC As Long, ByVal nBkMode As Long) As Long
    Private Declare Function TextOut Lib "gdi32" Alias "TextOutA" (ByVal hDC As Long, ByVal X As Long, ByVal Y As Long, ByVal lpString As String, ByVal nCount As Long) As Long
    Private Declare Function InvalidateRect Lib "user32" (ByVal hwnd As Long, ByVal lpRect As Long, ByVal bErase As Long) As Long
    Private Declare Function GetTextExtentPoint32 Lib "gdi32" Alias "GetTextExtentPoint32A" (ByVal hDC As Long, ByVal lpsz As String, ByVal cbString As Long, lpSize As Size) As Long
    Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
            
    Private bStop As Boolean, bRotating As Boolean
    
    
    
    Public Sub RotatetText( _
        ByVal oForm As Object, _
        ByVal sText As String, _
        ByVal CharWidth As Single, _
        ByVal CharHeight As Single, _
        ByVal X As Single, _
        ByVal Y As Single, _
        ByVal Speed As eSpeed, _
        Optional ByVal Horz As Boolean = True)
        
        Dim hwnd As Long, hDC As Long
        Dim XYOffset As Single
        Dim CharWidthOrHeight As Single
        Dim W As Single, H As Single
        Dim eSpd As eSpeed
     
        Call IUnknown_GetWindow(oForm, VarPtr(hwnd))
        hDC = GetDC(hwnd)
        W = CharWidth: H = CharHeight
        eSpd = Switch(Speed = Slow, 200, Speed = Medium, 80, Speed = Fast, 20)
        bStop = False
    
        If bRotating Then
            bRotating = False
            GoTo ExitCurrentRotation
        End If
        
    NextRotation:
    
        Do
        
            bRotating = True
            
            If Horz Then
                CharWidthOrHeight = CharWidth
            Else
                CharWidthOrHeight = CharHeight
            End If
            
            XYOffset = CharWidthOrHeight
            Do While XYOffset > 0
                XYOffset = XYOffset - 0.5
                DoEvents
                Call Rotate(hDC, sText, IIf(Horz, XYOffset, CharWidth), IIf(Horz, CharHeight, XYOffset), X, Y, W, H)
                If bStop Then GoTo GetOut
                Call Sleep(eSpd)
                oForm.Repaint
            Loop
            
            Do While XYOffset < CharWidthOrHeight
                XYOffset = XYOffset + 0.5
                DoEvents
                Call Rotate(hDC, sText, IIf(Horz, -XYOffset, CharWidth), IIf(Horz, CharHeight, -XYOffset), X, Y, W, H)
                If bStop Then GoTo GetOut
                Call Sleep(eSpd)
                oForm.Repaint
            Loop
            
            Do While XYOffset > 0
                XYOffset = XYOffset - 0.5
                DoEvents
                Call Rotate(hDC, sText, IIf(Horz, -XYOffset, CharWidth), IIf(Horz, CharHeight, -XYOffset), X, Y, W, H)
                If bStop Then GoTo GetOut
                Call Sleep(eSpd)
                oForm.Repaint
            Loop
            
            Do While XYOffset < CharWidthOrHeight
                XYOffset = XYOffset + 0.5
                DoEvents
                Call Rotate(hDC, sText, IIf(Horz, XYOffset, CharWidth), IIf(Horz, CharHeight, XYOffset), X, Y, W, H)
                If bStop Then GoTo GetOut
                Call Sleep(eSpd)
                oForm.Repaint
            Loop
            
            If bStop Then Exit Do
        
        Loop Until bStop
    
    ExitCurrentRotation:
        GoTo NextRotation
    
    GetOut:
    
        Call InvalidateRect(hwnd, 0, 0)
        Call ReleaseDC(hwnd, hDC)
    
    End Sub
    
    Public Sub StopRotation()
        bStop = True
    End Sub
    
    
        Private Sub Rotate( _
            ByVal hDC As Long, _
            ByVal sText As String, _
            ByVal eM11 As Single, _
            ByVal eM22 As Single, _
            ByVal eDx As Single, _
            ByVal eDy As Single, _
            ByVal W As Single, _
            ByVal H As Single)
    
        Dim lpXform As XFORM
        Dim tTextSize As Size
        Dim lPrevGM As Long
        
        Call SetBkMode(hDC, 1)
        lPrevGM = SetGraphicsMode(hDC, 2)
        Call GetWorldTransform(hDC, lpXform)
    
        With lpXform
            .eM11 = eM11
            .eM12 = 0.001
            .eM21 = 0.001
            .eM22 = eM22
            .eDx = eDx
            .eDy = eDy
            If SetWorldTransform(hDC, lpXform) Then
                Call GetTextExtentPoint32(hDC, sText, Len(sText), tTextSize)
                Call SetWindowOrgEx(hDC, (.eM11 * tTextSize.cx / 2), .eM22 * tTextSize.cy / 2, 0)
                Call SetViewportOrgEx(hDC, (W / 2) * tTextSize.cx, (H / 2) * tTextSize.cy, 0)
                Call TextOut(hDC, 0, 0, sText, Len(sText))
            End If
        End With
        
        Call SetGraphicsMode(hDC, lPrevGM)
    
    End Sub

    Code Usage example in Form Module:
    Code:
    Private Sub btn_Horz_Click()
        RotatetText Me, "Hello World", 4, 8, 50, 50, Medium, True
    End Sub
    
    Private Sub btn_Vert_Click()
        RotatetText Me, "Hello World", 4, 8, 50, 50, Medium, False
    End Sub
    
    Private Sub btnStop_Click()
        Call StopRotation
    End Sub

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width