Tuesday, October 25, 2011

How to set cursor position in RichTextBox in WinForms

How can we set cursor position in WinForms RichTextBox control? One way of doing it is to use RichTextBox.Select() method. This method takes two parameters. First parameter is a starting character index and second one is the length of the selection.
The following code snippet shows how to set cursor on the current position when mouse rightclick button is clicked.
private void richTextBox1_MouseDown(object sender, MouseEventArgs e)
{
   if (e.Button == System.Windows.Forms.MouseButtons.Right)
   {
      int index = richTextBox1.GetCharIndexFromPosition(e.Location);
      richTextBox1.Select(index, 0);
   }
}

Tuesday, October 11, 2011

Multiple UI threads in WinForms

Most WinForms application has one main UI thread and some background worker threads. And it is very typical and clean way of doing multi-threading in WinForms. But, in some special situaions, you might want to create multiple UI threads so that each thread has each form independently. The following sample shows how to create multiple UI threads in WinForms.

First in Main(), it launches a form called 'MainForm' with Application.Run() method. Application.Run() creates message pump for a UI form, in this case, in main UI thread.

static class Program
{
   /// 
   /// The main entry point for the application.
   /// 
   [STAThread]
   static void Main()
   {
      Application.EnableVisualStyles();
      Application.SetCompatibleTextRenderingDefault(false);
      Application.Run(new MainForm());
   }
}

In Form_Load() of MainForm, we create 3 new Forms from 3 different threads.

public partial class MainForm : Form
{
   public MainForm()
   {
      InitializeComponent();
   }

   private void MainForm_Load(object sender, EventArgs e)
   {
      // Start new UI thread for Form1
      Thread thread1 = new Thread(ShowForm1);
      thread1.Start();

      // Start new UI thread for Form2
      Thread thread2 = new Thread(() => { Form2 f2 = new Form2(); Application.Run(f2); });
      thread2.Start();

      // Start new UI thread for Form3
      Thread thread3 = new Thread(ShowForm3);
      thread3.Start();
   }

   void ShowForm1()
   {
      // message pump with Application.Run()
      Application.Run(new Form1());
   }

   void ShowForm3()
   {
      Form3 f3 = new Form3();
      // Start message pump by using ShowDialog()
      f3.ShowDialog(); 
   }
}

First thread, thread1, runs ShowForm1() function which is simply calls Application.Run() against new Form1 instance. This thread creates new message pump for Form1 and works separately from MainForm.

Second thread, thread2, shows an example of using anonymous delegate to launch Form2. Basically it's the same as ShowForm1().

Third thread, thread3, calls ShowForm3() function where Form3 is launched by using ShowDialog(). If one uses Show() method instead of ShowDialog() here, thread will show the Form3 but then the form will be closed immediately since the thread will exit. ShowDialog begins new message pump for Form3 and will stay until user clicks Close button.


Each UI thread will work separately. Once all forms are closed, the application will be closed.