Caret Services

The ICaretService interface, exposed through the WinFormHtmlEditor.Caret property, gives you programmatic control over the text caret (insertion point) inside the editor. You can position the caret by client-area pixel coordinates, by character index into the rendered text, or by named anchors such as the start or end of the current line. Each operation can optionally scroll the document so the new caret location is brought into view.

Because the caret is tightly coupled to the underlying browser document, the service is only valid once the editor has finished loading. Calling these methods before WinFormHtmlEditor.DocumentReady fires - or after Dispose has been called - will fail silently or throw. The service implements IDisposable and is owned by the editor; do not dispose it manually.

Index-based members (GetCaretIndex, SetCaretByIndex, GetCaretIndexInHtml) operate against two different coordinate spaces: the rendered/plain-text stream and the raw HTML source. Use the matching pair when round-tripping a caret location through external storage.

SetCaretAt(int x, int y, bool scrollToView)

Positions the caret at the given client-area pixel coordinates of the editor surface. Useful when translating mouse-event coordinates back into a caret position, for instance to drop the caret where the user right-clicked. The coordinates are relative to the editor control, not the screen.

Syntax
void SetCaretAt(int x, int y, bool scrollToView);
Parameters
NameTypeDescription
xintX coordinate in editor client pixels.
yintY coordinate in editor client pixels.
scrollToViewboolIf true, scrolls the document so the new caret location is visible.
Remarks

The point is hit-tested against the rendered document; if it falls outside any text node the caret snaps to the nearest valid insertion point.

Example
// Drop the caret where the user clicked, then scroll it into view.

private void htmlEditor1_MouseClick(object sender, MouseEventArgs e)

{

    htmlEditor1.Caret.SetCaretAt(e.X, e.Y, scrollToView: true);

    htmlEditor1.Focus();

}

GetCaretPosition()

Returns the current caret location as a System.Drawing.Point in editor client coordinates. The returned point reflects the rendered position, so it accounts for any prior scrolling and zoom. If there is no caret (the editor has never received focus), the returned point may be the document origin (0, 0).

Syntax
System.Drawing.Point GetCaretPosition();
Returns

Point — the caret position in editor client pixels.

Example
// Read the caret position and show it on the status strip.

var pt = htmlEditor1.Caret.GetCaretPosition();

toolStripStatusLabel1.Text = $"Caret at ({pt.X}, {pt.Y})";

SetCaretPosition(int x, int y, bool scrollToView)

Moves the caret to the supplied client coordinates. Functionally equivalent to SetCaretAt and retained for symmetry with GetCaretPosition. Prefer this method when round-tripping a caret position you previously read with GetCaretPosition.

Syntax
void SetCaretPosition(int x, int y, bool scrollToView);
Parameters
NameTypeDescription
xintX coordinate in editor client pixels.
yintY coordinate in editor client pixels.
scrollToViewboolIf true, scrolls the new caret position into view.
Example
// Save and later restore the caret position across an edit.

var saved = htmlEditor1.Caret.GetCaretPosition();

htmlEditor1.Editor.ExecCommand("InsertHTML", false, "<b>X</b>");

htmlEditor1.Caret.SetCaretPosition(saved.X, saved.Y, scrollToView: true);

Hide()

Hides the blinking caret without changing its logical position. Typing or programmatic edits still occur at the hidden caret location. Pair with Show to temporarily suppress the caret during a complex programmatic update so the user does not see it jump around.

Syntax
void Hide();
Example
// Hide the caret while we make a noisy batch of edits.

htmlEditor1.Caret.Hide();

foreach (var snippet in snippets)

    htmlEditor1.Editor.ExecCommand("InsertHTML", false, snippet);

htmlEditor1.Caret.Show(scrollToView: true);

Show(bool scrollToView)

Re-displays the caret after a previous call to Hide. Pass true to also scroll the caret location into view, which is convenient when the caret has been moved off-screen by intervening edits.

Syntax
void Show(bool scrollToView);
Parameters
NameTypeDescription
scrollToViewboolIf true, scrolls the caret into view after showing it.
Example
// Restore the caret after a hide/edit sequence.

htmlEditor1.Caret.Hide();

htmlEditor1.Editor.ExecCommand("SelectAll", false, null);

htmlEditor1.Formatting.SetBold();

htmlEditor1.Caret.Show(scrollToView: true);

ScrollToCaretView()

Scrolls the document so the current caret position is visible inside the editor viewport. Use this after programmatic text insertion that may have pushed the caret out of view, or after the user navigates with index-based caret APIs.

Syntax
void ScrollToCaretView();
Example
// Jump to a deep offset without scrolling, then bring it on-screen.

