Do I really need Application.Run in my Windows Forms application?

G

Guest

I have developed a small API for taking care of a lot of boiler plate stuff
in a multi formed windows application, for example setting up a messaging
thread framework.

New Forms, in the appllication using the API, are subclassed to a Form
contained within the API, and they are controlled (controlled in this
instance means, kept alive, displayed and hidden) at runtime by a thread
whose responsibility is this sole task.

In order to run the application, one also needs to further subclass an item
(BaseFormsApplicationStartup) contained within the API, whose required
parameter is the main Form of the application; for example ...

/ ******************************************************/
public class Startup : BaseFormsApplicationStartup
{
public Startup() : base(new MainUI())
{
AddDialog(new MessageWindow());
AddDialog(new GraphWindow());
AddDialog(new NetworkWindow());
DisplayMainApplicationDialog();
}
[STAThread]
static void Main() { new Startup(); }
}
/ ******************************************************/

The members AddDialog(BaseMessageApplicationWindow) and
DisplayMainApplicationDialog() are defined in the abstract class
BaseFormsApplicationStartup.

AddDialog simply places the application's Form under the control of a
DialogManager object. DisplayMainApplicationDialog, results (eventually) in
an instantiation of the following class for displaying the Form.

/ ******************************************************/
internal sealed class DialogDisplayThread
{
/// <summary>Internal Thread object</summary>
private Thread t = null;
/// <summary>Internal reference to the Form that owns the
Thread</summary>
private Form m_TheForm = null;
/// <summary>Constructor</summary>
/// <param name="f">The System.Windows.Forms.Form to display</param>
internal DialogDisplayThread(Form f)
{
m_TheForm = f;
t = new Thread(new ThreadStart(ThreadProc));
t.Name = f.Name + "DisplayThread";
t.IsBackground = true;
t.Start();
}
/// <summary>The ThreadStart method.</summary>
internal void ThreadProc() { m_TheForm.ShowDialog(); }
}
/ ******************************************************/

NOTE : I've used Form.ShowDialog() as opposed to Form.Show() because
the former is a blocking call, whilst the latter is not and as
soon as it
finishes, the Thread dies, which ultimately results in the Form
being
destroyed.

The point of all of this is that, I do not ever make use of
Application.Run(Form). I do not see this as a problem in itself, however, I
do have a problem in that my main application Form in a particular
implementation (making use of the API) is not displaying label text correctly.

I fire up the application and the Form is displayed, however where there are
System.Windows.Forms.Label controls on the Form, the text is not displayed,
and the control itself is completely transparent (through to the desktop or
underlying window, etc.), until I move the Form and cause an OnPaint event.
This behaviour continues on the form if it should be covered and then
uncovered, this OnPaint does not appear to affect the Label objects.

I have a sneaking suspicion that the problem would "go away" should I make a
call to Application.Run() passing in my main Form, but I'd rather know what
is going wrong so that I can address the issue rather than crowbarring the
API.

Thanks in advance ... if you want more info please do not hesitate to enquire.
 
G

Guest

Odd that the some of the form isn’t actually being painted... I wonder if
some of what you are doing requires the message loop. The major difference
between using it and not is that Application.Run() “Begins running a standard
application message loop on the current thread.â€

From:
http://msdn.microsoft.com/library/d...ystemwindowsformsapplicationclassruntopic.asp

If that is the case, you’ve really got two options, both include calling
Application.Run, either as

new Startup();
Application.Run();

or

Application.Run( new Startup() );

My money however would be to go with the first option in either case.

Brendan


billr said:
I have developed a small API for taking care of a lot of boiler plate stuff
in a multi formed windows application, for example setting up a messaging
thread framework.

New Forms, in the appllication using the API, are subclassed to a Form
contained within the API, and they are controlled (controlled in this
instance means, kept alive, displayed and hidden) at runtime by a thread
whose responsibility is this sole task.

In order to run the application, one also needs to further subclass an item
(BaseFormsApplicationStartup) contained within the API, whose required
parameter is the main Form of the application; for example ...

/ ******************************************************/
public class Startup : BaseFormsApplicationStartup
{
public Startup() : base(new MainUI())
{
AddDialog(new MessageWindow());
AddDialog(new GraphWindow());
AddDialog(new NetworkWindow());
DisplayMainApplicationDialog();
}
[STAThread]
static void Main() { new Startup(); }
}
/ ******************************************************/

The members AddDialog(BaseMessageApplicationWindow) and
DisplayMainApplicationDialog() are defined in the abstract class
BaseFormsApplicationStartup.

AddDialog simply places the application's Form under the control of a
DialogManager object. DisplayMainApplicationDialog, results (eventually) in
an instantiation of the following class for displaying the Form.

/ ******************************************************/
internal sealed class DialogDisplayThread
{
/// <summary>Internal Thread object</summary>
private Thread t = null;
/// <summary>Internal reference to the Form that owns the
Thread</summary>
private Form m_TheForm = null;
/// <summary>Constructor</summary>
/// <param name="f">The System.Windows.Forms.Form to display</param>
internal DialogDisplayThread(Form f)
{
m_TheForm = f;
t = new Thread(new ThreadStart(ThreadProc));
t.Name = f.Name + "DisplayThread";
t.IsBackground = true;
t.Start();
}
/// <summary>The ThreadStart method.</summary>
internal void ThreadProc() { m_TheForm.ShowDialog(); }
}
/ ******************************************************/

NOTE : I've used Form.ShowDialog() as opposed to Form.Show() because
the former is a blocking call, whilst the latter is not and as
soon as it
finishes, the Thread dies, which ultimately results in the Form
being
destroyed.

The point of all of this is that, I do not ever make use of
Application.Run(Form). I do not see this as a problem in itself, however, I
do have a problem in that my main application Form in a particular
implementation (making use of the API) is not displaying label text correctly.

I fire up the application and the Form is displayed, however where there are
System.Windows.Forms.Label controls on the Form, the text is not displayed,
and the control itself is completely transparent (through to the desktop or
underlying window, etc.), until I move the Form and cause an OnPaint event.
This behaviour continues on the form if it should be covered and then
uncovered, this OnPaint does not appear to affect the Label objects.

I have a sneaking suspicion that the problem would "go away" should I make a
call to Application.Run() passing in my main Form, but I'd rather know what
is going wrong so that I can address the issue rather than crowbarring the
API.

Thanks in advance ... if you want more info please do not hesitate to enquire.
 
G

Guest

Brendan,

thanks for that, it is the solution I seem to have stumbled accross (
calling Application.Run() after instantiating my Startup class), and it does
fix the missing text issue.

Does anyone know why this should be the case?

--

--

Of all words of tongue and pen, the saddest are: "It might have been"


Brendan Grant said:
Odd that the some of the form isn’t actually being painted... I wonder if
some of what you are doing requires the message loop. The major difference
between using it and not is that Application.Run() “Begins running a standard
application message loop on the current thread.â€

From:
http://msdn.microsoft.com/library/d...ystemwindowsformsapplicationclassruntopic.asp

If that is the case, you’ve really got two options, both include calling
Application.Run, either as

new Startup();
Application.Run();

or

Application.Run( new Startup() );

My money however would be to go with the first option in either case.

Brendan


billr said:
I have developed a small API for taking care of a lot of boiler plate stuff
in a multi formed windows application, for example setting up a messaging
thread framework.

New Forms, in the appllication using the API, are subclassed to a Form
contained within the API, and they are controlled (controlled in this
instance means, kept alive, displayed and hidden) at runtime by a thread
whose responsibility is this sole task.

In order to run the application, one also needs to further subclass an item
(BaseFormsApplicationStartup) contained within the API, whose required
parameter is the main Form of the application; for example ...

/ ******************************************************/
public class Startup : BaseFormsApplicationStartup
{
public Startup() : base(new MainUI())
{
AddDialog(new MessageWindow());
AddDialog(new GraphWindow());
AddDialog(new NetworkWindow());
DisplayMainApplicationDialog();
}
[STAThread]
static void Main() { new Startup(); }
}
/ ******************************************************/

The members AddDialog(BaseMessageApplicationWindow) and
DisplayMainApplicationDialog() are defined in the abstract class
BaseFormsApplicationStartup.

AddDialog simply places the application's Form under the control of a
DialogManager object. DisplayMainApplicationDialog, results (eventually) in
an instantiation of the following class for displaying the Form.

