Form Component
Current version : 1.3.0.0

Visit http://www.dev2net.com to get updates and latest news.

  1. Wait forms
  2. Pop-up forms
  3. Installing the component
  4. Using the component
  5. Appendix A : Form Component Object
  6. Appendix B : Examples
Form Component is a .NET assembly that enables developers to smoothly implement 2 sets of forms to their applications: Animated / interactive wait forms and pop-up forms. Both contains a rich set of properties that allow developers to apply different effects like fading, sliding, locking, embedded or custom backgrounds, embedded or custom icons/animated images to the forms.

Screen shots (click to enlarge)


Wait forms
The wait form is used to show a "work is in progress" form when the main application is doing some time consuming work. The wait form is created in the background on a separate thread and therefore runs independently of the main application.

The wait form implements a progress bar and a cancel button event, which the main application can subscribe to. It can be set with the main application as owner or without an owner. The developer can adjust several properties to customize the wait form (see the Object Model description in appendix A).


Pop-up forms (info message)
The pop-up form (or info message form) is used to show pop-up forms just like the Windows Messenger and similar applications. Unlike the wait form, the pop-up forms are bound to the main thread of the application and is supposed to be shown as a result of another process, return value from a method and similar operations while their main thread is not working.

Up to 3 pop-up forms can be shown at the same time and each can be locked or closed independently. Messages for pop-up are stored in a message queue and are shown by the message dispatcher when a message slot becomes available. The showing is fully automated and the slots are occupied with new messages as soon as they become available. Locked pop-up forms will fall into a lower slot, if the slot becomes available and there are no new messages in the queue.

The user can view already shown messages in the history queue from the Message Dispatch Center and current message queue can be cleared if required.

The developer can adjust several properties to customize each pup-up forms (see the Object Model description in appendix A).


Installing the component
To install the component from top, do the following: The features of the component are now ready for use. Both the wait form and the pop-up form are created with a set of default value for each property, which will allow you to run the forms without changing anything. Of course, you probably would like to add some customization to the forms, so explore the Object Model in appendix A to see the complete list of properties or go to Appendix B to have a closer look on the sample solution files.


Using the component (simple example using default properties) Above example is a very simple example on creating a pop-up form, by using the default settings available.

IMPORTANT: If you have not yet purchased a valid license for the form component, a nagging message will appear and the component throws an exception, stopping the pop-up message from appearing. This will occur the first time the SendMessage method is invoked and after that, each 3rd time the SendMessage is again invoked. This is also why the empty try/catch is used, to prevent the thrown exception from halting the code.

After adding the two dev2net namespaces, your private variable creates an instance of the FormComponent class. When this instance is created, it automatically creates the message queue and the message dispatcher, which are used for showing the pop-up forms in a controlled fashion.

In the button click event, a simple message is sent to the queue. Since this is the first message, the pop-up is shown almost instantly by the message dispatcher. "Almost", because the thread controlling the message queue, has an interval for scanning for new messages in the queue. You can adjust the scanning time span in the properties. If you click the button several times after each other, several pop-up forms will be shown (up to 3 at the same time). After the first pop-up form is hidden after its timeout has occurred, the next message (if any) in the queue, will pop-up.


Appendix A : Form Component Object Model

Class FormComponentConstructor
The FormComponentConstructor class contains basic construction of the message queue and the message dispatcher. If enabled, the Message Dispatch Center (MDC) is also constructed, when the class is initialized.

Namespace : dev2net.Forms

Constructor Description Applies to version
FormComponentConstructor() Constructs the form component with default properties in property class FormComponentConstructorProperties. 1.0.0.0
FormComponentConstructor (FormComponentConstructorProperties) Constructs the form component with the properties specified in the parsed property class FormComponentConstructorProperties. 1.0.0.0

