A single-form C# rich text editor — a full File/Edit/Format/View menu system, a matching right-click context menu, live word/character counts, font and color dialogs, and RTL/LTR + text-alignment toggles, built entirely with native WinForms controls.
Tenth project in the WinForms self-practice series.
A real menu bar this time — File, Edit, Format, View — each one wired to the same shared ToolStripMenuItem_Click handler that's run through the last two projects.
Right-click the textbox, and the same Font, Fore Color, Text Align, and Writing Orientation options show up again in a context menu — same Tags, same handler, just a second entry point.
A live status bar tracks words and characters as you type. A toolbar gives one-click RTL/LTR and alignment toggles, styled as flat buttons instead of the usual radio circles. And under the hood, Open/Save/Font/Color all lean on the dialog components WinForms ships with, instead of anything custom-built.
frmTextEditor
├── menuStrip1
│ ├── File → New / Open / Save As / New Window / Exit
│ ├── Edit → Undo / Cut / Copy / Paste / Delete / Select All / Date-Time
│ ├── Format → Font / Fore Color / Text Align / Writing Orientation
│ └── View → Status Bar / Word Wrap
│ (all routed through ToolStripMenuItem_Click, switch on Tag)
│
├── panel1 (rbRTL · rbLTR) ─┐
├── groupBox1 "Text Align" ├─ rb_CheckedChanged, switch on Tag
│ (rbLeft · rbCenter · rbRight) ─┘
│
├── btnChangeFont / button1 "Change Fore Color" → btn_Click, switch on Tag
├── chkReadOnly → chk_CheckedChanged → txtEditor.ReadOnly
│
├── txtEditor (ContextMenuStrip = cmTextbox)
│ ├── TextChanged → UpdateStatusBar()
│ │ ├── lblCharacters = TextLength
│ │ └── CalculateNumberOfWords() → lblWords
│ └── cmTextbox → Font / Fore Color / Text Align / Writing Orientation
│ (same ToolStripMenuItem_Click as the main menu)
│
└── panel_StatusBar (lblWords · lblCharacters)
| Section | Feature |
|---|---|
| File menu | New (with save-changes prompt), Open, Save As, New Window, Exit |
| Edit menu | Undo, Cut, Copy, Paste, Delete, Select All, Insert Date/Time |
| Format menu | Font, Fore Color, Text Align, Writing Orientation (RTL/LTR) |
| View menu | Toggle Status Bar, Toggle Word Wrap |
| Toolbar | RTL/LTR and Text Align toggle buttons, Change Font, Change Fore Color, Read Only |
| Status bar | Live word count and character count |
| Right-click menu | Same Font / Fore Color / Text Align / Writing Orientation options, directly on the textbox |
The Format menu, the right-click context menu, and (for alignment) the toolbar all end up in the exact same place:
private void ToolStripMenuItem_Click(object sender, EventArgs e)
{
switch (((ToolStripMenuItem)sender).Tag)
{
case "Font": ChangeFont(); break;
case "Left": txtEditor.TextAlign = HorizontalAlignment.Left; break;
// ...
}
}menuStrip1's Format items and cmTextbox's right-click items share the same Tags and the same Click handler. Two menus, one small switch statement.
this.rbRTL.Appearance = System.Windows.Forms.Appearance.Button;
this.rbRTL.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.rbRTL.FlatAppearance.CheckedBackColor = System.Drawing.Color.SkyBlue;Visually it reads as a segmented button group. Functionally it's still five ordinary RadioButtons — the "only one selected at a time" behavior comes free from the control, not from custom code.
private void CalculateNumberOfWords()
{
string[] SplitedString = txtEditor.Text.Split(' ');
if (string.IsNullOrWhiteSpace(txtEditor.Text))
lblWords.Text = "0";
else if (txtEditor.Text[txtEditor.TextLength - 1] == ' ')
lblWords.Text = (SplitedString.Length - 1).ToString();
else
lblWords.Text = SplitedString.Length.ToString();
}Splitting on spaces alone would count a trailing space as an extra empty "word" — the explicit check subtracts it back out.
private void ChangeFont()
{
fontDialog1.Font = txtEditor.Font;
if (fontDialog1.ShowDialog() == DialogResult.OK)
txtEditor.Font = fontDialog1.Font;
}
private void fontDialog1_Apply(object sender, EventArgs e)
{
txtEditor.Font = fontDialog1.Font;
}ShowApply = true adds an Apply button to the built-in dialog, and its own Apply event updates the textbox immediately — so font changes preview before OK is even clicked.
private void NewWindow()
{
Form frm = new frmTextEditor();
frm.Show();
}The form has IsMdiContainer = true set, but NewWindow() just shows an independent second copy rather than adding it as an MDI child. Worth knowing if real multi-document behavior — docked or tiled child windows inside one parent — is ever wanted later; right now it behaves like opening a second, unrelated instance of the app.
DialogResult Result = MessageBox.Show("Do you want to save changes ?",
"Text Editor", MessageBoxButtons.YesNoCancel,
MessageBoxIcon.Warning, MessageBoxDefaultButton.Button3);Yes / No / Cancel this time instead of OK / Cancel, but the same instinct as every confirm dialog in the series: the safest option is the one that fires by default.
| Control | First used here | Purpose |
|---|---|---|
| ContextMenuStrip | ✅ Yes | Right-click menu on the textbox, mirrors the Format menu |
| FontDialog | ✅ Yes | Font picker with a live Apply preview |
| ColorDialog | ✅ Yes | Text color picker |
| OpenFileDialog | ✅ Yes | File picker for Open |
| SaveFileDialog | ✅ Yes | File picker for Save As |
| MenuStrip / ToolStripMenuItem | Reused | File/Edit/Format/View menu (introduced in Login Form) |
| RadioButton | Reused | RTL/LTR and alignment toggles (introduced in To Do List) |
| GroupBox | Reused | Groups the alignment buttons (introduced in To Do List) |
| CheckBox | Reused | Read Only toggle (introduced in Login Form) |
| Panel | Reused | Layout containers (introduced in Login Form) |
| MessageBox | Reused | Save-changes prompt, file-opened/saved confirmations |
| Language | C# |
| Framework | .NET Framework |
| UI | Windows Forms (WinForms) |
| IDE | Visual Studio |
| Type | Desktop Application — Single-Form |
| Controls Used | Form · Label · TextBox · Button · CheckBox · RadioButton · GroupBox · Panel · MenuStrip · ContextMenuStrip · FontDialog · ColorDialog · OpenFileDialog · SaveFileDialog · MessageBox |
| Project | Application |
|---|---|
| Project 25 — Tax Calculator | Tax computation + session history |
| Project 26 — Text Encryption | Caesar Cipher encrypt/decrypt |
| Project 27 — Password Generator | GUID + Key + Password generator |
| Project 28 — Age Calculator | Full age breakdown with time lived |
| Project 29 — String Manipulation | Live string operations toolkit |
| Project 30 — Simple Calculator | Full calculator with theme toggle |
| Project 31 — World Explorer | Multi-form geography encyclopedia |
| Project 32 — To Do List | Task manager with priorities, due dates, and live stats |
| Project 33 — Login Form | Login/registration system with live validation and a lockout timer |
| Project 34 — Text Editor Form (you are here) | Menu-driven text editor with font/color dialogs and live stats |
| More projects | Next control groups 🔄 |
- ✅ Course 14 — C# Level 1 (Stage Two, in progress)
- ✅ Tenth project in the WinForms self-practice series
- ✅ First use of ContextMenuStrip, FontDialog, ColorDialog, OpenFileDialog, and SaveFileDialog
- ✅ Part of the Programming Advices Roadmap — Stage Two
Thank you to:
Next control group.
Next project.