/ ******************************************************/
internal sealed class DialogDisplayThread
{
/// <summary>Internal Thread object</summary>
private Thread t = null;
/// <summary>Internal reference to the Form that owns the
Thread</summary>
private Form m_TheForm = null;
/// <summary>Constructor</summary>
/// <param name="f">The System.Windows.Forms.Form to display</param>
internal DialogDisplayThread(Form f)
{
m_TheForm = f;
t = new Thread(new ThreadStart(ThreadProc));
t.Name = f.Name + "DisplayThread";
t.IsBackground = true;
t.Start();
}
/// <summary>The ThreadStart method.</summary>
internal void ThreadProc() { m_TheForm.ShowDialog(); }
}
/ ******************************************************/

NOTE : I've used Form.ShowDialog() as opposed to Form.Show() because
the former is a blocking call, whilst the latter is not and as
soon as it
finishes, the Thread dies, which ultimately results in the Form
being
destroyed.

The point of all of this is that, I do not ever make use of
Application.Run(Form). I do not see this as a problem in itself, however, I
do have a problem in that my main application Form in a particular
implementation (making use of the API) is not displaying label text correctly.

I fire up the application and the Form is displayed, however where there are
System.Windows.Forms.Label controls on the Form, the text is not displayed,
and the control itself is completely transparent (through to the desktop or
underlying window, etc.), until I move the Form and cause an OnPaint event.
This behaviour continues on the form if it should be covered and then
uncovered, this OnPaint does not appear to affect the Label objects.

I have a sneaking suspicion that the problem would "go away" should I make a
call to Application.Run() passing in my main Form, but I'd rather know what
is going wrong so that I can address the issue rather than crowbarring the
API.

Thanks in advance ... if you want more info please do not hesitate to enquire.
 
M

Mehdi

thanks for that, it is the solution I seem to have stumbled accross (
calling Application.Run() after instantiating my Startup class), and it does
fix the missing text issue.

Does anyone know why this should be the case?

I don't really have the time to fully understand what you are doing in your
framework, sorry, but one thing that i've noticed is that you are talking
about and using threads. Be very carefull NOT to use multiple threads to
create, show or access your UI elements (Forms or Controls). All your
Controls and classes derived from Control MUST be created, shown and
accessed from the UI thread only. You should never call a function or
access a property of a Control from a worker thread (that is, a thread that
is not the UI thread) or you'll run into loads of troubles.

Apart from that, i do not see any reason why you would have to use
Application.Run. Form.ShowDialog does starts its own message loop so i
would think that it's enough.
 
N

Nicholas Paldino [.NET/C# MVP]

The reason why you use the Application class is because some controls
will not work properly if you don't. I believe the splitter control is one
of these classes. Some controls register message filters with the
Application class to provide certain functionality. If you don't use the
Application.Run method, these controls will have unexpected effects.
 
G

Guest

thanks guys.

--

--

Of all words of tongue and pen, the saddest are: "It might have been"


Nicholas Paldino said:
The reason why you use the Application class is because some controls
will not work properly if you don't. I believe the splitter control is one
of these classes. Some controls register message filters with the
Application class to provide certain functionality. If you don't use the
Application.Run method, these controls will have unexpected effects.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Mehdi said:
I don't really have the time to fully understand what you are doing in
your
framework, sorry, but one thing that i've noticed is that you are talking
about and using threads. Be very carefull NOT to use multiple threads to
create, show or access your UI elements (Forms or Controls). All your
Controls and classes derived from Control MUST be created, shown and
accessed from the UI thread only. You should never call a function or
access a property of a Control from a worker thread (that is, a thread
that
is not the UI thread) or you'll run into loads of troubles.

Apart from that, i do not see any reason why you would have to use
Application.Run. Form.ShowDialog does starts its own message loop so i
would think that it's enough.
 
G

Guest

I have made the Startup class subclass
System.Windows.Forms.ApplicationContext allowing for the following
implementation:

/** ******************************************* */
using System.Windows.Forms;
public abstract class BaseApplicationStartup : ApplicationContext,
IApplicationStartup
{
// implementation
}

public class Startup : BaseFormsApplicationStartup
{
public Startup() : base(new MainUI())
{
AddDialog(new MessageWindow());
/* add other dialogs */
DisplayMainApplicationDialog();
}

[STAThread]
static void Main() { Application.Run(new Startup()); }
}

/** ******************************************* */

This means no special treatment in the Main function, and it also means we
get to call Application.Run and set up the ApplicationMessageLoop which makes
all controls display properly on the forms.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top