简体   繁体   中英

Basic TextBox from Scratch

I thought I'd take a stab at my own simple TextBox Control. I'm not quite sure how they're written, but I took a look at the Reference Source for the Windows Forms TextBox, and it's just added a whole lot more questions so I thought I would ask my own questions which are based on how I think a TextBox Control is made:

How are characters/text drawn? Since I'll be creating the TextBox from scratch, I'll obviously need to draw. So knowing that when you draw something in WinForms, you can't just select that text, you need to handle the MouseDown and MouseMove events, get the Location where the mouse is being pressed down, and then determine which, if any, character is at that location. But we can't really do that unless we've saved that character somewhere along with its coordinates. Which means we'll probably need to use a list to store everything that the user types:

List<Character> characters = new List<Character>();

class Character
{
    public string Text { get; set; }
    public Location { get; set; }
    public Size { get; set; }
}

Now that we've got the location of that character, we'll need to draw a filled rectangle so the user knows what they're selecting. We can do that by getting the Size and Location of the character at the coordinates we've determined previously.

Is this basically how a TextBox works?

1) When user types something, we use DrawString to draw what was "typed" and then store its Size and Location in a List for future reference? 2) When the user "selects" text, we lookup the coordinates the user "selected" in the List and then draw a filled rectangle at that Location?

I did write my own WinForms TextBox (in order to satisfy a need for spell checking during data entry, and highlighting of incorrect spellings via font underlines and colours). During my investigation for this I found that .net didn't carry out the text box rendering itself (it is a Windows facility) so had to invent it all from scratch.

My approach was very similar to yours but the important point to remember is that no one data structure is sufficient to store everything about a text box. Specifically a text box should have collections for the following;

  1. The list of characters.
  2. TextRuns which are indexes into that list of characters for all characters which share the same presentation - ie Font, Color etc. There will typically be fewer TextRuns than Characters.
  3. One Highlight TextRun to record the characters currently highlighted by the user
  4. Carat Position - this can be tricky. A textbox carat can be before the first character or after the last character, or any character in between.
  5. An Image of the last painted textbox - like a buffer, so that OnPaint messages can be quickly satisified without repeated MeasureString and DrawString calls. This can be typically larger than the renderable area of the TextBox in the case of multi-line or scrollable boxes, in which case you render a Rectangle subset on request.
  6. A list of RenderRuns which represent the position and size of a set of characters, all of which are in the same TextRun, and are painted on the same text box line, and is the basic unit of painting. A RenderRun will have offset position within the Image and a Size which enables you to select the correct RenderRun for any given position in the Image. Subsequent selection of a specific character would require a MeasureString for each character in the RenderRun. you can choose to store the character sizing in the RenderRun or dynamically calculate it each time you need it.

A consequence of all this was

  • The custom text box was notably slower than the Windows native equivalent
  • It took a lot more memory

So we only used it on those fields where spell checking was required.

Ultimately I would advise against attempting it, because although it is possible the overall "feel" was that it wasn't a native Windows textbox and it behaved very subtly differently (not least of which in the way it scrolled - by pixel rather than by line).

Hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM