Solved

Drawing Text within a Circle in VB.NET

Posted on 2004-08-24
15
1,398 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
  • 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
 
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
What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

 
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 500 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

What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

Join & Write a Comment

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…
Parsing a CSV file is a task that we are confronted with regularly, and although there are a vast number of means to do this, as a newbie, the field can be confusing and the tools can seem complex. A simple solution to parsing a customized CSV fi…
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.

747 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

Need Help in Real-Time?

Connect with top rated Experts

9 Experts available now in Live!

Get 1:1 Help Now