Method Description Applies to version
Dispose() Disposes the message dispatcher. The dispatcher is working on a separate thread and need to be shut down when the creating application is terminated. Typically this method is invoked in the main applications Close / Closing event. Any messages pending in the message queue or in history, are removed. 1.0.0.0
ShowMessage(TitleText, BodyText) Overloaded. Send a pop-up message to the message queue with the given title and body text and default pop-up properties. From the queue, the message is shown at the next available message slot.
Returns void.
1.0.0.0
ShowMessage(MessageProperties, TitleText, BodyText) Overloaded. Send a pop-up message to the message queue with the given title and body text, using the properties defined in the InfoMessageProperties class. From the queue, the message is shown at the next available message slot.
Returns void.
1.0.0.0
ShowMessage(MessageProperties) Overloaded. Send a pop-up message to the message queue using the properties defined in the InfoMessageProperties class. From the queue, the message is shown at the next available message slot.
Returns void.
1.2.0.0
ShowWait(MessageProperties, HeaderText, BodyText) Overloaded. Shows the wait form on the screen, using the defined properties.
Returns: An initialized WaitMessage class.
1.0.0.0

Property name Description Applies to version
MessagesInHistory List<InfoMessageProperties>
Returns a list of messages in the message history queue. In other words, a complete list of all the messages that has been shown on the screen during the lifetime of the component. The maximum number of messages in the history queue, is set in the FormComponentConstructorProperties.MaxMessagesInHistory property.
Read-only
1.0.0.0
MessagesInQueue Integer
The number of messages currently pending in the message queue, waiting to be shown by the message dispatcher. 
Read-only
1.0.0.0


Class FormComponentConstructorProperties
The FormComponentConstructorProperties class contains properties used by the FormComponentConstructor class.

Namespace : dev2net.Forms

Property name Description Applies to version
DispatcherWaitInMilliseconds Integer
The number of miliseconds the dispatcher should wait before it checks for new messages in the queue.
Default value is 500 miliseconds.
1.0.0.0
MaxMessagesInHistory Integer
The maximum number of messages we can store in the history queue. When the maximum number is reached, the oldest info message is overwritten. No exceptions are thrown if the maximum number is reached. The messages in the history are available as long as the component is alive.
Default value is 200 info messages.
1.0.0.0
MaxMessagesInQueue Integer
The maximum number of info messages allowed in the waiting queue. If the number is exceeded, an application exception is thrown.
Default value is 20 info messages.
1.0.0.0
MessageFormHeight Integer
Sets the height on the popup forms. IMPORTANT: Once this value is set, it cannot be changed during the lifetime of a formcomponent instance. This since the flow of the popup slot calculation depends on the height of all popup forms remains the same.
Default value is 90.
1.0.0.0
MessageFormWidth Integer
Sets the width on the popup forms. IMPORTANT: Once this value is set, it cannot be changed during the lifetime of a formcomponent instance. This since the flow of the popup slot calculation depends on the width of all popup forms remains the same.
Default value is 90.
1.0.0.0
MessagePadding Integer
Leaves each pop-up form on the screen with a padding space between them.
Default value is 5.
1.0.0.0
UseDispatchCenter Boolean
Determine if the Message Dispatch Center (MDC) should be available in the system tray. If True, the MDC icon will be visible and clickable in the system tray. If False, the icon is not visible and the MDC can not be used.
Default value is False.
1.0.0.0


Class InfoMessage
The InfoMessage class is the constructor for pop-up messages. This constructor should not be called directly, since it is called internally when a message leaves the message queue and, eventually, is shown in a free message slot.

There are no methods or properties available for this class.

Namespace : dev2net.Forms.Info


Class InfoMessageProperties
The InfoMessageProperties class contains properties used by the SendMessage method in FormComponentConstructor.

Namespace : dev2net.Forms.Info

