Skip to main content Skip to footer

Custom ToolStrips in C1Editor

The C1Editor is a WinForms rich text editor. It is shipped with four specialized ToolStrip controls that allow you to build complete user interfaces without writing any code. Add the toolstrip to the form, connect it to a C1Editor by setting the toolstrip's Editor property, and you have a professional quality XHTML editor. This article deals with the common problems faced in the C1Editor control by walking through the creation of custom toolstrips. These toolstrips are designed to show how you can implement the following features in simple steps :

  1. Merge multiple toolstrips
  2. Localizing toolstrip
  3. Implement spellchecking features
  4. Implement Custom Dialogs

The CustomToolStripMerge class

The CustomToolStripMerge class is class that provides the functionality to merge the buttons available in different toolstrips. The CustomToolStripMerge class is extremely simple. All we need to do is inherit the class from C1EditorToolStripBase and use the AddButton() and AddColorPicker() methods to add various buttons and colorpickers. This is what the CustomToolStripMerge control looks like:

    class CustomToolStripMerge : C1EditorToolStripBase  

{  

protected override void OnInitialize()  

{  

base.OnInitialize();  

AddButton(C1.Win.C1Editor.ToolStrips.CommandButton.Find);  

AddButton(C1.Win.C1Editor.ToolStrips.CommandButton.Replace);  

this.Items.Add(new ToolStripSeparator());  

AddButton(C1.Win.C1Editor.ToolStrips.CommandButton.Picture);  

AddButton(C1.Win.C1Editor.ToolStrips.CommandButton.FlashMovie);  

this.Items.Add(new ToolStripSeparator());  

AddButton(C1.Win.C1Editor.ToolStrips.CommandButton.Design);  

AddButton(C1.Win.C1Editor.ToolStrips.CommandButton.Source);  

this.Items.Add(new ToolStripSeparator());  

AddColorPicker(CommandColorPicker.ForeColor);  

AddColorPicker(CommandColorPicker.BackColor);  

AddColorPicker(CommandColorPicker.ParagraphBackColor);  

this.Items.Add(new ToolStripSeparator());  

AddButton(CommandButton.Table);  

AddButton(CommandButton.TableProperties);  

AddButton(CommandButton.CellProperties);  

AddButton(CommandButton.DeleteTable);  

}  

}

The CustomToolStripLocalized class

The next problem that the users encounter is localizing of existing toolstrips. Now you can do that by changing the text and tooltips of existing toolstrips or adding new button with localized text. In our example we have changed the tooltips of C1EditorToolStripMain buttons as well as added a new localized button which would show up a messagebox with localized text. Here you can add any functionality you want to. Now to do this, we would need to inherit our CustomToolStripLocalized class with C1EditorToolstripMain and change the tooltips of all the buttons. We would also add a new button with localized text. The class would look something like the following :

  class CustomToolStripLocalized :C1EditorToolStripMain  

{  

protected override void OnInitialize()  

{  

base.OnInitialize();  

LocalizeToolTip();  

this.Items.Add(new ToolStripSeparator());  

AddCustomButton();  

}  

void LocalizeToolTip()  

{  

this.Items[0].ToolTipText = "Nouveau Fichier(Ctrl + N)";  

this.Items[1].ToolTipText = "Open Fichier(Ctrl+O)";  

this.Items[2].ToolTipText = "Enregistrer le fichier (Ctrl+S)";  

this.Items[3].ToolTipText = "Imprimer (Ctrl + P)";  

this.Items[5].ToolTipText = "Couper (Ctrl + X)";  

this.Items[6].ToolTipText = "Copier (Ctrl + C)";  

this.Items[7].ToolTipText = "Coller (Ctrl + V)";  

this.Items[8].ToolTipText = "Annuler (Ctrl + Z)";  

this.Items[9].ToolTipText = "Refaire (Ctrl + Y)";  

this.Items[11].ToolTipText = "Tout sélectionner (Ctrl + A)";  

this.Items[12].ToolTipText = "Trouver (Ctrl + F)";  

this.Items[13].ToolTipText = "Remplacer (Ctrl + H)";  

this.Items[15].ToolTipText = "Voir Design";  

this.Items[16].ToolTipText = "Voir Source";  

this.Items[17].ToolTipText = "Voir Extrait";  

}  

void AddCustomButton()  

{  

Image img = Properties.Resources.howto;  

this.Items.Add("Bouton de test", img, toolstrip_ItemClick);  

}  

private void toolstrip_ItemClick(object sender, EventArgs e)  

{  

MessageBox.Show("Ce bouton montre comment implémenter un bouton personnalisé dans ToolStrip.", "Mésage", MessageBoxButtons.OK, MessageBoxIcon.None);  

}  

}

