Windows Forms Common Dialogs

19.1 How do I use the ColorDialog to pick a color?

It is straight-forward. Create an instance of the class and call its ShowDialog method.

ColorDialog colorDialog1 = new ColorDialog();

//fontDialog1.ShowColor = true;

if(colorDialog1.ShowDialog() != DialogResult.Cancel )

{

textBox1.ForeColor = colorDialog1.Color;

}

textBox1.Text = "this is a test";

19.2 How do I use the FontDialog class to set a control's font?

It is straight-forward. Create an instance of the class and call its ShowDialog method.

FontDialog fontDialog1 = new FontDialog();

fontDialog1.ShowColor = true;

if(fontDialog1.ShowDialog() != DialogResult.Cancel )

{

textBox1.Font = fontDialog1.Font ;

textBox1.ForeColor = fontDialog1.Color;

}

textBox1.Text = "this is a test";

19.3 How do I implement a Folder Browser class?

Below is a technique that uses FolderNameEditor and FolderBrowser classes to implement a solution. You can also use iterop to get a solution.
Both the FolderNameEditor and FolderBrowser classes used in this solution are described in the Docs as "This type supports the .NET Framework infrastructure and is not intended to be used directly from your code."

// add a reference to System.Design.DLL

using System.Windows.Forms.Design;

.............

public class DirBrowser : FolderNameEditor

{

FolderBrowser fb = new FolderBrowser();

public string Description

{

set { _description = value; }

get { return _description; }

}

public string ReturnPath

{

get { return _returnPath; }

}

public DirBrowser() { }

public DialogResult ShowDialog()

{

fb.Description = _description;

fb.StartLocation = FolderBrowserFolder.MyComputer;

DialogResult r = fb.ShowDialog();

if (r == DialogResult.OK)

_returnPath = fb.DirectoryPath;

else

_returnPath = String.Empty;

return r;

}

private string _description = "Choose Directory";

private string _returnPath = String.Empty;

}

(Posted by Ryan Farley on the microsoft.public.dotnet.language.csharp newsgroup)

19.4 How can I get just the name of a file from the complete path string?

Use FileInfo. Instantiate a FileInfo object with the full path as constructor arg. Then simply call FileInfo.Name and you will get just the name of the file.

FileInfo finfo = new FileInfo(strFileName);

Console.WriteLine(finfo.Name);

19.5 How can I get just the extension of a file from the complete path string?

Use FileInfo. Instantiate a FileInfo object with the full path as constructor arg. Then simply call FileInfo.Extension and you will get just the extension of the file.

FileInfo finfo = new FileInfo(strFileName);

Console.WriteLine(finfo.Extension);

19.6 How do I use the OpenFileDialog?

using System.Text;

using System.IO;

....

private void button1_Click(object sender, System.EventArgs e)

{

OpenFileDialog dlg = new OpenFileDialog();

dlg.Title = "Open text file" ;

dlg.InitialDirectory = @"c:\" ;

dlg.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*" ;

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

{

StreamReader sr = File.OpenText(dlg.FileName);

string s = sr.ReadLine();

StringBuilder sb = new StringBuilder();

while (s != null)

{

sb.Append(s);

s = sr.ReadLine();

}

sr.Close();

textBox1.Text = sb.ToString();

}

}

19.7 How do I specify the path for the FolderBrowser instance when it opens the first time?

In the 1.1 framework there is a SelectedPath property that will let you do this.




© 2001-06 Copyright George Shepherd.

20. Windows Forms ListBox FAQ Home

20.1 How do I add and delete items from a ListBox?

20.2 How do I implement Drag and Drop support between ListBoxes?

20.3 How can I drag file names from Windows Explorer and drop them into a listbox?

20.4 How do I implement an ownerdrawn listbox?

20.5 How can I set the width of a listbox to fit the text?



20.1 How do I add and delete items from a ListBox?

Check out Devinder Arora's article Using ListBox Control in C# on C# Corner.

20.2 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 <>

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);

20.3 How can I drag file names from Windows Explorer and drop them into a listbox?

Place a ListBox on your form, set its AllowDrop property and handle both DragEnter and DragDrop as below.

private void listBox1_DragEnter(object sender, System.Windows.Forms.DragEventArgs e)

{

if (e.Data.GetDataPresent(DataFormats.FileDrop))

e.Effect = DragDropEffects.All;

else

e.Effect = DragDropEffects.None;

}

private void listBox1_DragDrop(object sender, System.Windows.Forms.DragEventArgs e)