Property name Description Applies to version
BackgroundType Object
Sets the background used in the info message form. It can be either a fixed background, a color definition or a custom image object. Use the FormFactory.BackgroundTypes to use one of the build-in background images..
Default value is "GRAYWHITE" (see list in FormFactory.BackgroundTypes).
1.0.0.0
BodyText String
Text displayed in the body area of the info message form.
Default value is empty.
1.0.0.0
BodyTextLink String
Displays the text in the body area as a link, if this property is filled. The text must be a valid process descriptor, fx. a URL, filepath, executable shortcut (fx. mailto: myname@mail.com) etc.
Default value is empty.
1.0.0.0
InfoImage Object
Sets the image used on the pop-up form. It can be a fixed image or an animated GIF image. Use either the build-in icons in FormFactory.IconTypes or custom image object.
Important : If an animated image is used on several info message forms, they /// are limited to the main thread execution. As such, the main thread may not animate ALL images, but only the image on the last shown info message form. It is recommended /// only to use fixed images (none animated).
Default value image type "PEOPLE" (see list in FormFactory.IconTypes).
1.0.0.0
LockMessage Boolean
Locks the message to the screen, if set to True. The pop-up form will remain on the screen until the unlock button or close button is clicked.
Default value is False.
1.0.0.0
ShowSeconds Integer
Number of seconds the pop-up form stays on the screen, before it is hidden. If LockMessage is set to True, this property is ignored.
Default value is 6 seconds.
1.0.0.0
TitleText String
Text displayed in the title area of the info message form.
Default value is empty.
1.0.0.0
UseFade Boolean
Fade the form from invisible to fully displayed and back, if set to True.
Default value is True.
1.0.0.0
UseFormBorder Boolean
Displays a border around the pop-up form, if set to True.
Default value is False.
1.0.0.0
UseImageBorder Boolean
Displays a border around the info image, if set to True.
Default value is False.
1.0.0.0
UseSlide Boolean
Slides the form into the message slot, if set to True.
Default value is True.
1.0.0.0
SubTitleText String
If filled, shows a subtitle beneath the title area.
Default value is empty.
1.2.0.0


Class WaitMessage
The WaitMessage class is the constructor for wait forms. This constructor should not be called directly, since it is called internally when the FormComponentConstructor.ShowWait method is invoked.

Namespace : dev2net.Forms.Wait


Method Description Applies to version
Dispose() Disposes the wait form worker. The wait form is working on a separate thread and need to be shut down when the creating application is terminated. Since the class is derived from IDisposable interface, this method is invoked when the wait form closes. Best practice for calling the ShowWait method, is to encapsulate it in a using statement. Once the using statement ends, the instance is disposed automatically. See Appendix B for some example on invoking a ShowWait method. 1.0.0.0


Class WaitMessageProperties
The WaitMessageProperties class contains properties used by the SendWait method in FormComponentConstructor.

Namespace : dev2net.Forms.Wait

Property name Description Applies to version
AnimateImageSpeed Integer
To allow animation without interfering with the main UI in the WaitImage (if GIF is used), the image is split into frames and animated in the background in a separate thread. You can control the speed of the animation by adjusting this value.
Default value is 100 milliseconds.
1.0.0.0
BackgroundType Object
Sets the background used in the wait message form. It can be either a fixed background, a color definition or a custom image object. Use the FormFactory.BackgroundTypes to use one of the build-in background images.
Default value is "GRAYWHITE" (see list in FormFactory.BackgroundTypes).
1.0.0.0
BodyText String
Text displayed in the body area of the wait message form.
Default value is empty. The value can be set during the entire lifetime of the waitform object.
1.0.0.0
CancelButton Button
When the property "UseCancelButton" is set to true, the cancel button will appear on the wait form. The button is then exposed in this property, so the developer can assign fx. a local click event in the main UI thread, set another text on the button surface or any other property/event/method that a button control offers. 
1.0.0.0
DelaySeconds Integer
Prevents the wait form from showing until the number of seconds in this property has elapsed. Highly recommended, if a time consuming process in some cases can be less than 1 second, then no need to display the wait from until after fx. 2 seconds of the process has passed.
Default value is 0 (no delays).
1.0.0.0
FontColor Color
Set the font color of all text on the wait form.
Default value is Color.Black.
1.0.0.0
HeaderText String
Text displayed in the title area of the wait message form.
Default value is empty. The value can be set during the entire lifetime of the waitform object.
1.0.0.0
ParentForm Form
Sets the parent form as the owner of the wait form.
Default value is null.
1.0.0.0
ProgressbarValue Integer
If the progress bar is displayed, this property can change the current value of the progress bar.
Default value is 0. The value is always indicated as a percentage value, which means the calling application must calculate its own percentage value during a time-consuming process and assign this calculated value to this property.
1.0.0.0
ShowProgressBar Boolean
Displays a progress bar on the wait form, if set to True. The value can be changed using the ProgressbarValue property
Default value is False.
1.0.0.0
ShowWorkTime Boolean
Displays the total work time on the wait form, if set to True.
Default value is True.
1.0.0.0
SuspendState Boolean
Suspends the processing of the waitform from the background, fx. while the parentform is waiting for input from the user.
Default value is false. The value can be set during the entire lifetime of the waitform object.
1.0.0.0
UseCancelButton Boolean
Displays a cancel button on the form, if set to True. The calling application can subscribe to the public click event CancelClick, in which the calling application can dispose the wait form.
Default value is False.