htmlEditor1.Caret.SetCaretByIndex(2048);

htmlEditor1.Caret.ScrollToCaretView();

GetCaretIndex()

Returns the zero-based character index of the caret within the rendered (plain-text) content stream. This is the index you would use when computing offsets against WinFormHtmlEditor.Text. The HTML markup itself is not counted; for that, use GetCaretIndexInHtml.

Syntax
int GetCaretIndex();
Returns

int — zero-based caret offset into the rendered text.

Example
// Show the caret offset on the status bar as the user types.

private void htmlEditor1_KeyUp(object sender, KeyEventArgs e)

{

    int caret = htmlEditor1.Caret.GetCaretIndex();

    toolStripStatusLabel1.Text = $"Caret at char {caret}";

}

SetCaretByIndex(int index)

Places the caret at the given zero-based offset into the rendered text stream. There is no selection after the call - the caret is a single insertion point. If index exceeds the document length the caret is clamped to the end.

Syntax
void SetCaretByIndex(int index);
Parameters
NameTypeDescription
indexintZero-based caret offset into the rendered text.
Example
// Restore a caret position previously saved as a plain-text offset.

int saved = LoadCaretFromSettings();   // e.g. 412

htmlEditor1.Caret.SetCaretByIndex(saved);

htmlEditor1.Caret.ScrollToCaretView();

SetCaretByIndex(int index, int length)

Selects a range of length characters starting at index. Unlike the single-argument overload, this version produces a non-empty selection that can subsequently be operated on by clipboard or formatting commands. Pass length = 0 for a caret-only positioning, or just call the single-argument overload.

Syntax
void SetCaretByIndex(int index, int length);
Parameters
NameTypeDescription
indexintZero-based starting offset of the selection.
lengthintNumber of characters to include in the selection.
Example
// Highlight the first 20 characters and bold them.

htmlEditor1.Caret.SetCaretByIndex(0, 20);

htmlEditor1.Formatting.SetBold();

GetCaretIndexInHtml()

Returns the caret offset measured against the raw HTML source, including tag characters. The value can be used to slice the WinFormHtmlEditor.Html string. This is generally not the same as GetCaretIndex, which counts only rendered text characters.

Syntax
int GetCaretIndexInHtml();
Returns

int — zero-based caret offset into the HTML source string.

Remarks

The HTML offset shifts whenever the source markup changes (for example after applying a style that introduces a new <span>); do not cache it across edits.

Example
// Splice a custom HTML fragment at the caret in the raw source.

int htmlIndex = htmlEditor1.Caret.GetCaretIndexInHtml();

string html   = htmlEditor1.Html;

htmlEditor1.Html = html.Insert(htmlIndex, "<!-- mark -->");

SetCaretAtHome()

Moves the caret to the very beginning of the document, equivalent to pressing Ctrl+Home in the editor. Any active selection is cleared.

Syntax
void SetCaretAtHome();
Example
// Jump to the top of the document on a toolbar click.

private void btnGoToTop_Click(object sender, EventArgs e)

{

    htmlEditor1.Caret.SetCaretAtHome();

    htmlEditor1.Caret.ScrollToCaretView();

}

SetCaretAtLineBeginning()

Moves the caret to the start of the current visual line, equivalent to pressing Home. The "current line" is the line that currently contains the caret; if the document has just loaded and the caret has never been placed, the result is the same as SetCaretAtHome.

Syntax
void SetCaretAtLineBeginning();
Example
// Indent the current line by inserting a tab at its start.

htmlEditor1.Caret.SetCaretAtLineBeginning();

htmlEditor1.Editor.ExecCommand("InsertHTML", false, "&emsp;");

SetCaretAtLineEnd()

Moves the caret to the end of the current visual line, equivalent to pressing End. Useful for appending to the current line without disturbing earlier content.

Syntax
void SetCaretAtLineEnd();
Example
// Append a trailing footnote marker to the current line.

htmlEditor1.Caret.SetCaretAtLineEnd();

htmlEditor1.Editor.ExecCommand("InsertHTML", false, "<sup>[1]</sup>");

SetCaretAtEnd()

Moves the caret to the very end of the document, equivalent to pressing Ctrl+End. Call this before programmatic append-style insertions so the new content is added after existing content.

Syntax
void SetCaretAtEnd();
Example
// Append a paragraph and place the caret after it.

htmlEditor1.Caret.SetCaretAtEnd();

htmlEditor1.Editor.ExecCommand("InsertHTML", false, "<p>Appended</p>");

htmlEditor1.Caret.ScrollToCaretView();
Last updated on May 14, 2026