# Selections and Caret Position

> Select and replace text in a Windows Forms TextControl with Selection and InputPosition, track the caret and find the line and character under the mouse.

- **Product:** TX Text Control .NET for Windows Forms
- **Section:** Documentation
- **Kind:** Topic
- **Path:** TX Text Control .NET for Windows Forms > Document Editor > Editing Text > Selections and Caret Position
- **5408 words**
- **Web URL:** https://docs.textcontrol.com/tx-text-control-dotnet-winforms/document-editor/editing-text/selections/
- **LLMs URL:** https://docs.textcontrol.com/tx-text-control-dotnet-winforms/document-editor/editing-text/selections/llms.txt
- **LLMs-Full URL:** https://docs.textcontrol.com/tx-text-control-dotnet-winforms/document-editor/editing-text/selections/llms-full.txt

---

Every change a user or your code makes in a `TextControl` happens at the input position or in the selection. The caret marks the input position, and a selection is the highlighted range of text that the next command acts on. Your code reads both to find out where the user is working, and sets both to insert, replace or format text at a known place.

The examples extend the form of [Create Your First Windows Forms Application](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/getting-started/document-editor/first-application/llms-full.txt), whose editor is named `textControl1`. Formatting the selected text is covered on [Text and Paragraph Formatting](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/document-editor/formatting/llms-full.txt).

### Text Positions and the Input Position

A text position is the index of a character in the text, counted from 0. Position 0 lies in front of the first character, so a selection that starts at 18 and has a length of 4 covers the 19th to the 22nd character. The same numbers are used by [Select](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/textcontrol/select-method/llms-full.txt), by the [Selection](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/selection/llms-full.txt) class and by [Find](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/textcontrol/find-method/llms-full.txt).

The *input position* is where typed text appears. When nothing is selected, the selection has a length of 0 and its start is the input position. As soon as the user selects text, the selection has a start and a length, and typing replaces the selected text.

Two properties of the `TextControl` give access to both:

- [Selection](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/textcontrol/selection-property/llms-full.txt) returns a `Selection` object for the current selection, and accepts a new one.
- [InputPosition](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/textcontrol/inputposition-property/llms-full.txt) returns an [InputPosition](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/inputposition/llms-full.txt) object with the page, line and column of the caret, and accepts a new one to move the caret.

Both work in the text part that has the input focus: the main text, a text frame, or a header or footer. When the user edits a header, `Selection` refers to the header text.

### Select Text With the Mouse and Keyboard

The editor selects text without any code. The following mouse actions are built in:

| Mouse action | Result |
|---|---|
| Click | Moves the caret to the point of the click, or selects an image or a text frame |
| Click and drag | Selects the text between the point where the button is pressed and the point where it is released |
| Shift+click | Extends the selection to the point of the click |
| Double-click | Selects the word |
| Double-click and drag | Extends the selection word by word |
| Triple-click | Selects the paragraph |
| Triple-click and drag | Extends the selection paragraph by paragraph |
| Click in the left or right margin | Selects the line |

In a table, a click on the top of a column selects the column, a click in the margin next to a row selects the row, and a double-click selects the cell. With the keyboard, any key that moves the caret extends the selection when Shift is held down, for example Shift+Right Arrow or Ctrl+Shift+End. [Keyboard Shortcuts](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/document-editor/editing-text/keyboard-shortcuts/llms-full.txt) lists all keys.

### Select and Replace Text in Code

[Select](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/textcontrol/select-method/llms-full.txt) takes a start position and a number of characters. [SelectAll](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/textcontrol/selectall-method/llms-full.txt) selects the whole text, and [SelectWord](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/textcontrol/selectword-method/llms-full.txt) the word at the input position. Afterward, [Selection.Text](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/selection/text-property/llms-full.txt) returns the selected text, and setting it replaces the selection.

The following code in *Form1.cs* writes a sentence into the editor when the form opens, reads and replaces the order number and formats the first word:

```csharp
using System;
using System.Windows.Forms;
using TXTextControl;

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        Load += Form1_Load;
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        textControl1.Text = "Invoice for order 1234. Thank you for your order.";

        // Select the four characters "1234", which start at text position 18
        textControl1.Select(18, 4);
        string orderNumber = textControl1.Selection.Text;

        // Replace the selected text
        textControl1.Selection.Text = "5678";

        // Format "Invoice" with a prepared Selection object
        Selection title = new Selection(0, 7);
        title.Bold = true;
        title.Italic = true;
        textControl1.Selection = title;

        // Move the input position to the start of the text
        textControl1.InputPosition = new InputPosition(0);
        textControl1.Focus();
    }
}
```

Keep the `namespace` that Visual Studio created around the class. When the form opens, it shows "*Invoice* for order 5678. Thank you for your order." with "Invoice" in bold italics and the caret in front of it.

The code works as follows:

- `Text`, which `TextControl` inherits from the Windows Forms `Control` class, replaces the whole content with plain text.
- `Select(18, 4)` selects "1234", and `Selection.Text` reads it and then replaces it with "5678".
- `new Selection(0, 7)` creates a [Selection](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/selection/constructor/llms-full.txt) object for the first seven characters. Its properties, such as [Bold](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/selection/bold-property/llms-full.txt), are applied to that range when the object is assigned to `textControl1.Selection`.
- [new InputPosition(0)](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/inputposition/constructor/llms-full.txt) places the caret in front of the first character without selecting text.

#### Prepare a Selection Object or Change the Current Selection

There are two ways to change a range of text. You can select it with `Select` and set the properties of `textControl1.Selection` one by one, or you can prepare a new `Selection` object and assign it once, as the code above does for "Invoice".

The prepared object has two advantages: the user doesn't see the text being selected, and the change counts as one step for [Undo and Redo](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/document-editor/editing-text/undo-redo/llms-full.txt), where every single property set on the current selection is a step of its own. `Selection` has a constructor without parameters, too. Set its `Text` and formatting, and the assignment inserts the formatted text at the input position.

#### Selection Properties

| Property | Contains |
|---|---|
| [Start](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/selection/start-property/llms-full.txt) | The text position where the selection begins, starting with 0. Setting it keeps the current length. |
| [Length](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/selection/length-property/llms-full.txt) | The number of selected characters. With 0, `Start` is the input position. A start of 0 and a length of `int.MaxValue` select the whole text. |
| [Text](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/selection/text-property/llms-full.txt) | The selected text as a string. Setting it replaces the selection. |

A selection that spans text with different formatting has no common value for an attribute such as bold. In that case, the property returns its default value, and [IsCommonValueSelected](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/selection/iscommonvalueselected-method/llms-full.txt) returns `false` for that attribute.

The selected text can also be exchanged as formatted text. [Selection.Save](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/selection/save-method/llms-full.txt) writes the selection to a file, a byte array or a string in a format such as HTML, RTF or DOCX, and [Selection.Load](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/selection/load-method/llms-full.txt) replaces the selection with formatted content:

```csharp
// Get the selected text as HTML
string html;
textControl1.Selection.Save(out html, StringStreamType.HTMLFormat);

// Replace the selection with formatted text
textControl1.Selection.Load("<p>Paid in <strong>full</strong></p>", StringStreamType.HTMLFormat);
```

### Read the Input Position

The [InputPositionChanged](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/textcontrol/inputpositionchanged-event/llms-full.txt) event occurs whenever the caret moves, by typing, clicking or code. The following handler shows the position in the title bar of the form. Connect it in the constructor with `textControl1.InputPositionChanged += TextControl1_InputPositionChanged;`:

```csharp
private void TextControl1_InputPositionChanged(object sender, EventArgs e)
{
    InputPosition position = textControl1.InputPosition;

    Text = $"Page {position.Page}, line {position.Line}, column {position.Column}, " +
        $"text position {position.TextPosition}, selected: {textControl1.Selection.Length}";
}
```

Here, `Text` is the caption of the form. The `InputPosition` object describes the caret:

| Property | Contains |
|---|---|
| [Page](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/inputposition/page-property/llms-full.txt) | The page number, only when [ViewMode](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/textcontrol/viewmode-property/llms-full.txt) is `ViewMode.PageView` |
| [Line](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/inputposition/line-property/llms-full.txt) | The line on the page, starting with 1 |
| [Column](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/inputposition/column-property/llms-full.txt) | The column in the line, starting with 0 in front of the first character |
| [TextPosition](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/inputposition/textposition-property/llms-full.txt) | The text position, starting with 0 |
| [Section](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/inputposition/section-property/llms-full.txt) | The section, starting with 1 |