Important : The cancel event will not trigger until the main UI thread releases resources for handling the event. As such (depending on how the calling application is designed), the execution of the event can be delayed for some time.

Recommended : It's recommended to disable the main form (owner of the wait form) during a time-consuming process, to allow the cancel button to become focused. Otherwise the cancel button will require first to obtain focus and the clicked (what the user will experience as double click).
 
1.0.0.0
UseFormBorder Boolean
Displays a border around the pop-up form, if set to True.
Default value is False.
1.0.0.0
UseImageBorder Boolean
Displays a border around the wait image, if set to True.
Default value is False.
1.0.0.0
WaitFormLocation Point
Sets the location of the wait form. This property is only used if no parent form is defined in ParentForm property.
Default value is null.
1.0.0.0
WaitFormOpasity Double
Set the opasity for the waitform. The value is measured in percentage so the value must be set between 0.0 and 1.0, where 0.0 is invisible and 1.0 is full visibility.
Default value is 1.0.
1.0.0.0
WaitFormSize Size
Sets the size of the wait form, overriding the default size at from creation time. Setting the size will allow the calling application to add more text to the body of the wait form, if required.
Default value is Size(250, 65).

Note : The wait form will automatically expand from the given size, if features like progress bar and work timer is enabled. However, it is up to the calling application to ensure a correct size depending on amount of text in the body/header.
1.0.0.0
WaitImage Object
Sets the image used on the wait form. It can be a fixed image or an animated GIF image. Use either the build-in icons in FormFactory.IconTypes or custom image object.
Default value image A_EARTH (see list in FormFactory.IconTypes).
1.0.0.0


Class FormFactory
The FormFactory class is used to hold default properties for background and icons, used in both wait- and info message forms.

Namespace : dev2net.Forms

Enum Description Applies to version
BackgroundTypes Enum
Fixed background types that can be used in both the info form and wait form. The following values are available:

  • GRAYWHITE : Gradient background using gray/white
  • BLUEWHITE : Gradient background using blue/white
  • YELLOWWHITE : Gradient background using yellow/white
  • GREENWHITE : Gradient background using green/white
  • AQUADOMEGREEN : Image background (green aqua dome)
  • AQUADOMEBLUE : Image background (blue aqua dome)
  • AQUADOMEGRAY : Image background (gray aqua dome)
  • ALLWHITE : Gradient background using white only
1.0.0.0
IconTypes Enum
Fixed icon types that can be used in both the info form and wait form. Icon types beginning with A_ are animated icons and are primarily used for the wait form.

  • A_EARTH : Animated earth icon
  • A_LOADING :  Animated classic loading icon
  • ERROR : Regular windows error icon
  • WARNING : Regular windows warning icon 
  • INFO : Regular info icon 
  • PEOPLE : Regular people icon 
  • A_RUNNING : Animated running man icon 
  • A_WAITING :  Animated problem-with-PC icon 
  • DISCUSSION :  Regular discussion icon
  • MAIL : Regular mail icon 
  • RUN : Regular run symbol icon 
  • BACKUP : Regular backup icon
  • USERS : Regular users icon
  • TRANSFORM : Regular transform icon
  • IMPORT : Regular import icon
  • A_PENCIL : Animated pencil icon
  • A_LOADING_ROLLER : Animated classic loading roller icon
  • A_LOADING_ARROWS : Animated classic loading arrows icon
  • A_LOADING_WHEEL : Animated classic loading wheel icon
  • A_LOADING_CLOCK : Animated classic loading clock icon
  • A_LOADING_CIRCLE : Animated classic loading circle icon
