[Mono-winforms-list] MaskedTextBox.GetCharFromPosition Method

daniele_dll d.albano at gmail.com
Sat May 5 13:31:05 EDT 2007


this is my first post here, i haven't so much free time, but i read every
day all mails of this interesting mailing list :)

> Because there could be different fonts. The only solution seems to be to
call the Grapics.MeasureText method for each letter.

The fonts aren't the only problem, infact a char in a string is rendered
differently, with a different width, by a single char, so, probably, you
really need to use Grapics.MeasureText

But you can speed up it doing another kinda of calculation if the string
lenght is more than X (X must be calculated doing some benchs): you can
split the text in the middle and look for what part contains the position.

Here there is a fast example of my idea:
####### CODE #######
        private int MyGetCharIndexFromPosition(TextBox textBox, Point pt)
            // Initialize return value
            int returnValue = -1;

            // Acquire the necessary stuff for the code (graphics and
textbox content)
            Graphics g = textBox.CreateGraphics();
            string baseText = textBox.Text;

            // Check if the pointer is out of the text bounds
            float textBounds = g.MeasureString(baseText, textBox.Font
            if (pt.X + 7 > textBounds)
                return baseText.Length - 1;

            int pieceLenght = baseText.Length;
            int basePosition = 0;
            while (pieceLenght > 0)
                // Divide the lenght
                pieceLenght = pieceLenght >> 1;

                // Extract the first half of the base string
                string pieceText = baseText.Substring(0, basePosition +

                // Acquire the width
                float pieceWidth = g.MeasureString(pieceText, textBox.Font

                // Check if only a char remained
                if (pieceLenght == 1)
                    // Check what char index must be returned
                    if (pt.X + 7 /* i've added this because the text doesn't
start from the textbox left border */ <= pieceWidth)
                        returnValue = basePosition;
                        returnValue = basePosition + 1;

                    // Check on what side the code must work
                    if (pt.X + 7 <= pieceWidth)
                        // do nothing
                        // Update the basePosition
                        basePosition += pieceLenght;

            // Free memory

            // Return the value
            return returnValue;
####### CODE #######

This code is BUGGY: it doesn't select correctly the last char, i've really
short time, however this code can be used as starting point

I've tested this code ONLY with TextBox, not with MaskedTextBox, i'm saying
because i'm using the Text property of the control and in the maskedtextbox
the user doesn't see the text but the masked one

I hope this suggestion can be useful!

Best Regards,

2007/5/5, aatdark at aol.com <aatdark at aol.com >:
>  Hi
> I have written lots of nunit tests for the Function and they are all
> runnning well on MS .NET 2.0
>  No i'm proceding with step 2.
> for now i try to get the correct line with
> Line line = document.GetLineByPixel(p.Y,false);
> but the problem is: How can i get the char index from the position in
> pixels?
> I can only use the
> LineTagToCharIndex
> if i know the char index.
> Because there could be different fonts. The only solution seems to be to
> call the Grapics.MeasureText method for each letter.
> for example if the Text is:
> HiTestText
> I have to measure
> H
> Hi
> HiT
> HiTe
> ...
> But this seems to be terrible slow?
> Anyone a better solution for this ?
> Yours,
> Berni
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.ximian.com/pipermail/mono-winforms-list/attachments/20070505/f279c675/attachment.html 

More information about the Mono-winforms-list mailing list