These properties are read-only. To move the caret, assign a new object. The [InputPosition constructor](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/inputposition/constructor/llms-full.txt) takes a text position, a page, a line and a column, or a point in pixels relative to the upper left corner of the control. A text position at the start or end of a field can lie inside or outside the field, and a value of [TextFieldPosition](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/textfieldposition/enumeration/llms-full.txt) decides which:

```csharp
// Move the caret to page 1, line 1, column 0
textControl1.InputPosition = new InputPosition(1, 1, 0);

// Scroll the caret to the top of the visible area
textControl1.InputPosition.ScrollTo(InputPosition.ScrollPosition.Top);
```

[ScrollTo](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/inputposition/scrollto-method/llms-full.txt) scrolls the document so that the caret is visible. Without a parameter, it chooses the position itself.

### Read Text Without Selecting It

Selecting text moves the caret and the visible selection. To read text without changing either, use the collections of the `TextControl`:

```csharp
// The paragraph at the input position
string paragraphText = textControl1.Paragraphs.GetItem(textControl1.InputPosition.TextPosition).Text;

// The first line of the document
string firstLine = textControl1.Lines[1].Text;

// The fifth character
char fifthCharacter = textControl1.TextChars[5].Char;
```

- [Paragraphs](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/textcontrol/paragraphs-property/llms-full.txt) contains the paragraphs. [GetItem](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/paragraphcollection/getitem-method/llms-full.txt) returns the paragraph at a text position, and [Text](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/paragraph/text-property/llms-full.txt) its text.
- [Lines](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/textcontrol/lines-property/llms-full.txt) contains the lines, numbered from 1.
- [TextChars](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/textcontrol/textchars-property/llms-full.txt) contains the characters, numbered from 1.

Like `Selection`, both collections belong to the text part with the input focus. A [Line](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/line/llms-full.txt) also knows its [Number](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/line/number-property/llms-full.txt), its first character in [Start](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/line/start-property/llms-full.txt) (counted from 1), its [Length](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/line/length-property/llms-full.txt) including the break character and the [Page](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/line/page-property/llms-full.txt) it is on. [Line.Save](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/line/save-method/llms-full.txt) writes the text of one line to a string or a byte array in a format such as HTML or RTF, with the same `StringStreamType` and `BinaryStreamType` values as `Selection.Save`.

### Find the Line and Character at a Point

Every line and every character has a position on the page. [Line.TextBounds](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/line/textbounds-property/llms-full.txt) is the rectangle around the text of a line, [Line.Baseline](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/line/baseline-property/llms-full.txt) the position of its baseline, and [TextChar.Bounds](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/textchar/bounds-property/llms-full.txt) the rectangle around a single character. All three are given in twips, with the origin at the upper left corner of the whole document, not of the visible part.

The other way round, [TextCharCollection.GetItem](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/textcharcollection/getitem-method/llms-full.txt) and [LineCollection.GetItem](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/linecollection/getitem-method/llms-full.txt) take a point in pixels relative to the upper left corner of the control and return the character or the line there. That is what you need to react to the character under the mouse pointer, for example to show a tooltip. The following handler shows the character and its line in the caption of the form. Connect it in the constructor with `textControl1.MouseMove += TextControl1_MouseMove;`:

```csharp
private void TextControl1_MouseMove(object sender, MouseEventArgs e)
{
    // true returns the nearest character, false only a character under the point
    TextChar textChar = textControl1.TextChars.GetItem(e.Location, false);
    Line line = textControl1.Lines.GetItem(e.Location);

    if (textChar == null || line == null)
    {
        Text = "No text under the mouse pointer";
        return;
    }

    // Convert the document coordinates of the character (twips) into client coordinates
    Rectangle charBounds = textControl1.DocumentToClient(textChar.Bounds);

    Text = $"Character '{textChar.Char}' (number {textChar.Number}) in line {line.Number} " +
        $"on page {line.Page}, at {charBounds.Location} in the control";
}
```