{

string[] files = (string[])e.Data.GetData("FileDrop", false);

foreach (string s in files)

{

//just filename

listBox1.Items.Add(s.Substring(1 + s.LastIndexOf(@"\")));

//or fullpathname

// listBox1.Items.Add(s);

}

}

Here are some VB snippets.

Private Sub listBox1_DragEnter(sender As Object, e As System.Windows.Forms.DragEventArgs)

If e.Data.GetDataPresent(DataFormats.FileDrop) Then

e.Effect = DragDropEffects.All

Else

e.Effect = DragDropEffects.None

End If

End Sub 'listBox1_DragEnter

Private Sub listBox1_DragDrop(sender As Object, e As System.Windows.Forms.DragEventArgs)

Dim files As String() = CType(e.Data.GetData("FileDrop", False), String())

Dim s As String

For Each s In files

'just filename

listBox1.Items.Add(s.Substring(1 + s.LastIndexOf("\")))

or fullpathname

' listBox1.Items.Add(s)

Next s

End Sub 'listBox1_DragDrop

20.4 How do I implement an ownerdrawn listbox?

Check out this sample project at gotnetdot.com. It derives from Form and implements the owner drawing by handling the DrawItem event and MeasureItem event.

You can also download a sample that implements an owner drawn listbox by deriving from ListBox and overriding the virtual methods OnDrawItem and OnMeasureItem. Here is a OnDrawItem override that draws colored rectangles in the listbox.

protected override void OnDrawItem(System.Windows.Forms.DrawItemEventArgs e)

{

//undo the selection rect on the old selection

if( oldSelectedRect != e.Bounds &&

oldSelectedIndex > -1 && oldSelectedIndex <>

{

e.Graphics.DrawRectangle(new Pen((Color) Items[oldSelectedIndex], 2), oldSelectedRect);

}

//draw the item .. here we just fill a rect

if( e.Index > -1 && e.Index <>

e.Graphics.FillRectangle(new SolidBrush( (Color)Items[e.Index] ), e.Bounds);

//draw selection rect if needed

if(SelectedIndex == e.Index)

{

e.Graphics.DrawRectangle(new Pen(Color.Black,2), e.Bounds);

oldSelectedRect = e.Bounds;

oldSelectedIndex = e.Index;

}

}

20.5 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 is present.

System.Drawing.Graphics g = listBox1.CreateGraphics();

float maxWidth = 0f;

float height = 0f;

for(int i = 0; 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




© 2001-06 Copyright George Shepherd.

21. Windows Forms ComboBox FAQ Home

21.1 How do I bind the values of an enum to a ComboBox?

21.2 How can I programmatically prevent the combobox from dropping?

21.3 How can I turn off editing in the textbox portion of a ComboBox, restricting the user to selecting only those options in the drop list?

21.4 How can I adjust the height of the of my ComboBox dropdown?

21.5 How do I implement an owner drawn combobox?

21.6 How do I add a ComboBox button to a toolbar?

21.7 How do I set the width of a combobox to fit the entries in its list?

21.8 How can I programmatically create a new list for my ComboBox dropdown?



21.1 How do I bind the values of an enum to a ComboBox?

This entry was created using the feedback provided by Jay Harlow in the newsgroups.

The enum values can be bound to a combobox as follows:

[C#]

// Setup the binding as follows:

// MyValues is the enum type

comboBox1.DataSource = Enum.GetValues(typeof MyValues);

[VB]

comboBox1.DataSource = Enum.GetValues(Type.GetType(MyValues))

Then in the SelectedValueChanged event for the ComboBox.

[C#]

private void ComboBox1ValueChanged(object sender, EventArgs e)

{

MyValues v = (MyValues)this.comboBox1.SelectedValue;

}

[VB]

Private Sub ComboBox1ValueChanged(ByVal sender As Object, ByVal e As EventArgs)

Dim v As MyValues = CType(Me.comboBox1.SelectedValue, MyValues)

End Sub

21.2 How can I programmatically prevent the combobox from dropping?

You can avoid the combobox dropping by overriding its WndProc method and ignoring the WM_LBUTTONDOWN and WM_LBUTTONDBLCLK.

[C#]

public class MyComboBox : ComboBox

{

protected override void WndProc(ref System.Windows.Forms.Message m)

{

if(m.Msg == 0x201 //WM_LBUTTONDOWN

|| m.Msg == 0x203) //WM_LBUTTONDBLCLK

return;

base.WndProc(ref m);

}

}

[VB.NET]

Public Class MyComboBox

Inherits ComboBox

Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)

If m.Msg = &H201 OrElse m.Msg = &H203 Then 'WM_LBUTTONDOWN or WM_LBUTTONDBLCLK

Return

End If

MyBase.WndProc(m)

End Sub 'WndProc

End Class 'MyComboBox

21.3 How can I turn off editing in the textbox portion of a ComboBox, restricting the user to selecting only those options in the drop list?

Set the combobox's DropDownStyle property to DropDownList .

21.4 How can I adjust the height of the of my ComboBox dropdown?

You can control the height by changing the value of the MaxDropDownItems property of the the Combobox, which is the setting for maximum number of entries that will be displayed by the drop-down list.

21.5 How do I implement an owner drawn combobox?

You can subclass ComboBox. In your derived class, make sure you set

this.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;

this.DropDownStyle = ComboBoxStyle.DropDownList;

You also need to handle the DrawItem event to actually implement the drawing. Check out the details in the OwnerDrawnComboBox sample.

21.6 How do I add a ComboBox button to a toolbar?

Michael Gold discusses this problem in How to create a ComboBox button in a toolbar in .NET on C# Corner.

21.7 How do I set the width of a combobox to fit the entries in its list?

You can iterate through the list to find the longest text extent using MeasureString, and then use this as the combobox width adding a fudge factor for the dropdown button.

System.Drawing.Graphics g = comboBox1.CreateGraphics();

float maxWidth = 0f;

foreach(object o in comboBox1.Items)

{

float w = g.MeasureString(o.ToString(), comboBox1.Font).Width;

if(w > maxWidth)

maxWidth = w;

}

g.Dispose();

comboBox1.Width = (int) maxWidth + 20; // 20 is to take care of button width

21.8 How can I programmatically create a new list for my ComboBox dropdown?

Here are some snippets. (Courtesy of Michael Lang)

[C#]

DataTable list = new DataTable();

list.Columns.Add(new DataColumn("Display", typeof(string)));

list.Columns.Add(new DataColumn("Id", typeof(int)));

list.Rows.Add(list.NewRow());

list.Rows.Add(list.NewRow());

list.Rows.Add(list.NewRow());

list.Rows[0][0] = "one";

list.Rows[0][1] = 1;

list.Rows[1][0] = "two";

list.Rows[1][1] = 2;

list.Rows[2][0] = "three";

list.Rows[2][1] = 3;

comboBox1.DataSource = list;

comboBox1.DisplayMember = "Display";

comboBox1.ValueMember = "Id";

[VB.NET]

Dim list As New DataTable()

list.Columns.Add(New DataColumn("Display", GetType(String)))

list.Columns.Add(New DataColumn("Id", GetType(Integer)))

list.Rows.Add(list.NewRow())

list.Rows.Add(list.NewRow())

list.Rows.Add(list.NewRow())

list.Rows(0)(0) = "one" '

list.Rows(0)(1) = 1 '

list.Rows(1)(0) = "two" '

list.Rows(1)(1) = 2 '

list.Rows(2)(0) = "three" '

list.Rows(2)(1) = 3 '

comboBox1.DataSource = list

comboBox1.DisplayMember = "Display"

comboBox1.ValueMember = "Id"




© 2001-06 Copyright George Shepherd.

22. Windows Forms RichTextBox FAQ Home

22.1 How can I create and save a RTF file?

22.2 How can I get a string that contains RTF format codes into a RichTextBox?

22.3 How do I make the RichTextBox support drag and drop?

22.4 How do I set the color and font in a RichEditBox?

22.5 How can I change the FontStyle of a selection without losing the styles that are present?

22.6 How can I programmatically position the cursor on a given line and character of my richtextbox?

22.7 How can I load an embedded rich text file into a richtextbox?

22.8 How can I print my rich text?

22.9 Where can I find more information on the RTF specification?

22.10 How can I add a hyperlink to a RichTextBox control?



22.1 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

}

}

22.2 How can I get a string that contains RTF format codes into a RichTextBox?

Use the Rtf property of the control.

richTextBox1.Rtf = @"{\rtf1\ansi\ansicpg1252\deff0\deflang1033{\fonttbl{\f0\fswiss\fcharset0 Arial;}}\viewkind4\uc1\pard\b\i\f0\fs20 This is bold italics.\par }";

22.3 How do I make the RichTextBox support drag and drop?

1) Set the AllowDrop property to true
2) Add handlers for both the DragEnter and DragDrop event

this.richTextBox1.DragEnter += new System.Windows.Forms.DragEventHandler(this.richTextBox1_DragEnter);

this.richTextBox1.DragDrop += new System.Windows.Forms.DragEventHandler(this.richTextBox1_DragEnter);

....

private void richTextBox1_DragEnter(object sender,

System.Windows.Forms.DragEventArgs e)

{

if (((DragEventArgs)e).Data.GetDataPresent(DataFormats.Text))

((DragEventArgs)e).Effect = DragDropEffects.Copy;

else

((DragEventArgs)e).Effect = DragDropEffects.None;

}

private void richTextBox1_DragDrop(object sender, DragEventArgs e)

{

// Loads the file into the control.

richTextBox1.LoadFile((String)e.Data.GetData("Text"), System.Windows.Forms.RichTextBoxStreamType.RichText);

}

Here are VB snippets.

AddHandler Me.richTextBox1.DragEnter, New System.Windows.Forms.DragEventHandler(AddressOf Me.richTextBox1_DragEnter)

AddHandler Me.richTextBox1.DragDrop, New System.Windows.Forms.DragEventHandler(AddressOf Me.richTextBox1_DragEnter)

.....

Private Sub richTextBox1_DragEnter(sender As Object, e As System.Windows.Forms.DragEventArgs)

If CType(e, DragEventArgs).Data.GetDataPresent(DataFormats.Text) Then

CType(e, DragEventArgs).Effect = DragDropEffects.Copy

Else

CType(e, DragEventArgs).Effect = DragDropEffects.None

End If

End Sub 'richTextBox1_DragEnter

Private Sub richTextBox1_DragDrop(sender As Object, e As DragEventArgs)

' Loads the file into the control.

richTextBox1.LoadFile(CType(e.Data.GetData("Text"), [String]), System.Windows.Forms.RichTextBoxStreamType.RichText)

End Sub 'richTextBox1_DragDrop

22.4 How do I set the color and font in a RichEditBox?

You use the SelectionFont and SelectionColor properties. Make sure the control had focus. Then the following code will set the currently selected text to a red-bold-courier font. If no text is currently selected, then any new text typed (or inserted) will be red-bold-courier.

[C#]

richTextBox1.Focus();

richTextBox1.SelectionColor = Color.Red;

richTextBox1.SelectionFont = new Font ("Courier", 10, FontStyle.Bold);

[VB.NET]

richTextBox1.Focus()

richTextBox1.SelectionColor = Color.Red

richTextBox1.SelectionFont = new Font ("Courier", 10, FontStyle.Bold)

22.5 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 <>

{

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 <>

{

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 <>

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;

}

22.6 How can I programmatically position the cursor on a given line and character of my richtextbox?

There are a couple different methods that can be used here. The first changes focus, so may not be possible if you have controls that fire validation. The second uses interop, which requires full trust.
Method 1: Eric Terrell suggested this solution in an email to winformsfaq@syncfusion.com.

The richtextbox control contains a Lines array property, one entry for every line. Each line entry has a Length property. With this information, you can position the selection cursor using code such as:

private void GoToLineAndColumn(RichTextBox RTB, int Line, int Column)

{

int offset = 0;

for (int i = 0; i <>

{

offset += RTB.Lines[i].Length + 1;

}

RTB.Focus();

RTB.Select(offset + Column, 0);

}

(Note: you may want to store this.ActiveControl to be retrieved after calling Select()).
Method 2:

const int SB_VERT = 1;

const int EM_SETSCROLLPOS = 0x0400 + 222;

[DllImport("user32", CharSet=CharSet.Auto)]

public static extern bool GetScrollRange(IntPtr hWnd, int nBar, out int lpMinPos, out int lpMaxPos);

[DllImport("user32", CharSet=CharSet.Auto)]

public static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, POINT lParam);

[StructLayout(LayoutKind.Sequential)]

public class POINT

{

public int x;

public int y;

public POINT()

{

}

public POINT(int x, int y)

{

this.x = x;

this.y = y;

}

}

// Example -- scroll the RTB so the bottom of the text is always visible.

int min, max;

GetScrollRange(richTextBox1.Handle, SB_VERT, out min, out max);

SendMessage(richTextBox1.Handle, EM_SETSCROLLPOS, 0, new POINT(0, max - richTextBox1.Height));

22.7 How can I load an embedded rich text file into a richtextbox?

You use the LoadFile method of the RichTextBox, passing it a streamreader based on the resource. So include your RTF file as an embedded resource in your project, say RTFText.rtf. Then load your richtextbox with code such as

Stream stream = this.GetType().Assembly.GetManifestResourceStream("MyNameSpace.RTFText.rtf");

if (stream != null)

{

StreamReader sr = new StreamReader(stream);

richTextBox1.LoadFile(stream, RichTextBoxStreamType.RichText);

sr.Close();

}

Here is a VB snippet. Depending on your default namespace settings, you may not need explicit reference to the namespace in the GetManifestResourceStream argument.

Dim stream As Stream = Me.GetType().Assembly.GetManifestResourceStream("MyNameSpace.RTFText.rtf")

If Not (stream Is Nothing) Then

Dim sr As New StreamReader(stream)

richTextBox1.LoadFile(stream, RichTextBoxStreamType.RichText)

sr.Close()

End If

22.8 How can I print my rich text?

There is no direct support for printing rich text in the .NET Framework. To print it, you can use interop with the SendMessage API and these three messages to do your printing.

EM_SETTARGETDEVICE : specify the target device
EM_FORMATRANGE : format part of a rich edit control's contents for a specific device
EM_DISPLAYBAND : send the output to the device

Here is a link to a MSDN article by Martin Muller that implements this interop solution. Getting WYSIWYG Print Results from a .NET RichTextBox

22.9 Where can I find more information on the RTF specification?

This site has a lot of good information on the RTF specification: http://www.dubois.ws/software/RTF/.

22.10 How can I add a hyperlink to a RichTextBox control?

To add a hyperlink to the RichTextBox, so that it opens up the link you click on, ensure that DetectUrls property is set to True and call:

[C#]

private void richTextBox1_LinkClicked(object sender, System.Windows.Forms.LinkClickedEventArgs e)

{

System.Diagnostics.Process.Start(e.LinkText);

}

[VB.NET]

Private Sub richTextBox1_LinkClicked(ByVal sender As Object, ByVal e As System.Windows.Forms.LinkClickedEventArgs)

System.Diagnostics.Process.Start(e.LinkText)

End Sub




© 2001-06 Copyright George Shepherd.

23. Windows Forms ListView FAQ Home

23.1 How do I add SubItems to a ListView control?

23.2 When I call ListViewItem.Selected = true;, why doesn't the item get selected?

23.3 How do I unselect the selected items in a ListView programatically?

23.4 I am trying to programmatically change the ForeColor and BackColor properties of subitems in a listview. Why doesn't this work?

23.5 How do I implement custom column sorting in a listview?

23.6 How do I programmatically select an item in my listview?

23.7 How can I sort a column in a ListView?

23.8 How can I implement an owner drawn listview?

23.9 How can I tell which column (subitem) has been clicked on in my listview?



23.1 How do I add SubItems to a ListView control?

Try code such as:

ListViewItem item = new ListViewItem("NewItem");

item.SubItems.AddRange(new string[]{"SubItem1", "SubItem2")};

listView1.Items.Add(item);

listView1.Items.Add(new ListViewItem(new string[]{"item1", "item2", "item3", "item4"});

listView1.View = View.Details;

23.2 When I call ListViewItem.Selected = true;, why doesn't the item get selected?

Make sure the ListView has focus when you set the Selected property. For example, if this code is in the click handler for a button, this button will have the focus, and the selection in the list will fail. Just set the focus back to the list before you set the Selected property.

23.3 How do I unselect the selected items in a ListView programatically?

Simply do the following:

this.listView1.SelectedItems.Clear();

[C#]

[VB]

Me.listView1.SelectedItems.Clear()

23.4 I am trying to programmatically change the ForeColor and BackColor properties of subitems in a listview. Why doesn't this work?

Make sure the item's UseItemStyleForSubItems property is set to false.

ListViewItem item1 = new ListViewItem("item1",0);

//this line makes things work

item1.UseItemStyleForSubItems = false;

//set fore & back color of next sub item

item1.SubItems.Add("1", Color.Black, Color.LightGreen, Font);

item1.SubItems.Add("44");

item1.SubItems.Add("3");

//As long as UseItemStyleForSubItems is false, you can later set the colors with code such as

item1.SubItems[2].BackColor = Color.Pink;

23.5 How do I implement custom column sorting in a listview?

You ceate a class the implements the IComparer inteface. This interface has a single method that accepts two objects, and returns positive integers if the first object is larger than the second, negative integers if the first object is less than the second object, and returns zero if they are the same. Once you have this class, then you handle the listview's ColumnClick event to set the property ListViewItemSorter to point to an instance of this class. You can download a sample project. Here are some snippets.

public class SorterClass : IComparer

{

private int _colNum = 0;

public SorterClass(int colNum)

{

_colNum = colNum;

}

//this routine should return -1 if xy and 0 if x==y.

// for our sample we'll just use string comparison

public int Compare(object x, object y)

{

System.Windows.Forms.ListViewItem item1 = (System.Windows.Forms.ListViewItem) x;

System.Windows.Forms.ListViewItem item2 = (System.Windows.Forms.ListViewItem) y;

if(int.Parse(item1.SubItems[_colNum].Text) <>

return -1;

else if(int.Parse(item1.SubItems[_colNum].Text) > int.Parse(item2.SubItems[_colNum].Text))

return 1;

else

return 0;

}

}

//usage...

private void listView1_ColumnClick(object sender, System.Windows.Forms.ColumnClickEventArgs e)

{

//don't sort col 0

if(e.Column > 0)

{

SorterClass sc = new SorterClass(e.Column);

listView1.ListViewItemSorter = sc;

}

}

23.6 How do I programmatically select an item in my listview?

To select the i-th item, you can use code such as

//Make sure the listview has focus

listView1.Focus();

listView1.Items[i].Selected = true;

23.7 How can I sort a column in a ListView?

This Microsoft KB article provides a step by step sample.

23.8 How can I implement an owner drawn listview?

Carlos Perez explains how to do this in an article and a sample on codeproject.com. In this sample, he does an owner-drawn listview so he can implement custom sorting with a column header that contains a up/down icon to indicate the sorted column and order.

23.9 How can I tell which column (subitem) has been clicked on in my listview?

Here is a solution offered by Bharat Patel of Microsoft in the microsoft.public.dotnet.languages.csharp newgroup. The attached solution contains both C# and VB.NET projects. The solution use Interop with the LVM_GETSUBITEMRECT window's message to loop through each subitem's bounds rectangle until it finds the one that contains the specified mouse click point.




© 2001-06 Copyright George Shepherd.

24. Windows Forms TreeView FAQ Home

24.1 How do I implement Drag and Drop support between two TreeViews?

24.2 How do I make the TreeView scroll when I drag an item to the top or bottom?

24.3 How do I display checkboxes in the nodes of a treeview?

24.4 When I right-click a tree node, it does not become selected. How can I make it be selected on a right-click?

24.5 When I get the SelectedNode in the treeview's Click event, it is the old selection. How do I get the newly selected node?

24.6 How can I get a tooltip to vary from node to node in my treeview?

24.7 How can I determine the node level of a node in my treeview?

24.8 How can I populate a TreeView Control with XML Data?

24.9 How can I clone/copy all the nodes from one TreeView Control to another?

24.10 How do I programmatically select a node in a TreeView control?

24.11 Can I select multiple nodes in a TreeView Control?

24.12 How can I display a context menu when the user right-clicks on a node in the TreeView control?

24.13 How can I ensure that a node is selected when the user clicks along the line of a node?



24.1 How do I implement Drag and Drop support between two TreeViews?

In a posting in the Microsoft.Windows.Forms newsgroup, Brian Roder (Microsoft) gives VB.Net code snippets to handle the DragEnter, ItemDrag and DragDrop events that provide a solution to this problem. You can get C# code in this sample, TreeViewDnD. Here is some sample handlers.

private void treeView2_DragDrop(object sender, System.Windows.Forms.DragEventArgs e)

{

TreeNode newNode;

if( e.Data.GetDataPresent("System.Windows.Forms.TreeNode", false))

{

Point pt;

TreeNode destinationNode;

pt = treeView2.PointToClient(new Point(e.X, e.Y));

destinationNode = treeView2.GetNodeAt(pt);

newNode = (TreeNode) e.Data.GetData("System.Windows.Forms.TreeNode");

if(!destinationNode.Equals(newNode))

{

//destinationNode.Nodes.Add(newNode.Clone());

destinationNode.Nodes.Add((TreeNode) newNode.Clone());

destinationNode.Expand();

//Remove original node

newNode.Remove();

}

}

}

private void treeView2_DragEnter(object sender, System.Windows.Forms.DragEventArgs e)

{

e.Effect = DragDropEffects.Move;

}

private void treeView2_ItemDrag(object sender, System.Windows.Forms.ItemDragEventArgs e)

{

DoDragDrop(e.Item, DragDropEffects.Move);

}

24.2 How do I make the TreeView scroll when I drag an item to the top or bottom?

When you drag an item within the TreeView, you can handle the DragOver event for a drag-drop. If you want to drag-drop into a spot that's not currently visible, you can scroll the TreeView by handling the DragOver event:

[C#]

private void treeView1_DragOver(object sender, System.Windows.Forms.DragEventArgs e)

{

TreeView tv = sender as TreeView;

Point pt = tv.PointToClient(new Point(e.X,e.Y));

int delta = tv.Height - pt.Y;

if ((delta <> 0))

{

TreeNode tn = tv.GetNodeAt(pt.X, pt.Y);

if (tn.NextVisibleNode != null)

tn.NextVisibleNode.EnsureVisible();

}

if ((delta > tv.Height / 2) && (delta <>

{

TreeNode tn = tv.GetNodeAt(pt.X, pt.Y);

if (tn.PrevVisibleNode != null)

tn.PrevVisibleNode.EnsureVisible();

}

}

[VB.NET]

Private Sub treeView1_DragOver(sender As Object, e As System.Windows.Forms.DragEventArgs)

If TypeOf sender is TreeView Then

Dim tv As TreeView = CType(sender, TreeView)

Dim pt As Point = tv.PointToClient(New Point(e.X, e.Y))

Dim delta As Integer = tv.Height - pt.Y

If delta <> 0 Then

Dim tn As TreeNode = tv.GetNodeAt(pt.X, pt.Y)

If Not (tn.NextVisibleNode Is Nothing) Then

tn.NextVisibleNode.EnsureVisible()

End If

End If

If delta > tv.Height / 2 And delta <>

Dim tn As TreeNode = tv.GetNodeAt(pt.X, pt.Y)

If Not (tn.PrevVisibleNode Is Nothing) Then

tn.PrevVisibleNode.EnsureVisible()

End If

End If

End If

End Sub 'treeView1_DragOver

24.3 How do I display checkboxes in the nodes of a treeview?

Set the TreeView.CheckBoxes property to true.

24.4 When I right-click a tree node, it does not become selected. How can I make it be selected on a right-click?

Handle the treeview's mousedown event, and if it is the right-click, then explicitly set focus to th enode under the click.

private void treeView1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)

{

if(e.Button == MouseButtons.Right)

{

treeView1.SelectedNode = treeView1.GetNodeAt (e.X ,e.Y );

}

}

24.5 When I get the SelectedNode in the treeview's Click event, it is the old selection. How do I get the newly selected node?

Try using the AfterSelect event instead of the Click event. The Click event is inherited from Control.Click and occurs before the new selection is set into SelectedNode. The AfterSelect event is fired after the newly selected node is placed in the SelectedNode property. This code illustrates these events.

private void treeView2_AfterSelect(object sender, System.Windows.Forms.TreeViewEventArgs e)

{

TreeNode node = treeView2.SelectedNode;

Console.WriteLine("AfterSelect:" + node.ToString());//from tree

Console.WriteLine("AfterSelect:" + e.Node.ToString());//from event args

}

private void treeView2_Click(object sender, System.EventArgs e)

{

TreeNode node = treeView2.SelectedNode;

if(node == null)

Console.WriteLine("Click: (none)");

else

Console.WriteLine("Click: " + node.ToString());

}

24.6 How can I get a tooltip to vary from node to node in my treeview?

Try using a MouseMove event handler and checking to see if you have moved to a new node, and if so, set a new tiptext.

[C#]

private int oldNodeIndex = -1;

private ToolTip toolTip1;

private void Form1_Load(object sender, System.EventArgs e)

{

this.toolTip1 = new System.Windows.Forms.ToolTip();

this.toolTip1.InitialDelay = 300; //half a second delay

this.toolTip1.ReshowDelay = 0;

}

private void treeView1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)

{

TreeNode tn = this.treeView1.GetNodeAt(e.X, e.Y);

if(tn != null)

{

int currentNodeIndex = tn.Index;

if(currentNodeIndex != oldNodeIndex)

{

oldNodeIndex = currentNodeIndex;

if(this.toolTip1 != null && this.toolTip1.Active)

this.toolTip1.Active = false; //turn it off

this.toolTip1.SetToolTip(this.treeView1, string.Format("tooltip: node {0}", oldNodeIndex));

this.toolTip1.Active = true; //make it active so it can show

}

}

}

[VB.NET]

Private oldNodeIndex As Integer = - 1

Private toolTip1 As ToolTip

Private Sub Form1_Load(sender As Object, e As System.EventArgs)

Me.toolTip1 = New System.Windows.Forms.ToolTip()

Me.toolTip1.InitialDelay = 300 'half a second delay

Me.toolTip1.ReshowDelay = 0

End Sub 'Form1_Load

Private Sub treeView1_MouseMove(sender As Object, e As System.Windows.Forms.MouseEventArgs)

Dim tn As TreeNode = Me.treeView1.GetNodeAt(e.X, e.Y)

If Not (tn Is Nothing) Then

Dim currentNodeIndex As Integer = tn.Index

If currentNodeIndex <> oldNodeIndex Then

oldNodeIndex = currentNodeIndex

If Not (Me.toolTip1 Is Nothing) And Me.toolTip1.Active Then

Me.toolTip1.Active = False 'turn it off

End If

Me.toolTip1.SetToolTip(Me.treeView1, String.Format("tooltip: node {0}", oldNodeIndex))

Me.toolTip1.Active = True 'make it active so it can show

End If

End If

End Sub 'treeView1_MouseMove

24.7 How can I determine the node level of a node in my treeview?

Here is a code snippet suggested by Mattias Sjögren on the microsoft.public.dotnet.languages.csharp newsgroup.

[C#]

public int NodeLevel(TreeNode node)

{

int level = 0;

while ((node = node.Parent) != null) level++;

return level;

}

[VB.NET]

Public Sub NodateLevel(ByVal node as TreeNode) As Integer

Dim level as Integer = 0

While Not node Is Nothing

node = node.Parent

level = level + 1

End While

End Sub

24.8 How can I populate a TreeView Control with XML Data?

The following articles on MSDN give you step by step instructions on how you can populate a TreeView Control with data from an XML file.
C#: Populate a TreeView Control with XML Data in Visual C# .NET
VB.NET: Populate a TreeView Control with XML Data in Visual Basic .NET

24.9 How can I clone/copy all the nodes from one TreeView Control to another?

The following code snippet demonstrates how you can clone or copy all the nodes in TreeView1 to TreeView2 by clicking on Button1.

[C#]

private void IterateTreeNodes (TreeNode originalNode, TreeNode rootNode)

{

foreach( TreeNode childNode in originalNode.Nodes)

{

TreeNode newNode = new TreeNode(childNode.Text);

newNode.Tag = childNode.Tag;

this.treeView2.SelectedNode = rootNode;

this.treeView2.SelectedNode.Nodes.Add(newNode);

IterateTreeNodes(childNode, newNode);

}

}

//Button Click code

private void button1_Click(object sender, System.EventArgs e)

{

foreach( TreeNode originalNode in this.treeView1.Nodes)

{

TreeNode newNode = new TreeNode(originalNode.Text);

newNode.Tag = originalNode.Tag;

this.treeView2.Nodes.Add(newNode);

IterateTreeNodes(originalNode, newNode);

}

}

[VB.NET]

Private Sub IterateTreeNodes(ByVal originalNode As TreeNode, ByVal rootNode As TreeNode)

Dim childNode As TreeNode

For Each childNode In originalNode.Nodes

Dim NewNode As TreeNode = New TreeNode(childNode.Text)

NewNode.Tag = childNode.Tag

Me.treeView2.SelectedNode = rootNode

Me.treeView2.SelectedNode.Nodes.Add(NewNode)

IterateTreeNodes(childNode, NewNode)

Next

End Sub

'Button Click code

Private Sub button1_Click(ByVal sender As Object, ByVal e As System.EventArgs)

Dim originalNode As TreeNode

For Each originalNode In Me.treeView1.Nodes

Dim NewNode As TreeNode = New TreeNode(originalNode.Text)

NewNode.Tag = originalNode.Tag

Me.treeView2.Nodes.Add(NewNode)

IterateTreeNodes(originalNode, NewNode)

Next

End Sub

24.10 How do I programmatically select a node in a TreeView control?

You need to set the HideSelection property of the TreeView to false and call:

[C#]

//Select the first node

this.treeView1.SelectedNode = this.treeView1.Nodes[0];

[VB.NET]

'Select the first node

Me.treeView1.SelectedNode = Me.treeView1.Nodes(0)

24.11 Can I select multiple nodes in a TreeView Control?

The Treeview control does not support multiple selections but there are samples posted at GotDotNet and at arsdesign.com which demonstrates how this feature can be implemented.

24.12 How can I display a context menu when the user right-clicks on a node in the TreeView control?

You can display a context menu when a user right-clicks on a node by listening to the TreeView's MouseUp event as shown below:

[C#]

private void treeView1_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)

{

if(e.Button == MouseButtons.Right)

{

Point ClickPoint = new Point(e.X,e.Y);

TreeNode ClickNode = treeView1.GetNodeAt(ClickPoint);

if(ClickNode == null) return;

// Convert from Tree coordinates to Screen coordinates

Point ScreenPoint = treeView1.PointToScreen(ClickPoint);

// Convert from Screen coordinates to Formc coordinates

Point FormPoint = this.PointToClient(ScreenPoint);

// Show context menu

contextmenu.MenuItems.Clear();

contextmenu.MenuItems.Add("Item1");

contextmenu.MenuItems.Add("Item2");

contextmenu.Show(this,FormPoint);

}

}

[VB.NET]

Private Sub treeView1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)

If e.Button = MouseButtons.Right Then

Dim ClickPoint As Point = New Point(e.X,e.Y)

Dim ClickNode As TreeNode = treeView1.GetNodeAt(ClickPoint)

If ClickNode Is Nothing Then

Return

End If

' Convert from Tree coordinates to Screen coordinates

Dim ScreenPoint As Point = treeView1.PointToScreen(ClickPoint)

' Convert from Screen coordinates to Formc coordinates

Dim FormPoint As Point = Me.PointToClient(ScreenPoint)

' Show context menu

contextmenu.MenuItems.Clear()

contextmenu.MenuItems.Add("Item1")

contextmenu.MenuItems.Add("Item2")

contextmenu.Show(this,FormPoint)

End If

End Sub

24.13 How can I ensure that a node is selected when the user clicks along the line of a node?

A click event will be fired but a node will not be selected when the user clicks to the right of a node. This code snippets show how you can ensure that a node is selected in this scenario:

[C#]

private void treeView1_Click(object sender, System.EventArgs e)

{

treeView1.SelectedNode = treeView1.GetNodeAt(treeView1.PointToClient(Cursor.Position));

}

[VB.NET]

Private Sub treeView1_Click(ByVal sender As Object, ByVal e As System.EventArgs)

treeView1.SelectedNode = treeView1.GetNodeAt(treeView1.PointToClient(Cursor.Position))

End Sub




© 2001-06 Copyright George Shepherd.

25. Windows Forms Button FAQ Home

25.1 How do I autosize a button to fit its text?

25.2 How can I decorate a button face with custom drawing?

25.3 How can I put a bitmap or icon on a button face?

25.4 How can I trigger a button click event?

25.5 How can I get button to fire a click event at specific time intervals while the mouse is down like a scrollbar button?



25.1 How do I autosize a button to fit its text?

Get a Graphics object for the button and use its MeasureString method to compute the width you need.

Graphics g = button1.CreateGraphics();

float w = g.MeasureString(button1.Text, button1.Font).Width;

g.Dispose();

button1.Width = (int) w + 12; // 12 is for the margins

25.2 How can I decorate a button face with custom drawing?

Subclass Button and add a custom Paint event handler that does you custom drawing.

public class MyButton : System.Windows.Forms.Button

{

public MyButton()

{

this.Paint += new System.Windows.Forms.PaintEventHandler(this.button1_Paint);

}

private void button1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)

{

//custom drawing

Pen pen2 = new Pen(Color.Red);

pen2.Width = 8;

e.Graphics.DrawLine(pen2, 7, 4, 7, this.Height - 4);

pen2.Width = 1;

e.Graphics.DrawEllipse(pen2, this.Width - 16 , 6, 8, 8);

}

}

25.3 How can I put a bitmap or icon on a button face?

You can use the Button.Image property to add an image to a button face. Use the Button.ImageAlign (and possibly Button.TextAlign) to layout your button face.

You can also implement custom drawing on a button face as described in the FAQ entitled "How can I decorate a button face with custom drawing".

25.4 How can I trigger a button click event?

Use the button's public method PerformClick.

button1.PerformClick();

25.5 How can I get button to fire a click event at specific time intervals while the mouse is down like a scrollbar button?

Shawn Burke posted the following solution on the microsoft.public.dotnet.framework.windowsforms newsgroup.

public class RepeatButton : Button

{

private Timer timer1;

public int Interval

{

get

{

return Timer.Interval;

}

set

{

Timer.Interval = value;

}

}

private Timer Timer

{

get

{

if (timer1 == null)

{

// create and setup our timer.

timer1 = new Timer();

timer1.Tick += new EventHandler(OnTimer);

timer1.Enabled = false;

}

return timer1;

}

}

protected override void OnMouseDown(MouseEventArgs me)

{

base.OnMouseDown(me);

// turn on the timer

Timer.Enabled = true;

}

protected override void OnMouseUp(MouseEventArgs me)

{

// turn off the timer

Timer.Enabled = false;

base.OnMouseUp(me);

}

private void OnTimer(object sender, EventArgs e)

{

// fire off a click on each timer tick

//

OnClick(EventArgs.Empty);

}

}




© 2001-06 Copyright George Shepherd.

26. Windows Forms TabControl FAQ Home

26.1 How do color the tabs on my TabControl?

26.2 How do I programatically select a Tab Page?

26.3 Why do the order of the tabs keep changing when opening and closing the Form?

26.4 How do I force the focus to be on a text box in a tab page when the application gets loaded?

26.5 For a TabControl, how do I make the tabs on the tab pages appear on the bottom instead of on the right?

26.6 How do I use code to insert or delete tabpages in a TabControl?

26.7 How do I dynamically hide/unhide tabs in a TabControl?

26.8 How do I prevent the user from changing the selected tab page?

26.9 How can I drag and drop TabPages between TabControls?



26.1 How do color the tabs on my TabControl?

Ken Tucker offers this solution. Set the TabControl's DrawMode to OwnerDraw, and then handle the DrawItem event to draw things yourself. Here are both VB and C# sample projects that display a gradient tab for the active tabpage.

26.2 How do I programatically select a Tab Page?

There are a couple of ways you could do select a tab page programmatically:

[C#]

//Select the second Tab Page

this.tabControl.SelectedTab = this.tabPage2

or

//Select Second Tab

this.tabControl.SelectedIndex= 1;

[VB.NET]

'Select the second Tab Page

Me.tabControl.SelectedTab = Me.tabPage2

or

'Select Second Tab

Me.tabControl.SelectedIndex= 1

26.3 Why do the order of the tabs keep changing when opening and closing the Form?

This seems to be a known issue with the TabControl designer. The designer seems to automatically reorder the tabs while serializing changes made in the designer.

To work around this issue, in your constructor, after the call to InitializeComponent, you could remove all the tab pages and add them back in the desired order.

26.4 How do I force the focus to be on a text box in a tab page when the application gets loaded?

Listen to the Form's Activate event and set focus on the text box (using the Focus method). The common mistake is to try to set Focus in the Form_Load event. This is not possible because no Controls are visible at this time and hence focus cannot be set at this time.

26.5 For a TabControl, how do I make the tabs on the tab pages appear on the bottom instead of on the right?

Set the TabControl.Alignment property to TabAlignment.Bottom.

tabControl1.Alignment = TabAlignment.Bottom;

You can also change the tabs into buttons using the Appearance property and TabAppearance enums.

26.6 How do I use code to insert or delete tabpages in a TabControl?

To delete a tabpage, you use the tabControl1.Controls.Remove method. To add a new page as the last tab, use the tabControl1.Controls.Add method. Here is some sample code.

//remove the selected tab

tabControl1.Controls.Remove(tabControl1.SelectedTab);

//add a new tabpage as the last tab

tabControl1.Controls.Add(new TabPage("new Page"));

There does not appear to be support in the framework for inserting a tab at a particular position. A work around might be to save the current tabpage controls, clear the Controls collection, and then add the saved controls back to the Controls collection inserting a new tab. Here is some code that does this.

private void InsertTab(int tabNumber, ref TabControl tabControl)

{

int limit = tabControl.Controls.Count;

if(tabNumber <> limit)

{

tabControl.Controls.Add(new TabPage("new Page"));

return;

}

int target = tabControl.SelectedIndex;

//save the exisiting pages & clear the controls

Control [] c = new Control[limit];

tabControl.Controls.CopyTo(c, 0);

tabControl.Controls.Clear();

//add the earlier pages

for (int i = 0; i <>

tabControl.Controls.Add(c[i]);

//insert the page

tabControl.Controls.Add(new TabPage("new Page"));

//add the later pages

for (int i = target; i <>

tabControl.Controls.Add(c[i]);

//select the new page

tabControl.SelectedIndex = target;

}

26.7 How do I dynamically hide/unhide tabs in a TabControl?

It's a common mistake to try to use the Visible property of the TabPage to make the tab invisible. But this does not work (The Visible property of the TabPage is essentially obsolete). The TabControl doesn't provide you an easy way to do so.

The workaround is to remove and add the TabPage from the TabControl whenever you want to hide/unhide it. Refer to our other faq on how to insert/delete tab pages in a TabControl for more information.

26.8 How do I prevent the user from changing the selected tab page?

You can use the TabPage's Validating event to prevent a new tab page selection. Here are the steps:

1) Every time the user selects a new tab, make sure that the corresponding tab page gets the focus. You can do so as follows:

// In C#

private void tabControl1_SelectedIndexChanged(object sender,

System.EventArgs e)

{

tabControl1.TabPages[tabControl1.SelectedIndex].Focus();

tabControl1.TabPages[tabControl1.SelectedIndex].CausesValidation = true;

}

'VB.Net

Private Property sender,() As tabControl1_SelectedIndexChanged(object

End Property

Private Function e)() As System.EventArgs

tabControl1.TabPages(tabControl1.SelectedIndex).Focus()

tabControl1.TabPages(tabControl1.SelectedIndex).CausesValidation = True

End Function

Note that CausesValidation should be set to True since you will be listening to the Validating event in the next step. You will also have to add some code like above when the TabControl is shown the very first time (like in the Form_Load event handler).

2) Listen to the TabPage's Validating event (which will be called when the user clicks on a different tab page) and determine whether the user should be allowed to change the selected tab page.

// In C#

private void tabPage1_Validating(object sender,

System.ComponentModel.CancelEventArgs e)

{

if(!checkValidated.Checked)

e.Cancel = true;

}

' In VB.Net

Private Sub tabPage1_Validating(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs)

If Not checkValidated.Checked Then

e.Cancel = True

End If

End Sub

26.9 How can I drag and drop TabPages between TabControls?

The following code snippet shows how you can drag a TabPage from TabControl1 and drop it into TabControl2 (whose AllowDrop property must be set to True): $$ [C#] Source TabControl private void tabControl1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e) { if (e.Button == MouseButtons.Left) { this.tabControl1.DoDragDrop(this.tabControl1.SelectedTab,DragDropEffects.All); } } //Target TabControl private void tabControl2_DragEnter(object sender, System.Windows.Forms.DragEventArgs e) { if(e.Data.GetDataPresent(typeof(TabPage))) { e.Effect = DragDropEffects.Move; } else e.Effect = DragDropEffects.None; } private void tabControl2_DragDrop(object sender, System.Windows.Forms.DragEventArgs e) { TabPage DropTab = (TabPage)(e.Data.GetData (typeof(TabPage))); this.tabControl2.TabPages.Add (DropTab); } [VB.NET] 'Source TabControl Private Sub tabControl1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) If e.Button = MouseButtons.Left Then Me.tabControl1.DoDragDrop(Me.tabControl1.SelectedTab,DragDropEffects.All) End If End Sub 'Target TabControl Private Sub tabControl2_DragEnter(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) If e.Data.GetDataPresent(Type.GetType(TabPage)) Then e.Effect = DragDropEffects.Move Else e.Effect = DragDropEffects.None End If End Sub Private Sub tabControl2_DragDrop(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Dim DropTab As TabPage = CType((e.Data.GetData(Type.GetType(TabPage))), TabPage) Me.tabControl2.TabPages.Add (DropTab) End Sub $$




© 2001-06 Copyright George Shepherd.

27. Windows Forms TextBox FAQ Home

27.1 How can I prevent the beep when enter is hit in textbox?

27.2 How do I disable pasting into a TextBox (via Ctrl + V and the context menu)?

27.3 How can I disable the right-click context menu in my textbox?

27.4 How do I format numbers, dates and currencies in a TextBox?

27.5 How do I browse for, and read a text file into an TextBox?

27.6 How do I send a EM_XXXX message to a textbox to get some value such as line index in C#?

27.7 How do I prevent a control from receiving focus when it receives a mouseclick?

27.8 How do I make my textbox use all upper (or lower) case characters?

27.9 I have a delete key shortcut for my main menu. When my textbox is being edited, pressing delete activates this menu items instead of being processed by the TextBox. How can I get my TextBox to handle this delete?

27.10 How can I use a TextBox to enter a password?

27.11 How can I place a TextBox in overwrite mode instead of insert mode?

27.12 How can I make a ReadOnly TextBox ignore the mousedowns so that you cannot scroll the text or set the cursor?

27.13 How can I restrict the characters that my textbox can accept?

27.14 How do I set several lines into a multiline textbox?

27.15 When I set a TextBox to Readonly or set Enabled to false, the text color is gray. How can I force it to be the color specified in the ForeColor property of the TextBox.

27.16 How can I make the focus move to the next control when the user presses the Enter key in a TextBox?



27.1 How can I prevent the beep when enter is hit in textbox?

You can prevent the beep when the enter key is pressed in a TextBox by deriving the TextBox and overriding OnKeyPress.

[C#]

public class MyTextBox : TextBox

{

protected override void OnKeyPress(KeyPressEventArgs e)

{

if(e.KeyChar == (char) 13)

e.Handled = true;

else

base.OnKeyPress (e);

}

}

[VB.NET]

Public Class MyTextBox

Inherits TextBox

Protected Overrides Sub OnKeyPress(e As KeyPressEventArgs)

If e.KeyChar = CChar(13) Then

e.Handled = True

Else

MyBase.OnKeyPress(e)

End If

End Sub 'OnKeyPress

End Class 'MyTextBox

27.2 How do I disable pasting into a TextBox (via Ctrl + V and the context menu)?

First set the ContextMenu property of the TextBox to a dummy, empty ContextMenu instance. This will prevent the default context menu from showing. Then, override the ProcessCmdKey method as follows in a TextBox derived class:

// In C#

protected override bool ProcessCmdKey(ref Message msg, Keys keyData)

{

if(keyData == (Keys.Control | Keys.V))

return true;

else

return base.ProcessCmdKey(ref msg, keyData);

}

' In VB.Net

Protected Overrides Function ProcessCmdKey(ByRef msg As Message, ByVal keyData As Keys) As Boolean

If keyData =(Keys.Control | Keys.V) Then

Return True

Else

Return MyBase.ProcessCmdKey( msg, keyData)

End If

End Function

27.3 How can I disable the right-click context menu in my textbox?

You can set the ContextMenu property of the TextBox to a dummy, empty ContextMenu instance.

27.4 How do I format numbers, dates and currencies in a TextBox?

Each type has a ToString method that can be used to accomplished formatting. Also, you can use the String.Format method to format things as well. To format dates, use the ToString member of DateTime. You may want to use the InvariantInfo setting (see below) to get culture-independent strings.

27.5 How do I browse for, and read a text file into an TextBox?

You use the Frameworks OpenFileDialog to implement this functionailty.

using System.Text;

using System.IO;

....

private void button1_Click(object sender, System.EventArgs e)

{

OpenFileDialog dlg = new OpenFileDialog();

dlg.Title = "Open text file" ;

dlg.InitialDirectory = @"c:\" ;

dlg.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*" ;

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

{

StreamReader sr = File.OpenText(dlg.FileName);

string s = sr.ReadLine();

StringBuilder sb = new StringBuilder();

while (s != null)

{

sb.Append(s);

s = sr.ReadLine();

}

sr.Close();

textBox1.Text = sb.ToString();

}

}

27.6 How do I send a EM_XXXX message to a textbox to get some value such as line index in C#?

There is a protected SendMessage call you can use for this purpose, so you have to derive from TextBox.

public MyTextBox : TextBox

{

private const int EM_XXXX = 0x1234;

public int LineIndex

{

get

{

return base.SendMessage(EM_XXXX, 0, 0);

}

}

}

(from sburke_online@microsoft..nospam..com on microsoft.public.dotnet.framework.windowsforms)

27.7 How do I prevent a control from receiving focus when it receives a mouseclick?

You can set the control's Enabled property to false. This will prevent clicking but also gives the disabled look.

There is a ControlStyles.Selectable flag that determines whether the control can get focus or not. But it does not appear to affect some controls such as TextBox. But you can prevent the TextBox from getting focus by overriding its WndProc method and ignoring the mouse down.

public class MyTextBox : TextBox

{

const int WM_LBUTTONDOWN = 0x0201;

protected override void WndProc(ref System.Windows.Forms.Message m)

{

if(m.Msg == WM_LBUTTONDOWN)

return;

base.WndProc(ref m);

}

}

27.8 How do I make my textbox use all upper (or lower) case characters?

Use the CharacterCasing property of the TextBox.

textBox1.CharacterCasing = CharacterCasing.Upper;

// textBox1.CharacterCasing = CharacterCasing.Lower;

27.9 I have a delete key shortcut for my main menu. When my textbox is being edited, pressing delete activates this menu items instead of being processed by the TextBox. How can I get my TextBox to handle this delete?

Subclass the TextBox and override its PreProcessMessage method.

public class MyTextBox : TextBox

{

const int WM_KEYDOWN = 0x100;

const int WM_KEYUP = 0x101;

public override bool PreProcessMessage( ref Message msg )

{

Keys keyCode = (Keys)(int)msg.WParam & Keys.KeyCode;

if((msg.Msg == WM_KEYDOWN || msg.Msg == WM_KEYUP)

&& keyCode == Keys.Delete)

{

return false;

}

return base.PreProcessMessage(ref msg);

}

}

27.10 How can I use a TextBox to enter a password?

Set the TextBox.PasswordChar property for the textbox.

textBox1.PasswordChar = '\u25CF';

27.11 How can I place a TextBox in overwrite mode instead of insert mode?

You can handle the textbox's KeyPress event and if you want the keypress to be an overwrite, just select the current character so the keypress will replace it. The attached sample has a derived textbox that has an OverWrite property and a right-click menu that allows you to toggle this property.

The snippet below shows you a KeyPress handler that automatically does an overwrite if the maxlength of the textbox has been hit. This does not require a derived class.

private void textBox1_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)

{

if(textBox1.Text.Length == textBox1.MaxLength && textBox1.SelectedText == "")

{

textBox1.SelectionLength = 1;

}

}

27.12 How can I make a ReadOnly TextBox ignore the mousedowns so that you cannot scroll the text or set the cursor?

You can do this by deriving the TextBox, overriding the WndProc method and ignoring these mousedowns.

[C#]

public class MyTextBox : TextBox

{

protected override void WndProc(ref System.Windows.Forms.Message m)

{ // WM_NCLBUTTONDOWN WM_LBUTTONDOWN

if(this.ReadOnly && (m.Msg == 0xa1 || m.Msg == 0x201))

{

return; //ignore it

}

base.WndProc(ref m);

}

}

[VB.NET]

Public Class MyTextBox

Inherits TextBox

Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)

' WM_NCLBUTTONDOWN WM_LBUTTONDOWN

If Me.ReadOnly AndAlso(m.Msg = &HA1 OrElse m.Msg = &H201) Then

Return 'ignore it

End If

MyBase.WndProc(m)

End Sub 'WndProc

End Class 'MyTextBox

27.13 How can I restrict the characters that my textbox can accept?

You can handle the textbox's KeyPress event and if the char passed in is not acceptable, mark the events argument as showing the character has been handled. Below is a derived TextBox that only accepts digits (and control characters such as backspace, ...). Even though the snippet uses a derived textbox, it is not necessary as you can just add the handler to its parent form.

[C#]

public class NumbersOnlyTextBox : TextBox

{

public NumbersOnlyTextBox()

{

this.KeyPress += new KeyPressEventHandler(HandleKeyPress);

}

private void HandleKeyPress(object sender, KeyPressEventArgs e)

{

if(!char.IsDigit(e.KeyChar) && !char.IsControl(e.KeyChar))

e.Handled = true;

}

}

[VB.NET]

Public Class NumbersOnlyTextBox

Inherits TextBox

Public Sub New()

AddHandler Me.KeyPress, AddressOf HandleKeyPress

End Sub 'New

Private Sub HandleKeyPress(sender As Object, e As KeyPressEventArgs)

If Not Char.IsDigit(e.KeyChar) And Not Char.IsControl(e.KeyChar) Then

e.Handled = True

End If

End Sub 'HandleKeyPress

End Class 'NumbersOnlyTextBox

27.14 How do I set several lines into a multiline textbox?

There are a several of ways to do this. Here are a few:

1) Insert a carraige return-linefeed, "\r\n", between your lines.

textBox1.Text = "This is line 1.\r\nThis is line 2";

// or textBox1.Text = stringvar1 + "\r\n" + stringvar2;

2) Use the Environment.NewLine property. This property is normally set to "\r\n".

textBox1.Text = "This is line 1." + Environment.NewLine + "This is line 2";

3) Use the Lines property of the TextBox. Make sure you populate your array before you set the property.

string[] arr = new string[2];

arr[0] = "this is line1";

arr[1] = "this is line 2";

textBox3.Lines = arr;

27.15 When I set a TextBox to Readonly or set Enabled to false, the text color is gray. How can I force it to be the color specified in the ForeColor property of the TextBox.

Felix Wu gives this solution in the microsoft.public.dotnet.frameworks.windowsforms newgroup.

You can download a VB.NET sample.

Override the OnPaint event of the TextBox. For example:

protected override void OnPaint(PaintEventArgs e)

{

SolidBrush drawBrush = new SolidBrush(ForeColor); //Use the ForeColor property

// Draw string to screen.

e.Graphics.DrawString(Text, Font, drawBrush, 0f,0f); //Use the Font property

}

Note: You need to set the ControlStyles to "UserPaint" in the constructor.

public MyTextBox()

{

// This call is required by the Windows.Forms Form Designer.

this.SetStyle(ControlStyles.UserPaint,true);

InitializeComponent();

// TODO: Add any initialization after the InitForm call

}

27.16 How can I make the focus move to the next control when the user presses the Enter key in a TextBox?

Add a handler for your TextBox's KeyDown event. (This assumes you set the AcceptsReturn property to False). Then in your KeyDown eventhandler, have code such as:

[C#]

if (e.KeyCode = Keys.Enter)

SendKeys.Send("{TAB}");

[VB.NET]

If e.KeyCode = Keys.Enter Then

SendKeys.Send("{TAB}")

EndIf




© 2001-06 Copyright George Shepherd.

28. Windows Forms Cursors FAQ Home

28.1 I set the wait cursor using Cursor.Current = Cursors.WaitCursor;. Why does does it disappear before I want it to?

28.2 How do I change the cursor for a control?

28.3 How to convert a Cursor class to a .cur file?

28.4 How to load and display a cursor from a resource manifest?



28.1 I set the wait cursor using Cursor.Current = Cursors.WaitCursor;. Why does does it disappear before I want it to?

Setting the Current property changes the cursor and stops the processing of mouse events. Setting the cursor back to Cursors.Default restarts the mouse event processing and displays the proper cursor for each control. If a DoEvents is called before you reset the cursor back to the default, this will also start up the mouse event processing and you will lose the particular cursor you set. So, if your WaitCursor is disappearring, one explanation might be that DoEvents is getting called.

Here is some code that sets a WaitCursor.

Cursor oldCursor = Cursor.Current;

Cursor.Current = Cursors.WaitCursor;

try

{

// Do your processing that takes time...

// eg. let's wait for 2 seconds...

DateTime dt = DateTime.Now.AddSeconds(2);

while(dt > DateTime.Now)

{ //do nothing

}

}

finally

{

Cursor.Current = oldCursor;

}

28.2 How do I change the cursor for a control?

Try

button1.Cursor = new System.Windows.Forms.Cursor(@"C:\winnt\cursors\hnodrop.cur");

28.3 How to convert a Cursor class to a .cur file?

protected void WriteCursorToFile(Cursor cursor, string fileName)

{

byte[] blob = TypeDescriptor.GetConverter(typeof(System.Windows.Forms.Cursor)).ConvertTo(cursor, typeof(byte[])) as byte[];

if(blob != null)

{

FileStream fileStream = new FileStream(fileName, FileMode.Create);

fileStream.Write(blob, 0, blob.Length);

fileStream.Flush();

fileStream.Close();

}

else

MessageBox.Show("Unable to convert Cursor to byte[]");

}

28.4 How to load and display a cursor from a resource manifest?

System.IO.Stream strm = null;

try

{

string curName = "WindowsApplication1.Cursor1.cur";

strm = this.GetType().Assembly.GetManifestResourceStream(curName);

this.Cursor = new Cursor(strm);

}

catch(Exception ex)

{

MessageBox.Show(ex.Message.ToString());

}

finally

{

if(strm != null)

strm.Close();

}

No comments: