Some info:
C#
Winforms project in visual studio 2012
.Net framework 4.5
Windows 8.1 OS x64
I am having the strangest bug!
Whenever i use:
private void Main_Load(object sender, EventArgs e)
{
TestForm form = new TestForm();
form.ShowDialog();
}
TestForm is just a stadard form with no controls added.
It will stop the main thread as it should! But instead of waiting for input, it will spawn a new "form" ever 0.5 sec aprox... i took a new solution and tried, and there it worked fine, but in the app im currently working on, it does this when ever it is run somewhere inside or from this form.
Placing the same form code inside a BackGroundWorker, then it works fine.
ONLY inside the main UI form i have, where this error occurs..
Using Show() works as normal, only 1 form opens, but does not work with dialog result :-/
I have no idea why and have never seen this before??
please help.
EDIT:
I did as Roy Dictus suggested, and placed a break point.
This is in my LauncherFrom that load Main:
private void timerHide_Tick(object sender, EventArgs e)
{
this.Hide();
// Open main form IF true else open hidden
var f = new a.Views.Main();
if (Properties.Settings.Default.StartHidden)
{
f.Opacity = 0;
f.Show();
f.Hide();
f.Opacity = 1;
}
else
{
f.Show();
}
// Stop timer
timerHide.Stop();
}
And it looks like timerHide.Stop(); is never being called.
I have used this many times before, and i have a few more ShowDialog() calls that work fine..
So why does this not work for only SOME of the ShowDialog();??
If i remove TestForm.ShowDialog(); from Main_Load() it calls timerHide.Stop(); just fine.
Your code never reaches tiemrHide.Stop(). That's because you show a modal dialog which runs its own message pump. And so your timer fires again and again.
Here's how it goes:
The timer event timerHide_Tick fires, and creates a new main form instance.
The new main form shows a modal dialog in Main_Load.
The modal dialog runs a message pump.
The timer event fires again.
Goto 1.
You need to call Stop() at the very start of timerHide_Tick.
Related
I have some code meant to open a new windows form when one is closed, and yet I get nothing, no error.
I've tried a few different methods for opening a new form on a Form.FormClosed event.
This is the code I have right now:
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
Form1 myForm = new Form1();
myForm.Show();
}
But yet I get no error, nothing.
I'm expecting for a new windows form to be opened when I close another one.
Any help would be appreciated, thanks!
The problem is that as soon as the first Form1 instance closes, your application shuts down and exits because the application message loop is defined with the initial Form instance, and it is just waiting for events on that form until it closes. On closing, the application will exit, opening a new form doesn't stop this process.
You need to adjust the Main() method in Program.cs to look something like this:
[STAThread]
static void Main()
{
// ... Application configuration as required here
new Form1().Show(); // The first form instance is now no longer bound to the Application message loop. Start it before we begin the run loop
Application.Run(); // Don't pass in Form1
}
Your original code should now work. I might add however, this is not a great user experience. Carefully consider what you're trying to achieve, and perhaps consider alternatives - do you just need a "reset form" button? Or is the primary goal to prevent a user from closing the application? If the latter, you can remove the Close icon altogether.
Perhaps something simple to get your going forward.
private Form1 myForm = new Form1(); //Declare the form as a private member variable
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
e.Cancel = true; //Cancel the closing so this object stays alive
this.Visible = false; //Hide this form
myForm.Show(); //Show the next form
}
Please note #pcdevs comment. You'll need a way to indicate the form is being closed/application quiting vs progressing to the next step/form. You might want to look at some CodeProject articles about "C# Winform Wizards", those sequential dialog prompt apps...
I want to hide my form while keeping my application running in background.
I've used notifyIcon and it remains always visible.
I've used "this.Hide();" to hide my form but unfortunately my application gets close (no exception).
I am also using threading and this form is on second thread.
Please tell me how can I solve it.
I am also using threading and this form is on second thread.
My crystal ball says that you've used ShowDialog() to show the form. Yes, calling Hide() on a modal dialog will close it. Necessarily so, a modal dialog normally disables all of the windows in the application. If you hide it then there's no way for the user to get back to the program, there are no windows left to activate. That this form runs on another thread otherwise doesn't factor into the behavior.
You'll need to call Application.Run(new SomeForm()) to avoid this. Now it isn't modal and you can hide it without trouble. But really, do avoid showing forms on non-UI threads. There's no reason for it, your main thread is already quite capable.
add the following event handlers for form resize and notify icon click event
private void Form_Resize(object sender, EventArgs e)
{
if (WindowState == FormWindowState.Minimized)
{
this.Hide();
}
}
private void notifyIcon_Click(object sender, EventArgs e)
{
this.Show();
this.WindowState = FormWindowState.Normal;
}
but this is not close you application
I have 2 forms ...when i start the application..and use the close "X" from the title bar the entire application closes...now when i select an option from the 1st form in my case it is a button "ADD" as its a phonebook application..it goes to the 2nd form as i have used 1stform.hide() and 2ndform.show()...now when i do "X" from the title bar it doesnt shutdown completely as the 1stform is not closed....how to program it in such a way tht any stage the entire application should close
Your first form is set as the startup form. That means whenever it gets closed, your entire application is closed. And conversely, your application does not close until it gets closed. So when you hide the startup form and show the second form, the user closing the second form does not trigger your application closing because they have only closed a secondary, non-modal dialog.
I recommend changing your design so that the startup form is also the main form of your application. No sense trying to work around built-in functionality that can actually be useful. You want the application to quit when the main form is closed, no matter what other child forms are opened.
But the quick-and-dirty solution in your case is to make a call to Application.Exit. That will close all of the currently open forms and quit your application immediately. As I said just above, I don't so much recommend this approach because having to call Application.Exit from every form's FormClosed event handler is a sign that something has gone seriously wrong in your design.
If the single startup form paradigm doesn't work out for you, you should look into taking matters into your own hands and customizing the Main method in your Program.cs source file. See the answers given to this related question for some ideas on how that might work for you.
What you can do is to use the Form's FormClosing event, and add the following code:
Application.Exit();
This will stop the entire application, and close all windows. However, if a background thread is running, the process itself will survive. In this case you can use:
Environment.Exit();
Add a Application.Exit on every forms's Closing event
like this:
Create an closing event handler first
private void Form_ClosingEventhandler()(object sender, CancelEventArgs e)
{
//Perform any processing if required like saving user settings or cleaning resources
Application.Exit();
}
then bind this event to any form you create.
//Where you create new form and show it.
Form1 frm= new Form1();
//set other properties
frm.Closing += new EventHandler(Form_ClosingEventhandler);
Form2 frm2= new Form2();
//set other properties
frm2.Closing += new EventHandler(Form_ClosingEventhandler);
Surely you don't want to shut down the entire application after the user adds a phone number? You just need to make sure that your main window becomes visible again. Write that like this:
private void AddButton_Click(object sender, EventArgs e) {
var frm = new AddPhoneNumber();
frm.StartPosition = FormStartPosition.Manual;
frm.Location = this.Location;
frm.Size = this.Size; // optional
frm.FormClosing += delegate { this.Show(); };
frm.Show();
this.Hide();
}
I have a form in a Windows form application that I want to display on top of a main form, close it, and then immediately show a dialog box using MessageBox.Show(). But the first form is still showing when the message box is shown, and it does not disappear until I click OK on the message box. I tried waiting to show the message box in an event handler for the form's VisibleChanged event and even calling Refresh() on both the form and the main form. Is there a way I can determine when the first form has fully disappeared before displaying the message box?
Edit:
Here is some code that demonstrates how the forms are being shown.
static class Program
{
// The main form is shown like this:
static void Main()
{
Application.Run(new MainForm());
}
}
public class Class1
{
// _modalForm is the first form that is displayed that won't fully go away
// when it is closed.
ModalForm _modalForm;
BackgroundWorker _worker;
public Class1()
{
_modalForm = new ModalForm();
_worker = new BackGroundWorker();
_worker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted
}
public void Method1()
{
_worker.RunWorkerAsync();
// The first form is shown.
_modalForm.ShowDialog();
}
// This code runs in the UI thread.
void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
_modalForm.VisibleChanged += new EventHandler(_modalForm_visibleChanged);
_modalForm.Close();
}
void _modalForm_visibleChanged(object sender, EventArgs e)
{
// When the message box is shown, the other form is still visible
// and remains so until I click OK.
MessageBox.Show("The other form was just closed.");
// Note: I originally tried to use the FormClosed event instead of
// VisibleChanged. Then I tried Deactivate, in attempt to use an event
// that occurred later thinking that might do the trick. VisibleChanged
// is the latest event that I found.
//
}
I'll guess that you are running your code on Windows XP or Vista/Win7 with Aero turned off. Closing a form does not make the pixels on the screen disappear instantly. The Windows window manager sees that the window for the form got destroyed and that this revealed parts of other windows underneath it. It will deliver a WM_PAINT message to let them know that they need to repaint the parts of the window that got revealed.
This will not work properly if one or more of those windows isn't actively pumping a message loop. They can't see the WM_PAINT message. They won't repaint themselves, the pixels of the closed form will remain on the screen.
Find out why these windows are not responding. Hopefully it is your window and the debugger can show you what the UI thread is doing. Make sure it isn't blocking on something or stuck in a loop.
After seeing the edit: there's indeed blocking going on, of a different kind. The MessageBox.Show() call is modal, it prevents the VisibleChanged event from completing. That delays the closing of the form.
Use System.Diagnostics.Debug.WriteLine() or Console.WriteLine() to get diagnostics in a Window Forms app. You'll see it in the Output window. Or simply use a debugger breakpoint.
The Form.FormClosed event is raised when the form completes closing. At this point, all Form.FormClosing event handlers have been run, and none of them canceled the close.
Form.FormClosed replaced Form.Closed (which is deprecated) in the .NET 2.0 framework.
Form.Closed Event
http://msdn.microsoft.com/en-us/library/system.windows.forms.form.closed(VS.71).aspx
I've one MainForm window and from that user can press 3 buttons. Each of the button starts new Form in which user can do anything he likes (like time consuming database calls etc). So i decided to put each of the forms in it's own threads:
private Thread subThreadForRaportyKlienta;
private Thread subThreadForGeneratorPrzelewow;
private Thread subThreadForRaporty;
private void pokazOplatyGlobalne() {
ZarzadzajOplatamiGlobalneDzp varGui = new ZarzadzajOplatamiGlobalneDzp();
varGui.ShowDialog();
}
private void pokazRaportyKlienta() {
RaportyDzpKlient varGui = new RaportyDzpKlient();
varGui.ShowDialog();
}
private void pokazRaportyWewnetrzne() {
RaportyDzp varGui = new RaportyDzp();
varGui.ShowDialog();
}
private void pokazGeneratorPrzelewow() {
ZarzadzajPrzelewamiDzp varGui = new ZarzadzajPrzelewamiDzp();
varGui.ShowDialog();
}
private void toolStripMenuGeneratorPrzelewow_Click(object sender, EventArgs e) {
if (subThreadForGeneratorPrzelewow == null || subThreadForGeneratorPrzelewow.IsAlive == false) {
subThreadForGeneratorPrzelewow = new Thread(pokazGeneratorPrzelewow);
subThreadForGeneratorPrzelewow.Start();
} else {
}
}
private void toolStripMenuGeneratorRaportow_Click(object sender, EventArgs e) {
if (subThreadForRaporty == null || subThreadForRaporty.IsAlive == false) {
subThreadForRaporty = new Thread(pokazRaportyWewnetrzne);
subThreadForRaporty.Start();
} else {
}
}
private void toolStripMenuGeneratorRaportowDlaKlienta_Click(object sender, EventArgs e)
{
if (subThreadForRaportyKlienta == null || subThreadForRaportyKlienta.IsAlive == false) {
subThreadForRaportyKlienta = new Thread(pokazRaportyKlienta);
subThreadForRaportyKlienta.Start();
} else {
}
}
I've got couple of questions and i hope someone could explain them:
When i use Show() instead of ShowDialog() the windows just blink for a second and never shows. What's the actual difference between those two and why it happens?
When i use ShowDialog everything seems normal but i noticed not everything gets filled properly in one of the gui's (one listView stays blank even thou there are 3 simple add items in Form_Load(). I noticed this only in one GUI even thou on first sight everything works fine in two other gui's and i can execute multiple tasks inside those Forms updating those forms in background too (from inside the forms methods). Why would this one be diffrent?
What would be proper way of doing this? Tasks performed in each of those Forms can be time consuming and i would like to give user possibility to jump between those 4 windows without problem so he can execute what he likes.
The difference is with Modal and Modeless Windows Forms.
Modeless forms let you shift the
focus between the form and another
form without having to close the
initial form
Show() method is used for this purpose
Show() shows the new form, then returns. If this is all the thread is doing than the thread will exit, and that will destroy the form.
ShowDialog() shows the form, and then begins running a message pump, until the form is hidden or destroyed, ShowDialog() doesn't return, so your thread keeps running.
If You mean for these forms to each behave like a separate application window. then you could also use Application.Run() after form.Show() to run a message pump for the form on that thread. The drawback to doing it this way, is that when any one of your forms is closed, it might end up taking down the whole process because of the way WM_QUIT is handled.
But other than the way you would deal with closing down your application, Form.ShowDialog() is very much like Form.Show() followed by Application.Run(). The conditions that cause the message pump to exit are a bit different between these to, so you would choose one or the other mostly based on how you want to your application to handle closing one of your forms.
You should put the time-consuming tasks in their own BackgroundWorker threads. Keep all of the forms in the main thread.
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
1: Show() is not blocking, that is it shows the window and then returns. Afterwards, the varGui variable goes out of scope and is finalized by the garbage collector => disappears.
2: You'd need to show the updating code to get a definite answer, but as you can only update the contents of a form when running in the thread that created the form. Doing it otherwise is unreliable, so is the usual culprit when form updates don't work. In a method of a form class, call:
if (InvokeRequired) {
.Invoke(..); // call back this same method on the right thread
} else {
// dowork
}
to manage the UI.
3: The proper way is what Jake wrote: use one thread for all GUI stuff and BackgroundWorker threads for, well, background work.