1.0.0.0
  • RSS : Regular RSS icon
  • TRASH : Regular trash can icon
  • GEAR: Regular gear icon
  • IE : Regular internet explorer browser icon
  • OPERA : Regular opera browser icon
  • CHROME : Regular chrome browser icon
  • SAFARI : Regular safari browser icon
  • FIREFOX : Regular firefox browser icon 
1.2.0.0



Appendix B : Examples 

The following examples are a demonstration of the wait- and info forms. Not all features are being shown in the examples, but it should provide fundamental knowledge about how methods and properties are used.


Example 1 : Wait form

In the following example for WaitForm, we'll demonstrate 2 solutions. Both solutions creates a DataTable with 100 rows and add this datatable to a DataGridView, while the waitform is running. The difference between the 2 solutions is that the first solution uses the main UI thread to do the DataTable and DataGridView processing, while the second solution uses a background worker. The result is the same, but the aspects are different.

1. solution - Using the main thread : When working on the main thread, the thread has to do perform painting of controls, handle events being fired and more. Adding a heavy process to load fx. data from a database, will take away resources from the thread and some operations will not be processed unless the Application.DoEvents() method is invoked. Implementing this solution is straight forward, but should be limited to smaller processing and not fx. external processing or complex tasks.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using dev2net.Forms;
using dev2net.Forms.Wait;
using System.Threading;

namespace Sample8_WaitFormWithDoEvents
{
    
/* This example shows waitform when simulating some heavy processing on the UI thread. Since the waitform 
     * gets related to this form by owner, we need to call the DoEvents method to pump messages (update the screen, 
     * allowing events etc.) */

