?
Solved

Drawing Text within a Circle in VB.NET

Posted on 2004-08-24
15
Medium Priority
?
1,608 Views
Last Modified: 2008-01-09
I've found an example of placing Text within a Rectangle (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/_gdiplus_the_state_of_a_graphics_object_usecsharp.asp)

However I need to place text within a Circle and also a polygon shape. I've tried to find examples using the eclipse but no luck yet.

To be clear I need the text to auto-wrap within the circle not just clip it off. I've been able to create a clipping region but not the wrapping effect I need within a circle.

0
Comment
Question by:brian2k1
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 4
  • 4
15 Comments
 
LVL 96

Expert Comment

by:Bob Learned
ID: 11891323
I have figured out one way of wrapping the text, but it is not an elegant solution, but it worked for me.  I needed to put multi-line text into a diamond shape.  The direction I took was to break the shape up into a series of rectangles that have coordinates calculated from the slope of the edges, with each one the heighth of the measured text.

Bob
0
 
LVL 25

Expert Comment

by:RonaldBiemans
ID: 11891564
In don't think setclip will work for this because it makes the underlying graphic only draw within the clip area but it will start outside of it using the original region (does this make sense).

This will draw and wrap text within the boundaries of a elipse (or circle) (in this case I use a panel to draw on)

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim g As Graphics
        g = Panel1.CreateGraphics
        Dim myrect As New RectangleF(0, 0, 100, 100)
        Dim w As Single = CSng(((myrect.Width / 2) * Math.Cos(135 * (Math.PI / 180))) + (myrect.Width / 2))
        Dim myrect2 As New RectangleF(w, w, myrect.Width - w,myrect.Height  - w)

        g.DrawEllipse(New Pen(Color.Black), myrect)
        g.DrawString("bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla", Me.Font, New SolidBrush(Color.Black), myrect2)
    End Sub



0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 11892052
See, I told you that it wasn't the best way :)  I never pretend to be the graphics expert, but I am trying to learn.

Bob
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 1

Author Comment

by:brian2k1
ID: 11894027
That works to some degree however when I change the eclipse to 475x475 (CD size) the text is off to the right a little bit and is in a rectangle shape instead of the circle.
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 11894041
I got totally psyched out, and thought that Ronald suggested was going to work, since it usually does :)

Bob
0
 
LVL 25

Expert Comment

by:RonaldBiemans
ID: 11894169
Sorry to let you down TheLearnedOne ;-).

And sorry Brian2k1, I though that was what you wanted, it is indeed in a rectangle since drawstring only excepts a rectangle or a point. About the slightly to the right that has probably to do with the single instead of a double.

I will have a look and see if I can make it to fill the whole circle (not much hope though without splitting the string)





0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 11894186
No problem, I just struggled with a solution, and to find out that it could have been that easy--it was inticing :)

Bob
0
 
LVL 25

Expert Comment

by:RonaldBiemans
ID: 11901015
Hi Brian2k,

I'm almost there, I think :-)  just a question.

The method I've been working on starts at the top of the circle and goes down from there, so if there is little text it will all be at the top of the circle, is that a problem ?
0
 
LVL 1

Author Comment

by:brian2k1
ID: 11904059
no that will work. :-)
0
 
LVL 25

Expert Comment

by:RonaldBiemans
ID: 11904229
Ok, I'll have it finished tomorrow morning (Going home now).
Bye the way I think I'm able to make you choose if you want to start at the top, center or bottom.



0
 
LVL 25

Accepted Solution

by:
RonaldBiemans earned 2000 total points
ID: 11912373
Hi Brian2k1,

try this, the code still needs some tweaking (error handling etc.. I'll leave that up to you) but I think it will do what you want, I haven't build in the option of the location (I have to work on my own projects aswell ;-))

