Keep custom buttons in sync

    A formatting button should reflect the text at the caret: Bold should appear pressed on bold text, and table commands should be available when relevant. Handle SelectionChanged and query StateQuery to keep your own buttons in step with the current selection.

    The two members that solve this

    Two members on WinFormHtmlEditor handle it. The event SelectionChanged fires whenever the caret moves or the selection changes: typing, arrow keys, mouse clicks, paste, or a programmatic edit. The service StateQuery, an IStateQueryService, is the same service the built-in toolbar uses to drive its own pressed-state logic. Hook the event, query the service on each fire, and update your controls.

    private void ManuscriptForm_Load(object sender, EventArgs e) {
        htmlEditor1.SelectionChanged += HtmlEditor_SelectionChanged;
    }
    
    private void HtmlEditor_SelectionChanged(object sender, EventArgs e) {
        var sq = htmlEditor1.StateQuery;
        // Toggle pressed state on the ribbon buttons.
        ribbonBoldButton.Checked = sq.IsBold();
        ribbonItalicButton.Checked = sq.IsItalic();
        ribbonUnderlineButton.Checked = sq.IsUnderline();
        // Highlight Insert Image when an image is the active element.
        ribbonImageButton.BackColor = sq.IsImage() ? SystemColors.Highlight : SystemColors.Control;
        // Show the active font in the status bar.
        lblActiveFont.Text = sq.GetActiveFontFamilyName();
        lblActiveSize.Text = sq.GetActiveFontSize();
    }
    Private Sub ManuscriptForm_Load(sender As Object, e As EventArgs)
        AddHandler htmlEditor1.SelectionChanged, AddressOf HtmlEditor_SelectionChanged
    End Sub
    
    Private Sub HtmlEditor_SelectionChanged(sender As Object, e As EventArgs)
        Dim sq = htmlEditor1.StateQuery
        ' Toggle pressed state on the ribbon buttons.
        ribbonBoldButton.Checked = sq.IsBold()
        ribbonItalicButton.Checked = sq.IsItalic()
        ribbonUnderlineButton.Checked = sq.IsUnderline()
        ' Highlight Insert Image when an image is the active element.
        ribbonImageButton.BackColor = If(sq.IsImage(), SystemColors.Highlight, SystemColors.Control)
        ' Show the active font in the status bar.
        lblActiveFont.Text = sq.GetActiveFontFamilyName()
        lblActiveSize.Text = sq.GetActiveFontSize()
    End Sub
    A host application toolbar whose buttons follow the caret in the SpiceLogic WinForms HTML Editor: with the caret inside bold text, the host Bold button shows pressed, driven by the SelectionChanged event and the editor's own state service.
    A host application toolbar whose buttons follow the caret in the SpiceLogic WinForms HTML Editor: with the caret inside bold text, the host Bold button shows pressed, driven by the SelectionChanged event and the editor's own state service.

    What StateQuery exposes

    The IStateQueryService interface exposes the current editor state so you can keep toolbar/ribbon buttons in sync with the selection, without polling.

    • Inline formatting: IsBold(), IsItalic(), IsUnderline(), IsStrikeThrough(), IsSuperscript(), IsSubscript().
    • Block formatting: IsOrderedList(), IsUnorderedList(), IsJustifyLeft(), IsJustifyCenter(), IsJustifyRight(), IsActiveElementHeaderTitle(), GetActiveHeaderTitleNumber().
    • Active element kind: IsHyperLink(), IsImage(), IsTable(), IsTableCell(), IsYouTubeVideo(), IsActiveOrAncestorElementTable(), IsActiveOrAncestorElementHyperLink().
    • Font: GetActiveFontFamilyName(), GetActiveFontSize(), GetActiveForeColor(), GetActiveHighlightColor().
    • Edit-state guards: CanUndo(), CanRedo(), CanCut(), CanCopy(), CanPaste(), CanDelete(), CanMergeTableCells().
    • Low-level access: GetActiveHtmlElement() returns the raw IHTMLElement when the high-level helpers don't cover an attribute you need.

    Driving Undo/Redo enabled state

    Undo and Redo buttons should only be enabled when there is actually something to undo or redo. Extend the same SelectionChanged handler:

    private void HtmlEditor_SelectionChanged(object sender, EventArgs e) {
        var sq = htmlEditor1.StateQuery;
        ribbonBoldButton.Checked = sq.IsBold();
        ribbonItalicButton.Checked = sq.IsItalic();
        ribbonUnderlineButton.Checked = sq.IsUnderline();
        ribbonUndoButton.Enabled = sq.CanUndo();
        ribbonRedoButton.Enabled = sq.CanRedo();
        ribbonPasteButton.Enabled = sq.CanPaste();
    }
    Private Sub HtmlEditor_SelectionChanged(sender As Object, e As EventArgs)
        Dim sq = htmlEditor1.StateQuery
        ribbonBoldButton.Checked = sq.IsBold()
        ribbonItalicButton.Checked = sq.IsItalic()
        ribbonUnderlineButton.Checked = sq.IsUnderline()
        ribbonUndoButton.Enabled = sq.CanUndo()
        ribbonRedoButton.Enabled = sq.CanRedo()
        ribbonPasteButton.Enabled = sq.CanPaste()
    End Sub
    The same host toolbar one caret move later: with the caret inside italic text, the host Italic button shows pressed and Bold has cleared, so the host buttons track the document rather than the last command used.
    The same host toolbar one caret move later: with the caret inside italic text, the host Italic button shows pressed and Bold has cleared, so the host buttons track the document rather than the last command used.

    The performance footnote

    The SelectionChanged handler can fire often, so keep it cheap. Calls into StateQuery are inexpensive, but avoid anything heavy inside the handler: no network calls, no file I/O, and no layout-triggering reflows of large panels. If a reaction to selection changes cannot run synchronously, defer it to a short-debounce System.Windows.Forms.Timer so long edit sessions don't stutter.

    Ask your AI to do this

    Connect the SpiceLogic MCP server, then give your coding assistant this prompt.

    I use the SpiceLogic WinForms HTML Editor. Help me keep my custom formatting buttons in sync with the current selection. Confirm the exact API names, types and defaults with the SpiceLogic MCP documentation, then show the changes for my project.

    Last updated on Oct 9, 2026

    Put this into practice.

    Clone the C# and VB.NET sample projects from GitHub. Start with Quickstart, then explore the feature samples.

    Prefer a guided look? Book a free live demo with our engineers - live on Zoom or Teams, never a chatbot.