    public partial class Form1 : Form
    {
        
/* Setup variables we can use in the entire scope */
        private FormComponentConstructorProperties constructorProperties = new FormComponentConstructorProperties();
        
private FormComponentConstructor componentConstructor = new FormComponentConstructor();
        
private WaitMessageProperties waitProperties = new WaitMessageProperties();
        
private WaitMessage waitMessage;
        
private bool wasCancelled;
        
private DataTable rowTable = new DataTable();

        
public Form1()
        {
            InitializeComponent();
            rowTable.Columns.Add(
"Row number");
            rowTable.Columns.Add(
"Row time");
        }

        
private void button1_Click(object sender, EventArgs e)
        {
            wasCancelled = 
false;

            
/* Set some properties for the waitform */
            waitProperties.BackgroundType = FormFactory.BackgroundTypes.AQUADOMEGRAY;
            waitProperties.WaitImage = FormFactory.IconTypes.A_LOADING_CIRCLE;
            waitProperties.AnimateImageSpeed = 20;
            waitProperties.DelaySeconds = 0;
            waitProperties.UseImageBorder = 
false;
            waitProperties.UseFormBorder = 
false;
            waitProperties.ShowWorkTime = 
true;
            waitProperties.ParentForm = 
this;
            waitProperties.ShowProgressBar = 
true;
            waitProperties.UseCancelButton = 
true;
            waitProperties.WaitFormOpasity = 0.75;  

            
/* We don't want the user to touch the form while we work. You can do this in several ways, fx. disable 
             * all controls on the form or like in this sample, the form itself. */
            this.Enabled = false;
            
            
/* Now start the waitform using our properties. All processing occurs in the UI thread, e.g. when clicking 
             * the start button of this form. By calling the creation of the waitform in a using, the dispose of the 
             * waitform is automatically called when the block finishes. */
            using (waitMessage = componentConstructor.ShowWait(waitProperties, "Sample - Fill grid, 100 rec, DoEvents""Using DoEvents ...."))
            {
                
try
                {
                    
/* We want to be able to cancel, so now assign the cancelbutton with our owncancel event */
                    waitProperties.CancelButton.Click += new EventHandler(CancelButton_Click);

                    
/* Now simulate some processing is going on. In this case we're going to fill at gridview with 
                     * random data.*/
                    FillGridData();
                }
                
catch
                {
                    
/* If you have not purchased a license yet, this will catch all license messages from the component. */
                }
                
finally
                {
                    
/* Enable the form and activate it. Activate is important if the async. cancel has not yet 
                     * completely shut down the wait form  before the control has returned to the main form */
                    this.Enabled = true;
                    
this.Focus();   
                }
            }
        }

        
private void FillGridData()
        {
            
/* Fill a datatable with some random data. In this loop we use a thread to slow the filling down 
             * and we call the DoEvents to make sure everything is rendered and events can be fired. */
            int counter = 0;
            
while (++counter <= 100)
            {
                
/* Update the progress bar */
                waitProperties.ProgressbarValue = counter;

                
/* Update body text */
                waitProperties.BodyText = "Now filling row " + counter.ToString();

                
/* Simulate we collect data for the grid, fx. in a database */
                DataRow row = rowTable.NewRow();
                row[0] = counter.ToString();
                row[1] = 
DateTime.Now.ToLongTimeString();
                rowTable.Rows.Add(row);

                
/* Call DoEvents and sleep a little */
                Application.DoEvents();
                
Thread.Sleep(25);    // 25 miliseconds

                /* Did we click cancel? Then exit */
                if (wasCancelled)
                {
                    
break;
                }
            }

            
/* Now fill the grid */
            waitProperties.BodyText = "Updating the grid..";
            dataGridView1.DataSource = rowTable;

            
/* Required to render the gridview so fx. scrollbars are visible and the grid shows 
             * correct styles */
            dataGridView1.PerformLayout();
        }

        
void CancelButton_Click(object sender, EventArgs e)
        {
            
/* Suspend processing in the waitform until the user has made a choice if he/she wants to 
             * cancel or not. */
            waitProperties.SuspendState = true;
            
try
            {
                
if (MessageBox.Show("Sure you want to cancel?""Cancel?"
                    MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                {
                    wasCancelled = 
true;
                }
            }
            
finally
            {
                
/* Resume processing */
                waitProperties.SuspendState = false;
            }
        }
    }
}

2. solution - Using a background worker : This solution leaves the main thread to handle only tasks like painting controls/forms, handling events and more, while the heavy processing is done in a separate thread, called a background worker. Using a worker is quite simple and it even implements different ways to communicate with the main thread where required. We recommend using a background worker when possible.
 using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using dev2net.Forms;
using dev2net.Forms.Wait;
using System.Threading;

namespace Sample9_WaitformWithWorker
{
   
/* This example shows waitform when simulating some heavy processing in a background worker. This does not
     * require the UI thread to pump messages by calling DoEvents. Many developers consider this to be the 
     * preferred way to do heavy processing, by not letting the UI thread work and instead let a worker handle
     * fx data collection, external processing etc. */

