How can I change the FontStyle of a selection without losing the styles that are present
If you visit the selection a character at the time, you can get the current FontStyle and modify it directly to add or remove a style like Bold or Italic. Doing it a character at a time will avoid losing the other styles that are set. The problem with doing it a whole selection at a time is that the FontStyle of the entire selection is the common styles set among all characters in the selection. So, if one char is bold and one is not, then bold is not set when you retrieve the fontstyle for the entire selection. Doing things a character at the time, avoids this problem and allows things to work OK. You can download a working sample(CS,VB). private void AddFontStyle(FontStyle style) { int start = richTextBox1.SelectionStart; int len = richTextBox1.SelectionLength; System.Drawing.Font currentFont; FontStyle fs; for(int i = 0; i < len; ++i) { richTextBox1.Select(start + i, 1); currentFont = richTextBox1.SelectionFont; fs = currentFont.Style; //add style fs = fs | style; richTextBox1.SelectionFont = new Font( currentFont.FontFamily, currentFont.Size, fs ); } } private void RemoveFontStyle(FontStyle style) { int start = richTextBox1.SelectionStart; int len = richTextBox1.SelectionLength; System.Drawing.Font currentFont; FontStyle fs; for(int i = 0; i < len; ++i) { richTextBox1.Select(start + i, 1); currentFont = richTextBox1.SelectionFont; fs = currentFont.Style; //remove style fs = fs & ~style; richTextBox1.SelectionFont = new Font( currentFont.FontFamily, currentFont.Size, fs ); } } private void button1_Click(object sender, System.EventArgs e) { AddFontStyle(FontStyle.Bold); } Here is a suggestion from Nicholas Clark on how to avoid seeing the character by character changes appear as you apply the styles one character at a time in the above code. Create a hidden RTB and store the selected text in it. Then apply the attributes and copy it back into the original richtextbox, so that you don’t see the selection changing. private void change_font(FontStyle style,bool add) { richTextBox2.Rtf = richTextBox1.SelectedRtf; int lengt = richTextBox2.Text.Length; int length = richTextBox1.SelectionLength; int start = richTextBox1.SelectionStart; for (int i = 0; i < lengt; i++) { richTextBox2.Select(i,1); Font cfont = richTextBox2.SelectionFont; FontStyle fs = cfont.Style; if (add) { fs = fs | style; } else { fs = fs & ~style; } richTextBox2.SelectionFont = new Font( cfont.FontFamily, cfont.Size, fs ); } richTextBox2.Select(0,richTextBox2.Text.Length); richTextBox1.SelectedRtf = richTextBox2.SelectedRtf; richTextBox1.Select(start,length); this.richTextBox1.Focus(); isChanged = true; }
How can I create and save a RTF file
One way to do this is to use the RichTextBox.SaveFile method. private void button1_Click(object sender, System.EventArgs e) { // Create a SaveFileDialog & initialize the RTF extension SaveFileDialog saveFile1 = new SaveFileDialog(); saveFile1.DefaultExt = ‘*.rtf’; saveFile1.Filter = ‘RTF Files|*.rtf’; // get a file name from the user if (saveFile1.ShowDialog() == DialogResult.OK) { // Save the RTF contents of the RichTextBox control that // was dragged onto the Window Form and populated somehow richTextBox1.SaveFile(saveFile1.FileName, RichTextBoxStreamType.RichText); //use to save RTF tags in file //RichTextBoxStreamType.PlainText);//use to save plain text in file } }
How can I set the width of a listbox to fit the text
You can iterate through the list to find the longest text extent using MeasureString, adding a fudge factor if the scrollbar is present. System.Drawing.Graphics g = listBox1.CreateGraphics(); float maxWidth = 0f; float height = 0f; for (int i = 0; i < listBox1.Items.Count; ++i) { float w = g.MeasureString(listBox1.Items[i].ToString(), listBox1.Font).Width; if (w > maxWidth) maxWidth = w; height += listBox1.GetItemHeight(i); } g.Dispose(); listBox1.Width = (int) (maxWidth + 6 + ((height > listBox1.Height – 4) ? 16 : 0)); // 16 is scrollbar width
How can I make my control automatically grow when the parent form is sized
Change the control’s Anchor property so that it is anchored on all 4 sides. Please note that you can only have 1 control per form anchored in this manner (all 4 sides). And other controls on the form should be anchored by their sides that are not adjacent to special control anchored on all 4 sides.
How do I implement Drag and Drop support between ListBoxes
The code below minimally handles D&D for a single selection list box by handling four events. The D&D is initiated in MouseDown if the user mouses down on the current selection. The DragEnter event is used to set the dragging effect to copy if you are not over the drag source. The DragDrop event is used to do the drop. And finally, the SelectedIndexChanged event is used to track the current selection for use in the MouseDown event. You can download a working project (C#, VB). This project handles additional events to provide visual queues during the drop. The samples referenced above do not allow dragging and dropping within the same listbox. Here is another set of samples that does allow you to drag and drop within the same listbox. public class ListBoxDragNDrop : ListBox { private int lastMouseUpItemIndex = -1; private bool isDropSource = false; public ListBoxDragNDrop() { this.AllowDrop = true; //allow D&D this.SelectionMode = SelectionMode.One; //single selection DragDrop += new System.Windows.Forms.DragEventHandler(OnDragDrop); DragEnter += new System.Windows.Forms.DragEventHandler(OnDragEnter); MouseDown += new System.Windows.Forms.MouseEventHandler(OnMouseDown); SelectedIndexChanged += new System.EventHandler(OnSelectedIndexChanged); } private void OnDragDrop(object sender, DragEventArgs e) { if(e.Effect == DragDropEffects.Copy) { Point point = this.PointToClient(new Point(e.X, e.Y)); int index = this.IndexFromPoint(point); if( index > -1 && index < this.Items.Count) Items.Insert(index, e.Data.GetData(DataFormats.Text)); else Items.Add(e.Data.GetData(DataFormats.Text)); } } private void OnDragEnter(object sender, System.Windows.Forms.DragEventArgs e) { if (e.Data.GetDataPresent(DataFormats.Text) && !isDropSource ) e.Effect = DragDropEffects.Copy; else e.Effect = DragDropEffects.None; } private void OnMouseDown(object sender, System.Windows.Forms.MouseEventArgs e) { if(MouseButtons == MouseButtons.Left && SelectedIndex == lastMouseUpItemIndex) { isDropSource = true; DoDragDrop(SelectedItem, DragDropEffects.Copy); isDropSource = false; lastMouseUpItemIndex = this.SelectedIndex; } } private void OnSelectedIndexChanged(object sender, System.EventArgs e) { lastMouseUpItemIndex = this.SelectedIndex; } } One more note. If your listboxes contain full file pathnames, you can support dropping these paths onto Windows Explorer by supporting the FileDrop dataformat. In the OnMouseDown override, if you replace the DoDragDrop line with the following code block, you will be able to drop files. //put the file path is a string array string[] files = new String[1]; files[0] = SelectedItem.ToString(); //create a dataobject holding this array as a filedrop DataObject data = new DataObject(DataFormats.FileDrop, files); //also add the selection as textdata data.SetData(DataFormats.StringFormat, SelectedItem.ToString()); //do the dragdrop DoDragDrop(data, DragDropEffects.Copy);