Find drawn characters under the mouse in C#

[drawn characters]

The following examples find the positions of drawn characters in a string that is drawn by using the Graphics object’s DrawString method.

This example does the opposite: it finds the drawn characters at given positions.

The program uses the following variables to keep track of the text and the positions of the drawn characters.

// The text.
private string TheText =
    "When in the course of human events it " +
    "becomes necessary for the quick brown " +
    "fox to jump over the lazy dog...";

// The character locations.
private List<RectangleF> TheRects;

When it starts, the program uses the following code to draw its text.

// Draw the text.
private void Form1_Load(object sender, EventArgs e)
{
    // Make a Bitmap to hold the text.
    Bitmap bm = new Bitmap(
        picText.ClientSize.Width,
        picText.ClientSize.Height);
    using (Graphics gr = Graphics.FromImage(bm))
    {
        gr.Clear(Color.White);

        // Don't use TextRenderingHint.AntiAliasGridFit.
        gr.TextRenderingHint = TextRenderingHint.AntiAlias;

        // Make a font to use.
        using (Font font = new Font("Times New Roman", 16, FontStyle.Regular))
        {
            // Draw the text.
            gr.DrawString(TheText, font, Brushes.Blue, 4, 4);

            // Measure the characters.
            TheRects = MeasureCharacters(gr, font, TheText);
        }
    }

    // Display the result.
    picText.Image = bm;
}

This code creates a bitmap and draws the text on it. It also calls the MeasureCharacters method described in the post Measure character positions when drawing long strings in C# to find the locations of the drawn characters. It finishes by displaying the bitmap on the picText PictureBox control

When the mouse moves over the picText control, the following event handler executes.

private void picText_MouseMove(object sender, MouseEventArgs e)
{
    // See if the mouse is over one of the character rectangles.
    string new_text = "";
    for (int i = 0; i < TheText.Length; i++)
    {
        if (TheRects[i].Contains(e.Location))
        {
            new_text =
                "Character " + i.ToString() + ": " + TheText[i];
            break;
        }
    }
    if (lblChar.Text != new_text) lblChar.Text = new_text;
}

This code loops through the TheRects list checking the rectangles that contain the drawn characters to see if any contains the mouse’s position. If the mouse position lies inside one of the rectangles, the program displays the index and value of the corresponding character.

See the earlier posts and download the example to see additional details.

Unfortunately this method doesn’t work for strings drawn in more complex ways. For example, if you use a formatting rectangle and a StringFormat object to draw wrapped text with ellipses, then the string measuring methods won’t work. In that case you might want to display the text in a TextBox or RichTextBox control and use a TextRenderer object to measure character positions.


Download Example   Follow me on Twitter   RSS feed   Donate




About RodStephens

Rod Stephens is a software consultant and author who has written more than 30 books and 250 magazine articles covering C#, Visual Basic, Visual Basic for Applications, Delphi, and Java.
This entry was posted in algorithms, drawing, fonts, graphics, strings and tagged , , , , , , , , , , , , , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.