WinForms FAQ - Patterns

Find answers for the most frequently asked questions
Expand All Collapse All

You can do this by starting a new thread and executing Application.Run for the status dialog form when the background thread starts running. To communicate changes in percentage use BeginInvoke to executes a specific delegate asynchronously on the thread that the form was created on.

Download the ProgressThread progressthread.zip sample for a complete implementation of a BackgroundThreadStatusDialog class that shows a status dialog in a separate thread.

In order to use BackgroundThreadStatusDialog from your code you have to update the Progress inside your loop and check the IsCanceled state to detect if the user pressed the Cancel button.


    private void button1_Click(object sender, System.EventArgs e)
    {
      BackgroundThreadStatusDialog statusDialog = new BackgroundThreadStatusDialog();
      try
      {
        for (int n = 0; n < 1000; n++)
        {
          statusDialog.Percent = n/10;
          int ticks = System.Environment.TickCount;
          while (System.Environment.TickCount - ticks < 10)
            ;
          if (statusDialog.IsCanceled)
            return;
        }
        statusDialog.Close();
        MessageBox.Show(statusDialog.IsCanceled ? ''Canceled'' : ''Success'');
      }
      finally
      {
        statusDialog.Close();
      }
    }
Permalink

You can do so by calling BeginInvoke on your delegates. Unfortunately, you can’t call BeginInvoke() on the event member directly. You can invoke BeginInvoke()only if the delegate’s internal list of sink callbacks (actually other delegates) has only one target in it. If you have more than one, the delegate throws an exception. The workaround is to iterate over the event delegate internal invocation list, calling BeginInvoke() on everyone of them. You access the internal list using the GetInvocationList() method. Here is an example:


public delegate void NumberChangedDelegate(int num);

public class MySource
{
    public event NumberChangedDelegate m_NumberChangedEvent;

    public void FireEventAsynch(int num)
    {
        Delegate[] delegates = m_NumberChangedEvent.GetInvocationList();
        foreach (Delegate del in delegates)
        {
            NumberChangedDelegate sink = (NumberChangedDelegate) del;
            sink.BeginInvoke(num, null, null);
        }
    }

    public void FireEvent(int num)
    {
        m_NumberChangedEvent(num);
    }
}

From Juval Löwy at www.idesign.net; from his article in the .Net Insight online magazine at www.fawcette.com.

Permalink

Compiled from the newsgroup posts by Andy Fish and Brian:

You can do this in the DragDrop event handler of your control:


[C#]
try
{
	//Use e.Data.GetData('UniformResourceLocator') to get the URL
    	System.IO.Stream ioStream=
                 	(System.IO.Stream)e.Data.GetData('FileGroupDescriptor');
    	byte[] contents = new Byte[512];
    	ioStream.Read(contents,0,512);
    	ioStream.Close();
    	StringBuilder sb = new StringBuilder();
	//The magic number 76 is the size of that part of the
	//FILEGROUPDESCRIPTOR structure before the filename starts - cribbed
	//from another usenet post.
    	for (int i=76; contents[i] != 0; i++) 
    	{
        		sb.Append((char)contents[i]);
    	}
    	if (!sb.ToString(sb.Length-4,4).Equals('.url'))
    	{
        		throw new Exception('filename does not end in ’.url’');
    	}
    	filename = sb.ToString(0,sb.Length-4);

}
catch(Exception ex)
{
    	MessageBox.Show(ex.ToString());
}

[VB.Net]
Try
	’Use e.Data.GetData('UniformResourceLocator') to get the URL
    	System.IO.Stream ioStream=
                 	CType(e.Data.GetData('FileGroupDescriptor'), System.IO.Stream)
    	Dim contents() As Byte =  New Byte(512) {} 
    	ioStream.Read(contents,0,512)
    	ioStream.Close()
    	Dim sb As StringBuilder =  New StringBuilder() 
 	
	’The magic number 76 is the size of that part of the
	’FILEGROUPDESCRIPTOR structure before the filename starts - cribbed
	’from another usenet post.
    	Dim i As Integer
    	For  i = 76 To contents(i)  0 Step  i + 1
        		sb.Append(CType(contents(i), Char))
    	Next
    	If Not sb.ToString(sb.Length-4,4).Equals('.url') Then
        		Throw New Exception('filename does not end in ’.url’')
    	End If
    	filename = sb.ToString(0,sb.Length-4)
Catch ex As Exception
    	MessageBox.Show(ex.ToString())
End Try
Permalink

This is because of a bug in the .net framework. When tooltips are set on a control that hosts other controls within it (like the numeric updown), tooltips are not shown on those child controls.

To workaround this issue, do the following in code:


[C#]
foreach(Control c in this.numericUpDown1.Controls)
{
	this.tooltip.SetToolTip(c, 'mytooltip');
}

[VB.Net]
Dim c As Control
For Each c In Me.numericUpDown1.Controls
	Me.tooltip.SetToolTip(c, 'mytooltip')
Next
Permalink

Share with

Couldn't find the FAQs you're looking for?

Please submit your question and answer.