Replacing the editor's right-click context menu
Mei-Lin works on the sales CRM at a logistics company. Sales reps spend their day inside an account-detail screen attaching notes to customer records: call summaries, follow-up reminders, snippets pasted from emails. She uses WinFormHtmlEditor as the note editor and her product manager came to her with a clear ask: when a rep right-clicks inside a note, they should see two commands that don't exist in the default menu -- Link to Ticket... and Convert Selection to Task.
The default right-click menu in WinFormHtmlEditor is a reasonable editing menu: cut/copy/paste, table commands, image properties. But it's not the right menu for a CRM note. Mei-Lin wanted to replace it entirely.
Replace the menu via EditorContextMenuStrip
The editor exposes a single property for this: EditorContextMenuStrip, of type System.Windows.Forms.ContextMenuStrip. Assign your own strip and the editor uses it whenever the user right-clicks inside the document surface.
private void NoteEditorForm_Load(object sender, EventArgs e)
{
var menu = new ContextMenuStrip();
var linkToTicket = new ToolStripMenuItem("Link to Ticket...");
linkToTicket.Click += (s, args) =>
{
var ticketId = TicketPicker.Show(this);
if (ticketId != null)
{
string anchor = $"<a href=\"crm://ticket/{ticketId}\">#{ticketId}</a>";
htmlEditor1.Content.InsertHtmlAtCaret(anchor);
}
};
var convertToTask = new ToolStripMenuItem("Convert Selection to Task");
convertToTask.Click += (s, args) =>
{
string selected = htmlEditor1.Selection.GetSelectedHtml();
if (!string.IsNullOrWhiteSpace(selected))
TaskService.CreateFromHtml(currentAccount.Id, selected);
};
menu.Items.Add(linkToTicket);
menu.Items.Add(new ToolStripSeparator());
menu.Items.Add(convertToTask); // Hand the strip to the editor. From now on, right-clicking inside the // note shows this menu instead of the built-in one. htmlEditor1.EditorContextMenuStrip = menu;}Private Sub NoteEditorForm_Load(sender As Object, e As EventArgs)
Dim menu = New ContextMenuStrip()
Dim linkToTicket = New ToolStripMenuItem("Link to Ticket...")
linkToTicket.Click += Sub(s, args)
Dim ticketId = TicketPicker.Show(Me)
If ticketId IsNot Nothing Then
Dim anchor As String = $"<a href=""crm://ticket/{ticketId}"">#{ticketId}</a>"
htmlEditor1.Content.InsertHtmlAtCaret(anchor)
End If
End Sub
Dim convertToTask = New ToolStripMenuItem("Convert Selection to Task")
convertToTask.Click += Sub(s, args)
Dim selected As String = htmlEditor1.Selection.GetSelectedHtml()
If Not String.IsNullOrWhiteSpace(selected) Then TaskService.CreateFromHtml(currentAccount.Id, selected)
End Sub
menu.Items.Add(linkToTicket)
menu.Items.Add(New ToolStripSeparator())
menu.Items.Add(convertToTask) ' Hand the strip to the editor. From now on, right-clicking inside the // note shows this menu instead of the built-in one. htmlEditor1.EditorContextMenuStrip = menu;}
End Sub[IMAGE: editor-context-menu-strip.png -- right-click menu showing Link to Ticket and Convert to Task in place of the default menu]
Disable items based on current state
Mei-Lin's PM came back the next day with a refinement: "Convert to Task" should be greyed out when there's nothing selected. The EditorContextMenuStrip is a normal Windows Forms ContextMenuStrip, so she wired up its Opening event:
menu.Opening += (s, args) =>
{
string selected = htmlEditor1.Selection.GetSelectedHtml();
convertToTask.Enabled = !string.IsNullOrWhiteSpace(selected);
};menu.Opening += Sub(s, args)
Dim selected As String = htmlEditor1.Selection.GetSelectedHtml()
convertToTask.Enabled = Not String.IsNullOrWhiteSpace(selected)[IMAGE: context-menu-opening-state.png -- menu with Convert to Task disabled because there is no selection]
The ContextMenuShowing event: a notification hook
Mei-Lin also wanted to track which parts of a note reps right-click on, so the team could decide where to put the next CRM-specific shortcut. The editor exposes a ContextMenuShowing event that fires whenever the built-in menu is about to appear. The event args give you the cursor position relative to the editor, which is enough for analytics:
htmlEditor1.ContextMenuShowing += (sender, e) =>
{
// e.OffsetMousePosition is the cursor location relative to the editor surface.
AnalyticsClient.Track(
"NoteEditorRightClick",
new { x = e.OffsetMousePosition.X, y = e.OffsetMousePosition.Y });
};One thing worth knowing: ContextMenuShowingEventArgs only carries OffsetMousePosition. There's no Cancel, no MenuItems collection, no way to suppress or mutate the built-in menu from inside this event. If you want a completely different menu (as Mei-Lin did), the supported path is EditorContextMenuStrip. The event is for observation, not modification.
[IMAGE: context-menu-showing-event.png -- event firing as the built-in menu appears, with the offset coordinates highlighted]
In production, reps started using Link to Ticket dozens of times a day per account. The cross-references between notes and tickets now flow into the CRM's knowledge graph automatically. Mei-Lin's PM filed a follow-up to add a third item -- Insert Account Name -- and she shipped it the same afternoon by adding one more ToolStripMenuItem to the strip she built on day one.