    public partial class Form1 : Form
    {
       
/* Setup variables we can use in the entire scope */
        private FormComponentConstructorProperties constructorProperties = new FormComponentConstructorProperties();
       
private FormComponentConstructor componentConstructor = new FormComponentConstructor();
       
private WaitMessageProperties waitProperties = new WaitMessageProperties();
       
private BackgroundWorker worker;
       
private WaitMessage waitMessage;
       
private DataTable rowTable = new DataTable();

       
public Form1()
        {
            InitializeComponent();

           
/* Datatable setup */
            rowTable.Columns.Add("Row number");
            rowTable.Columns.Add(
"Row time");

           
/* Background worker setup */
            worker = new BackgroundWorker();
            worker.DoWork +=
new DoWorkEventHandler(worker_DoWork);
            worker.WorkerSupportsCancellation =
true;
            worker.RunWorkerCompleted +=
new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
        }

       
private void button1_Click(object sender, EventArgs e)
        {
           
/* Set some properties for the waitform */
            waitProperties.BackgroundType = FormFactory.BackgroundTypes.ALLWHITE;
            waitProperties.WaitImage = FormFactory.IconTypes.A_LOADING_ROLLER;
            waitProperties.AnimateImageSpeed = 1000;
            waitProperties.DelaySeconds = 0;
            waitProperties.UseImageBorder =
false;
            waitProperties.UseFormBorder =
false;
            waitProperties.ShowWorkTime =
true;
            waitProperties.ParentForm =
this;
            waitProperties.ShowProgressBar =
true;
            waitProperties.UseCancelButton =
true;
            waitProperties.WaitFormOpasity = 0.85;

           
/* We don't want the user to touch the form while we work. You can do this in several ways, fx. disable 
             * all controls on the form or like in this sample, the form itself. */
            this.Enabled = false;

           
/* Now start the waitform using our properties. All processing occurs in the backgroundworker, which leaves
             * the UI thread low on processing. This way the UI thread can concentrate on the rendering of the main form
             * and the wait form. And we can eliminate the use for Application.DoEvents. Many developers consider this
             * to be the right way to do heavy processing, by not letting the UI thread work. */
            waitMessage = componentConstructor.ShowWait(waitProperties, "Sample - Fill grid, 100 records, worker", "Using worker ....");
           
try
            {
               
/* We want to be able to cancel, so now assign the cancelbutton with our owncancel event */
                waitProperties.CancelButton.Click += new EventHandler(CancelButton_Click);

               
/* Now simulate some processing is going on. In this case we're going to fill at gridview with 
                 * random data, from a background worker. So now we start the background worker. */
                worker.RunWorkerAsync();
            }
           
catch
            {
               
/* If you have not purchased a license yet, this will catch all license messages from the component. */

                /* We also want to make sure that if an error occured when starting the waitform / worker, we can dispose 
                 * the waitform controlled by calling the dispose. */
                if (waitMessage != null)
                {
                    waitMessage.Dispose();
                }
            }
        }

       
void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
           
/* Now assign the loaded data to the grid */
            waitProperties.BodyText = "Updating the grid..";
            dataGridView1.DataSource = rowTable;

           
/* Required to render the gridview so fx. scrollbars are visible and the grid shows 
             * correct styles */
            dataGridView1.PerformLayout();

           
if (waitMessage != null)
            {
                waitMessage.Dispose();
            }

           
/* Enable the form and focus it. Focus() or Activate() is important if the async. cancel has not yet 
             * completely shut down the wait form before the control has returned to the main form */
            this.Enabled = true;
           
this.Focus();
        }

       
void worker_DoWork(object sender, DoWorkEventArgs e)
        {
           
int counter = 0;
           
while (!worker.CancellationPending)
            {
               
if (++counter > 100 || worker.CancellationPending)
                {
                    e.Cancel =
true;
                   
break;
                }
                
               
/* Update the progress bar */
                waitProperties.ProgressbarValue = counter;

               
/* Update body text */
                waitProperties.BodyText = "Now getting row " + counter.ToString() + " from the database..";

               
/* Simulate we collect data for the grid, fx. in a database */
                DataRow row = rowTable.NewRow();
                row[0] = counter.ToString();
                row[1] =
DateTime.Now.ToLongTimeString();
                rowTable.Rows.Add(row);

               
/* Sleep a little */
                Thread.Sleep(25);    // 25 miliseconds
            }
        }

       
void CancelButton_Click(object sender, EventArgs e)
        {
           
/* In this example, we do also suspend the waitform state. However, since the background worker
             * we are collecting data from, is not stopping while the user makes a decision on the UI thread, 
             * the worker may complete before the user click fx. 'Yes' to cancel. In this case, the dialog 
             * is simply shutdown, because the event will be removed from the queue and control returns to
             * the UI thread. 
             * 
             * Hence, the waitform will also continue to get updated and/or showing animation (if enabled).
             */
            waitProperties.SuspendState = true;
           
try
            {
               
if (MessageBox.Show("Sure you want to cancel?", "Cancel?"
                    MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                {
                   
if (!worker.CancellationPending)
                    {
                        worker.CancelAsync();
                    }
                }
            }
           
finally
            {
               
/* Resume processing */
                waitProperties.SuspendState = false;
            }
        }
    }
}


Example 2 : Info form, the basic solution
This example shows the use of a popup/infomessage with only the default properties set.
using System;
using System.Windows.Forms;
using dev2net.Forms;
using dev2net.Forms.Info;

namespace Sample2_ShowInfoForm
{
   
public partial class Form1 : Form
    {
       
/* The component has a build-in message dispatcher, which allows you to send your messages to the dispatcher queue. 
         * The dispatcher can show up to 3 messages at the same time on the screen, and leave the remaining messages waiting in the queue 
         * (if more messages are sent). The queue has some max. settings for number of messages in the queue, which you can 
         * control (default max. messages in queue is 20).  To maintain the dispatcher while your form is active, the FormComponentConstructor 
         * object must be created like this or in fx. a form load and be available during  the entire lifetime of your application. */
 
       
private FormComponentConstructor fcc = new FormComponentConstructor();

       
public Form1()
        {
            InitializeComponent();
        }

       
private void button1_Click(object sender, EventArgs e)
        {
           
/* Send a message to the dispatcher queue. You can try and click the button fx. 4 times in a row, then the message dispatcher 
             * will show each message as they arrived into the queue, with max. 3 messages at the screen at the same time. */
            try
            {
                fcc.SendMessage(
"Title of the message", "Body of the info message form. Was added to the queue at " + DateTime.Now.ToString());
            }
           
catch  
            { 
               
// Catch all license exceptions here, if your component is not yet licensed 
            } 
        }
    }
}
 


Example 3 : Pop-up form with Message Dispatch Center enabled and with links on locked forms

This example shows how to use popup/infomessage with URL link in the body text and lock feature enabled. It also shows how to add padding between the different popup forms. Finally, it gives an example on how to load and display the Message Dispatch Center, where history can be viewed and message queue can be cleared.
using System;
using System.Windows.Forms;
using dev2net.Forms;
using dev2net.Forms.Info;

namespace Sample7_InfoMessageCustomProperties
{
    
public partial class Form1 : Form
    {
        
private FormComponentConstructor fcc;

        
public Form1()
        {
            InitializeComponent();

            
FormComponentConstructorProperties fccp = new FormComponentConstructorProperties();
            fccp.UseDispatchCenter = 
true;    // Enables the Message Dispatch Center (MDC) in the system tray
            fccp.MessagePadding = 5;          // Set a distance of 5 pixels between each info message form

            fcc = new FormComponentConstructor(fccp);
        }

        
private void button1_Click(object sender, EventArgs e)
        {
            
try
            {
                
/* Set some propertis for each info message form */
                InfoMessageProperties mesgProperties = new InfoMessageProperties();
                mesgProperties.BackgroundType = 
FormFactory.BackgroundTypes.AQUADOMEGREEN;
                mesgProperties.BodyTextLink = 
"http://www.dev2net.com"/* Enables the body text as a new process. Can be an URL, 
                                                                         * a file in the local drives,  open Microsoft Word or any 
                                                                         * other executable application etc. Works like 
                                                                         * the Start/Run of Windows. */ 
                mesgProperties.LockMessage = true;                      /* Don't autohide the message form, leave it on the screen until the 
                                                                         * user closes it or clicks the unlock button */ 
                mesgProperties.InfoImage = FormFactory.IconTypes.DISCUSSION;

                
/* Send the message to the dispatcher queue. You can try and click the button fx. 4 times in a row, then the message dispatcher 
                 * will show each message as they arrived into the queue, with max. 3 messages at the screen at the same time. */
                fcc.SendMessage(mesgProperties, "New website available""Click here to visit it");
            }
            
catch {}
        }

        
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            
/* IMPORTANT: If you have enabled the Message Dispatch Center (MDC), you MUST dispose the component constructor 
             * when your application form is closing/closed to clear it from the system tray. 
             * Without the MDC, this dispose is not required, as the GC will collect the object eventually. */
            fcc.Dispose();
        }
    }
}