Let me know if it works

   Public Class MyFillCircle
        Public Myfont As Font
        Public MyString As String
        Private Points As New ArrayList
        Private myArray() As String

        Sub New(ByVal Str As String, ByVal f As Font)
            Myfont = f
            MyString = Str
        End Sub

        Public Sub FillCircle(ByVal e As PaintEventArgs)
            Dim myrect As New RectangleF(0, 0, 475, 475)
            myArray = Split(MyString)
            Dim ht As SizeF = e.Graphics.MeasureString(MyString, Myfont)
            Dim n As Integer = CInt(((myrect.Width / 2) / ht.Height))
            Dim nt As Integer = (n * 2) - 1
            For x As Single = n To 1 Step -1
                Points.Add(New RectangleF((myrect.Width / 2) * (1 - Math.Cos(Math.Asin(((x - 0.5) * ht.Height) / (myrect.Width / 2)))), _
                (myrect.Width / 2) - ((x - 0.5) * ht.Height), _
                myrect.Width * Math.Cos(Math.Asin((((x) - 0.5) * ht.Height) / (myrect.Width / 2))), _
                ht.Height))
            Next
            For x As Single = n - 2 To 0 Step -1
                Points.Add(New RectangleF(CType(Points(x), RectangleF).X, myrect.Height - CType(Points(x), RectangleF).Y - ht.Height, CType(Points(x), RectangleF).Width, ht.Height))
            Next
            e.Graphics.DrawEllipse(New Pen(Color.Black), myrect)
            Dim StringsToPrint As New ArrayList
            Dim PRSTR As String = ""
            Dim PRSTR2 As String = ""
            Dim IPoint As Integer = nt - 1
            For x As Integer = 0 To myArray.GetUpperBound(0)
                PRSTR += myArray(x) & " "
                If e.Graphics.MeasureString(PRSTR, Myfont).Width <= CType(Points(IPoint), RectangleF).Width Then
                    PRSTR2 = PRSTR
                Else
                    PRSTR2 = PRSTR2.TrimEnd
                    StringsToPrint.Add(PRSTR2)
                    PRSTR = ""
                    IPoint -= 1
                    If IPoint < 0 Then
                        Exit Sub
                    End If
                End If
            Next
            If PRSTR <> "" Then
                StringsToPrint.Add(PRSTR2)
            End If
            For y As Integer = 0 To StringsToPrint.Count - 1
                Dim ff As Single
                Dim ww As SizeF
                ww = e.Graphics.MeasureString(StringsToPrint(y), Myfont)
                ff = ((CType(Points(y), RectangleF).Width - ww.Width) / 2)
                Points(y) = New RectangleF(ff + CType(Points(y), RectangleF).X, CType(Points(y), RectangleF).Y, CType(Points(y), RectangleF).Width, CType(Points(y), RectangleF).Height)
                e.Graphics.DrawString(StringsToPrint(y), Myfont, New SolidBrush(Color.Black), Points(y))
            Next
        End Sub

    End Class

call like

    Dim f As MyFillCircle

    Dim b As Boolean = False



    Private Sub Panel1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Panel1.Paint
        If b Then
            f.FillCircle(e)
        End If
    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        f = New MyFillCircle(TextBox1.Text, Me.Font)
        b = True
        Panel1.Invalidate()
    End Sub
0
 
LVL 1

Author Comment

by:brian2k1
ID: 11914995
Ronald,

I'm not sure if it works exactly yet but I'm giving you the points anyway for effort ;-)

I'll follow up in this message with any changes should they be required.

Thanks a ton for your effort it has helped me understand the GDI better.
0
 
LVL 25

Expert Comment

by:RonaldBiemans
ID: 11915105
Well if you do experience problems let me know and we will figure it out. One thing though to keep in mind is I use
myArray = Split(MyString) (which splits the string on spaces which means no CRLF are allowed in the string)


TheLearnedOne, am I back in your grace yet ?

0
 
LVL 1

Author Comment

by:brian2k1
ID: 11915142
you were never out of it. you the man!
0
 
LVL 25

Expert Comment

by:RonaldBiemans
ID: 11915263
Thanks Brian2k1, Let me know how you are getting along with your project.

another note, I put in this piece of code to center the string if it is too short to fill the complete rectangle if you don't want that
              Dim ff As Single
                Dim ww As SizeF
                ww = e.Graphics.MeasureString(StringsToPrint(y), Myfont)
                ff = ((CType(Points(y), RectangleF).Width - ww.Width) / 2)
                Points(y) = New RectangleF(ff + CType(Points(y), RectangleF).X, CType(Points(y), RectangleF).Y, CType(Points(y), RectangleF).Width, CType(Points(y), RectangleF).Height)
                e.Graphics.DrawString(StringsToPrint(y), Myfont, New SolidBrush(Color.Black), Points(y))

use just this part

                e.Graphics.DrawString(StringsToPrint(y), Myfont, New SolidBrush(Color.Black), Points(y))
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Article by: jpaulino
XML Literals are a great way to handle XML files and the community doesn’t use it as much as it should.  An XML Literal is like a String (http://msdn.microsoft.com/en-us/library/system.string.aspx) Literal, only instead of starting and ending with w…
Since .Net 2.0, Visual Basic has made it easy to create a splash screen and set it via the "Splash Screen" drop down in the Project Properties.  A splash screen set in this manner is automatically created, displayed and closed by the framework itsel…
Visualize your data even better in Access queries. Given a date and a value, this lesson shows how to compare that value with the previous value, calculate the difference, and display a circle if the value is the same, an up triangle if it increased…
In this video, Percona Solutions Engineer Barrett Chambers discusses some of the basic syntax differences between MySQL and MongoDB. To learn more check out our webinar on MongoDB administration for MySQL DBA: https://www.percona.com/resources/we…
Suggested Courses

765 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question