The code works as follows:

- `MouseMove` is the event of the Windows Forms `Control` class, and `e.Location` the position of the mouse pointer in pixels relative to the control. The code needs `using System.Drawing;` for `Rectangle`.
- `TextChars.GetItem(e.Location, false)` returns a [TextChar](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/textchar/llms-full.txt) only when the point is inside the rectangle of a character, and `null` otherwise. With `true` as the second parameter, it returns the nearest character.
- `Lines.GetItem(e.Location)` returns the line at the point, or `null`. `Lines.GetItem` also accepts a text position.
- [DocumentToClient](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/textcontrol/documenttoclient-method/llms-full.txt) converts a point or a rectangle in document twips into client coordinates of the control, and [ClientToDocument](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/textcontrol/clienttodocument-method/llms-full.txt) converts client coordinates into document twips. [ScrollLocation](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/textcontrol/scrolllocation-property/llms-full.txt) gives the upper left corner of the visible part in document twips, the link between the two coordinate systems.

The [InputPosition constructor](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/inputposition/constructor/llms-full.txt) that takes a point in pixels moves the caret to the character found there.

#### Insert and Remove Single Characters

[TextCharCollection.Add](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/textcharcollection/add-method/llms-full.txt) inserts one character at the input position, or at a text position you pass, optionally in a given font. Another overload inserts a control character, one of the [ControlChars](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/controlchars/enumeration/llms-full.txt) values such as `LineBreak`, `PageBreak` or `NonBreakingSpace`. [TextCharCollection.Remove](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/textcharcollection/remove-method/llms-full.txt) deletes a character and returns `false` if it can't, for example for a table cell end character that other formatting depends on:

```csharp
// Insert a copyright sign in the font Arial at text position 0
textControl1.TextChars.Add('©', "Arial", 0);

// Insert a line break at the input position
textControl1.TextChars.Add(ControlChars.LineBreak);

// Remove the first character of the text
bool removed = textControl1.TextChars.Remove(textControl1.TextChars[1]);
```

Both methods were introduced in version 23.0. To let the user pick a symbol instead, open the built-in dialog box with [AddSymbolDialog](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/textcontrol/addsymboldialog-method/llms-full.txt); [Dialog Boxes](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/document-editor/ribbon-ui/dialog-boxes/llms-full.txt) lists the other built-in dialog boxes.

### Select Tables and Objects

Table parts are not selected with character positions. [Table.Select](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/table/select-method/llms-full.txt), [TableRow.Select](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/tablerow/select-method/llms-full.txt), [TableColumn.Select](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/tablecolumn/select-method/llms-full.txt) and [TableCell.Select](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/tablecell/select-method/llms-full.txt) select a whole table, a row, a column or a cell; see [Tables and Table Formulas](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/document-editor/tables/llms-full.txt).

Images, text frames and other objects can be placed behind the text. [SelectObjects](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/textcontrol/selectobjects-property/llms-full.txt) decides what a click selects there: with `true`, the object behind the text; with `false`, the text in front of it.

### Change How the Selection Looks

| Property | Effect |
|---|---|
| [HideSelection](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/textcontrol/hideselection-property/llms-full.txt) | Whether the selected text stays highlighted when the editor loses the focus, for example to a dialog box of your application |
| [SelectionViewMode](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/reference/txtextcontrol/textcontrol/selectionviewmode-property/llms-full.txt) | `TransparentBitmap` shows the selection with a transparent highlight, `Classic` inverts the selected text |

### Next Steps

- [Clipboard Operations](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/document-editor/editing-text/clipboard/llms-full.txt): copy, cut and paste the selection.
- [Search and Replace](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/document-editor/editing-text/search-replace/llms-full.txt): find text and select every match.
- [Text and Paragraph Formatting](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/document-editor/formatting/llms-full.txt): format the selection.
- [Events](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/document-editor/events/llms-full.txt): the other events of the editor.

---

## Nearby

- **Previous:** [Editing Text](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/document-editor/editing-text/llms-full.txt)
- **Next:** [Clipboard Operations](https://docs.textcontrol.com/tx-text-control-dotnet-winforms/document-editor/editing-text/clipboard/llms-full.txt)