The CustomToolStripAdvanced class

Another problem usually faced by the customers are how to incorporate the spellchecking features, add custom dialogs and append text to the editor at current cursor position or at the end of the editor text. We would create a CustomToolStripAdvanced which would include all these. First we would inherit the class with C1EditorToolStripBase and then add buttons to this. First we would start with the spellchecking options. In spell checking the most commonly used scenarios are enabling/disenabling As-You-Type spellchecking, spell-check option and showing the error list. We will create a method called AddSpellButtons() which would add all these three buttons. We would need to use C1SpellChecker to spell-check our C1Editor control.

        void AddSpellButtons()  

{  

ToolStripButton btn1 = new ToolStripButton();  

btn1.Text = "As you type";  

btn1.Image = Properties.Resources.SpellCheck;  

btn1.CheckOnClick = true;  

btn1.DisplayStyle = ToolStripItemDisplayStyle.Image;  

btn1.CheckStateChanged += new EventHandler(btn_CheckStateChanged);  

this.Items.Add(btn1);  

this.Items.Add("Spell Check", null, spellCheck_ItemClicked);  

this.Items.Add("Show Errors", null, ShowErrors);  

}  

//Toggles As-You-Type Spell Checking  

void btn_CheckStateChanged(object sender, EventArgs e)  

{  

if (Editor != null)  

{  

ToolStripButton btn = (ToolStripButton)sender;  

spellchecker.SetActiveSpellChecking(this.Editor, this.Editor.GetActiveXInstance(), btn.Checked);  

}  

}  

//Spell Checks using SpellDialog  

private void spellCheck_ItemClicked(System.Object sender, System.EventArgs e)  

{  

if (Editor != null)  

spellchecker.CheckControl(this.Editor,this.Editor.GetActiveXInstance());  

}  

//Shows Error List  

private void ShowErrors(Object sender, EventArgs e)  

{  

if (Editor != null)  

{  

// get a list with all spelling mistakes  

CharRangeList errors = spellchecker.CheckText(Editor.Text);  

if (errors.Count > 0)  

{  

DataGridView grid = new DataGridView();  

grid.DataSource = errors;  

grid.Dock = DockStyle.Fill;  

Form f = new Form();  

f.StartPosition = FormStartPosition.CenterParent;  

f.Size = new System.Drawing.Size(600, 300);  

f.Text = string.Format("{0} Spelling errors detected", errors.Count);  

f.Controls.Add(grid);  

f.ShowDialog();  

}  

else  

MessageBox.Show("No Spell Errors");  

}  

}

To use custom dialogs, we will create a custom dialog CustomTableForm and set the C1Editor.CustomDialogs.TableDialog as this custom dialog. We start by creating a class and inheriting the ITableItemDialog interface. Also we will implement two main methods of this interface – BindData() and ShowData(). The class would look something like :

  public partial class CustomTableForm : Form, ITableItemDialog  

{  

C1Editor editor;  

XHTMLTableItem tableitem;  

private XHTMLTableItem Item  

{  

get { return tableitem as XHTMLTableItem; }  

}  

public C1Editor Editor  

{  

get { return editor; }  

set { editor = value; }  

}  

public CustomTableForm()  

{  

InitializeComponent();  

numColumns.Validated += new EventHandler(num_Validated);  

numRows.Validated += new EventHandler(num_Validated);  

numWidth.Validated += new EventHandler(num_Validated);  

numBorderWidth.Validated += new EventHandler(num_Validated);  

}  

void num_Validated(object sender, EventArgs e)  

{  

NumericUpDown control = sender as NumericUpDown;  

if (control != null)  

control.Text = control.Value.ToString();  

}  

private void chkWidth_CheckedChanged(object sender, EventArgs e)  

{  

numWidth.Enabled = chkWidth.Checked;  

cbWidth.Enabled = chkWidth.Checked;  

}  

private void cbWidth_SelectedIndexChanged(object sender, EventArgs e)  

{  

Item.WidthType = (C1.Win.C1Editor.UICustomization.SizeType)cbWidth.SelectedIndex;  

}  

private void OnItemPropertiesChanged()  

{  

//Set the minimum number  

numRows.Minimum = (tableitem != null && tableitem.IsEditMode) ? Item.RowCount : 1;  

numColumns.Minimum = (tableitem != null && tableitem.IsEditMode) ? Item.ColumnCount : 1;  

}  

void ITableItemDialog.BindData(XHTMLTableItem item)  

{  

tableitem = item;  

cbWidth.SelectedIndex =(int) Item.WidthType;  

numColumns.DataBindings.Add("Value", Item, "ColumnCount");  

numRows.DataBindings.Add("Value", Item, "RowCount");  

numWidth.DataBindings.Add("Value", Item, "WidthValue");  

numBorderWidth.DataBindings.Add("Value", Item, "Border");  

chkWidth.DataBindings.Add("Checked", Item, "UseWidth");  

OnItemPropertiesChanged();  

}  

bool ITableItemDialog.Show(IWin32Window owner)  

{  

return ShowDialog(owner) == DialogResult.OK;  

}

After this we will add a new method to CustomToolStripAdvanced class called the AddCustomTable() method.

        void AddCustomTable()  

{  

AddButton(CommandButton.Table);  

this.Items[4].ToolTipText = this.Items[4].Text = "Custom Table";  

this.Items[4].DisplayStyle = ToolStripItemDisplayStyle.ImageAndText;  

}  

protected override void OnItemClicked(ToolStripItemClickedEventArgs e)  

{  

base.OnItemClicked(e);  

if (Editor != null)  

this.Editor.CustomDialogs.TableDialog = new CustomTableForm();  

}

To append text, we will create another custom dialog AppendDialog which would append the text to C1Editor to the current cursor position or at the end. This dialog would have a richtextbox where the user would enter the text to be appended to the editor and he can also select the position where he would like to insert the text, i.e., at the end or at the current position. This class would also have two properties, AppendText and Position which would return the text and insertion position to the editor.

        public string AppendText  

{  

get { return richTextBox1.Text; }  

}  

public int Position  

{  

get  

{  

if (rbCurrent.Checked)  

return 1;  

else  

return 0;  

}  

}

After this we will add a new method to CustomToolStripAdvanced class called the AddAppendText() method.

        void AddAppendText()  

{  

ToolStripButton appendTxtbtn = new ToolStripButton();  

appendTxtbtn.Text = "Append Text";  

appendTxtbtn.Image = Properties.Resources.Add;  

appendTxtbtn.DisplayStyle = ToolStripItemDisplayStyle.Image;  

appendTxtbtn.Click += new EventHandler(appendTxtbtn_Click);  

this.Items.Add(appendTxtbtn);  

}  

void appendTxtbtn_Click(object sender, EventArgs e)  

{  

if (Editor != null)  

{  

AppendDialog dialog = new AppendDialog();  

if (dialog.ShowDialog() == DialogResult.OK)  

{  

string text = dialog.AppendText;  

if (dialog.Position == 1)  

{  

C1TextRange range = Editor.Selection;  

range.Select();  

XmlElement node = Editor.Document.CreateElement("div");  

node.InnerXml = text;  

range.SetXmlElement(node);  

}  

else  

{  

Editor.Text += text;  

int i = Editor.Text.Length;  

Editor.SelectionStart = i;  

Editor.Select(i, 0);  

}  

}  

}  

}

Our final CustomerToolStripAdvanced class would look like :

  class CustomToolStripAdvanced : C1EditorToolStripBase  

{  

C1SpellChecker spellchecker = new C1SpellChecker();  

protected override void OnInitialize()  

{  

base.OnInitialize();  

AddSpellButtons();  

this.Items.Add(new ToolStripSeparator());  

AddCustomTable();  

this.Items.Add(new ToolStripSeparator());  

AddAppendText();  

}  

#region Spell Checking Options  

//Adds SpellChecking Options  

void AddSpellButtons()  

{  

ToolStripButton btn1 = new ToolStripButton();  

btn1.Text = "As you type";  

btn1.Image = Properties.Resources.SpellCheck;  

btn1.CheckOnClick = true;  

btn1.DisplayStyle = ToolStripItemDisplayStyle.Image;  

btn1.CheckStateChanged += new EventHandler(btn_CheckStateChanged);  

this.Items.Add(btn1);  

this.Items.Add("Spell Check", null, spellCheck_ItemClicked);  

this.Items.Add("Show Errors", null, ShowErrors);  

}  

//Toggles As-You-Type Spell Checking  

void btn_CheckStateChanged(object sender, EventArgs e)  

{  

if (Editor != null)  

{  

ToolStripButton btn = (ToolStripButton)sender;  

spellchecker.SetActiveSpellChecking(this.Editor, this.Editor.GetActiveXInstance(), btn.Checked);  

}  

}  

//SpellChecks using SpellDialog  

private void spellCheck_ItemClicked(System.Object sender, System.EventArgs e)  

{  

if (Editor != null)  

spellchecker.CheckControl(this.Editor,this.Editor.GetActiveXInstance());  

}  

//Shows Error List  

private void ShowErrors(Object sender, EventArgs e)  

{  

if (Editor != null)  

{  

// get a list with all spelling mistakes  

CharRangeList errors = spellchecker.CheckText(Editor.Text);  

if (errors.Count > 0)  

{  

DataGridView grid = new DataGridView();  

grid.DataSource = errors;  

grid.Dock = DockStyle.Fill;  

Form f = new Form();  

f.StartPosition = FormStartPosition.CenterParent;  

f.Size = new System.Drawing.Size(600, 300);  

f.Text = string.Format("{0} Spelling errors detected", errors.Count);  

f.Controls.Add(grid);  

f.ShowDialog();  

}  

else  

MessageBox.Show("No Spell Errors");  

}  

}  

#endregion  

#region CustomTable Options  

void AddCustomTable()  

{  

AddButton(CommandButton.Table);  

this.Items[4].ToolTipText = this.Items[4].Text = "Custom Table";  

this.Items[4].DisplayStyle = ToolStripItemDisplayStyle.ImageAndText;  

}  

protected override void OnItemClicked(ToolStripItemClickedEventArgs e)  

{  

base.OnItemClicked(e);  

if (Editor != null)  

this.Editor.CustomDialogs.TableDialog = new CustomTableForm();  

}  

#endregion  

#region Append Text Options  

void AddAppendText()  

{  

ToolStripButton appendTxtbtn = new ToolStripButton();  

appendTxtbtn.Text = "Append Text";  

appendTxtbtn.Image = Properties.Resources.Add;  

appendTxtbtn.DisplayStyle = ToolStripItemDisplayStyle.Image;  

appendTxtbtn.Click += new EventHandler(appendTxtbtn_Click);  

this.Items.Add(appendTxtbtn);  

}  

void appendTxtbtn_Click(object sender, EventArgs e)  

{  

if (Editor != null)  

{  

AppendDialog dialog = new AppendDialog();  

if (dialog.ShowDialog() == DialogResult.OK)  

{  

string text = dialog.AppendText;  

if (dialog.Position == 1)  

{  

C1TextRange range = Editor.Selection;  

range.Select();  

XmlElement node = Editor.Document.CreateElement("div");  

node.InnerXml = text;  

range.SetXmlElement(node);  

}  

else  

{  

Editor.Text += text;  

int i = Editor.Text.Length;  

Editor.SelectionStart = i;  

Editor.Select(i, 0);  

}  

}  

}  

}  

#endregion  

}

Now you have a C1Editor with three customized toosltrips. Download Sample

MESCIUS inc.

comments powered by Disqus