The current problem is that the "mainScreen" shows up, but immediately closes, I have no idea why. This is the piece of code that handles the close and opening of the new form.
Edit: .this refers to Login.cs (sorry)
if(templogin == true && permission.Equals("1"))
{
mainScreen.IsAdmin();
this.Close();
mainScreen.ShowDialog();
}
I think, you should not close the application(as login form seems main form while you started the application) before another form run:
Do like this :
if(templogin == true && permission.Equals("1"))
{
this.Hide();
mainScreen.IsAdmin();
mainScreen.ShowDialog();
this.Close();
}
If you want to run 2 forms (switching from one to another), then you should do it in Main
Instead of
Application.Run(new StartupForm());
you'll have to use
var startup = new StartupForm();
startup.ShowDialog();
if(somecondition) // when StartupForm is closed and return something (or property is set, etc)
{
var main = new MainScreen();
main.ShowDialog();
}
You don't need Application.Run at all when using ShowDialog.
Related
On my application's first run, two forms open. The topmost form needs to take priority, and disallow any interaction with the form in the background. I have tried ShowDialog() as referenced here, however this hides the form in the background which I do not wish to do. Is there a method of accomplishing this?
public Form1()
{
InitializeComponent();
if (!fileexists(#"c:\Management Tools\Absence Tracker\bin\data\tbase.skf"))
{ firstrunactions(); }
}
void firstrunactions()
{
//open the get-started form and invite user to populate serialisable objects
firstrun frwindow = new firstrun();
frwindow.ShowDialog();
}
When you are using .ShowDialog() the execution of the containing method is paused until you close the newly opened window. So make sure to do everthing else before you call .ShowDialog(). Otherwise your program gets stuck in this method. If you are calling .ShowDialog() before the background window is shown will cause problems.
But using .ShowDialog() here is totally correct and has the right functionality.
Example how not to do it (causes the same behavior like in your problem):
public Form1()
{
InitializeComponent();
//this is the wrong place for showing a child window because it "hides" its parent
Form frwindow = new Form();
frwindow.ShowDialog(this);
}
The magical place where it works:
private void Form1_Shown(object sender, EventArgs e)
{
Form frwindow = new Form();
frwindow.ShowDialog(this);
}
Edit: In your case it is enough moving if(!fileexistst...) into the Form1_Shown()-event.
Try with frwindow.ShowDialog(this);
Or instead "this" pass the other form as parameter.
Also move this part if (!fileexists(#"c:\Management Tools\Absence Tracker\bin\data\tbase.skf"))
{ firstrunactions(); }
}
in OnLoad override.
I am using a method sice I will have alot of child forms. Now it does show when I call a form by clicking on a button, but not after the login child is closed.
Method:
private void mForms(Form f)
{
if (this.MdiChildren.Contains(f))
{
f.WindowState = FormWindowState.Normal;
}
else
{
f.MdiParent = this; f.Show();
}
}
This just simply checks if the MDIcontainer already contains the requested form. If yes, put it back up again (in case it's minimized), if not, show it.
Now I can call the forms using this:
private void ts_bestand_studenten_add_Click(object sender, EventArgs e)
{
if (add_student.IsDisposed)
{
add_student = new add_student();
}
mForms(add_student);
}
This checks if it is disposed already or not. If so, redefine it. Then it calls to the method to open the right form. This works as it should.
Now the problematic part:
After the login screen is closed and user is logged in, the userlevel is defined. I should be able to open another form. This is the method I use for that: (NOTE: the userlevels work fine since it does reach the Messagebox)
// Predefines start_screen_admin
Form start_screen_admin = new start_screen_admin();
public void mCommitRights()
{
if (userlevel.gCheckLevel == 0)
{
// Admin, no changes
MessageBox.Show("Admin");
mForms(start_screen_admin);
}
... more of the same to check for userlevels
}
Now you think this should work. I don't have to redefine it because it's the first time it opens and it is already predefined. The MessageBox shows, but the form does not. I really can't see a problem in this. I tried everything I could think of..
I think you need to include the Select() method to bring the form to the front:
Try changing it to this:
private void mForms(Form f) {
if (this.MdiChildren.Contains(f)) {
f.WindowState = FormWindowState.Normal;
f.Select();
} else {
f.MdiParent = this;
f.Show();
}
}
This question might sound simple but I can't find the answer i'm looking for.
I have a Login_Form and a Main_Form.
Once I log into the Main_Form I just make it visible and I activate it because I don't want my Login_Form to close.
My question is, is there a way to close both forms at the same time from the Main_Form?
The this.Close(); will only close the current form.
if (access)
{
Main_Form mainForm = new Main_Form();
mainForm.Visible = true;
mainForm.Activate();
}
This is where I Instantiate the main_form how can I pass a reference to the login_form?
Thanks in advance and remember the Login_Form must remain open until I close it from the Main_Form!
Feedback
After looking at which of your answers I would use I found out about the Application.Close() Method Which closes all the forms. Should have taught about this before posting here thanks everyone.
If your Main form has a reference to the Login form you can call the close method on it. How you do that is up to you.
You could pass the reference in to the Main from FROM the login form when you show it.
You could keep a global reference to the Login Form. (think singleton)
any other way you can think of
For example:
public class MainForm : Form
{
Form loginform;
public MainForm(Form loginForm)
{
this.loginForm = loginForm;
}
public void CloseForms()
{
loginForm.Close();
this.Close();
}
}
In your Active() method, just pass the login form in. Alternatively you can use the code above, and just pass this into the constructor instead of the Active() method.
public class MainForm : Form
{
Form loginform;
public Active(Form loginForm)
{
this.loginForm = loginForm;
}
public void CloseForms()
{
loginForm.Close();
this.Close();
}
}
//from the LOGIN form
if (access)
{
Main_Form mainForm = new Main_Form();
mainForm.Visible = true;
mainForm.Activate(this); //this is a reference to the current form. LOGIN in this case
}
If you have a reference to the login form then call Close on that form.
Login_Form.Close()
You will have modify the constructor of Main_Form to accept login form instance as a parameter
You can also use the AddOwnedForm Method.
From above link:
When a form is owned by another form, it is closed or hidden with the
owner form. For example, consider a form named Form2 that is owned by
a form named Form1. If Form1 is closed or minimized, Form2 is also
closed or hidden. Owned forms are also never displayed behind their
owner form. You can use owned forms for windows such as find and
replace windows, which should not be displayed behind the owner form
when the owner form is selected.
Code:
Form loginForm = new Form();
this.AddOwnedForm(loginForm);
loginForm.Show();
Edit:
Form mainForm = new Form();
mainForm.Visible = true;
mainForm.AddOwnedForm(this);
mainForm.Activate();
now if you close the mainForm it will close both forms.
You could just use Application.Exit(); not Application.Close();
I need to be sure that all forms will be closed if I user somehow close the main form. So I decided to hide Close() function and I wrote something like this
public new bool Close()
{
List<Form> formsList = new List<Form>(Application.OpenForms.Count);
foreach (var form in Application.OpenForms)
formsList.Add((Form)form);
formsList.Reverse();
foreach (var form in formsList)
{
if (form.IsDisposed) continue;
Invoke(new GenericEventHandler(() => { form.Close(); }));
}
return Application.OpenForms.Count == 0;
}
So if all forms are closed successfully I return true and thanks to this I know that user can be logged out from application.
However it seems that form.Close() function is not fired immediately. After calling form.Close() formclosed event is not fired immediately as well as collection Application.OpenForms is not modified. The amount of opened forms is noted changed.
What could be a reason?
Why dont you just use
Application.Exit();
If the main form is created in the standard way in WinForms via Application.Run(new MainForm()); then when it closes, the application will exit, closing all other forms. So I don't think you need to worry about manually closing all child forms.
Well, if the user closes the main form, then upon closing it your application will definitely exit, since your form is responsible for keeping the application alive when it was passed to Application.Run().
Now, if you want to close your app when a form is closed, in that form you do this:
protected override void OnFormClosed(FormClosedEventArgs e)
{
base.OnFormClosed(e);
Application.Exit();
}
In general I suggest not to use new keyword to any members of Control and/or Form class. If you need your own method use your own name of it.
In your code you don't really need to use Invoke when closing child forms.
If you need to be sure that all your child Forms are closed before you actually execute logic related to MainForm.Close you may subscribe to MainForm.FormClosing event with handler similar to follwing:
void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
bool allChildFormsClosed = !closeAllChildForms();
if(!allChildFormsClosed)
{
e.Cancel = true;
MessageBox.Show("Failed to close one or more child forms.");
// better add some yes|no dialog to force exit if necessary
}
}
You may implement closeAllChildForms in a similar way as you did above - just: remove the formsList.Reverse(); and the 'Invoke..' - just call Close directly and update: if (this == form || form.IsDisposed) continue;
If for some reason, Application.Exit isn't cutting it for you, you could try this code (put it in the form's FormClosing event):
while (Application.OpenForms.Count > 1)
{
Form form = Application.OpenForms[1];
form.Close();
while (!form.IsDisposed) Application.DoEvents();
}
or if you want it to time out if it can't close all the forms after a while,
while (Application.OpenForms.Count > 1)
{
Form form = Application.OpenForms[1];
form.Close();
DateTime StartTime = DateTime.Now;
while (!form.IsDisposed && (StartTime - DateTime.Now).TotalMilliseconds < 1000)
Application.DoEvents(); //1-second timeout here
if (!form.IsDisposed) //if it's still not closed
{
//send a message to the user that the application can't exit right now
mbox("some forms are still open or whatever");
e.Cancel = true;
return;
}
}
I have a project with requirements as below,
Login form opens up and asks for user name and password.
Login Successful - Login form closes and another main form opens and all the functionalities will be added here.
In the main form there is a Call button when clicked on it, it will pop a dial pad.
When the number is entered on the dial pad and clicked "ok", control comes back to the same main form.
When logout is clicked, It wil take me to the login screen again.
For this can anybody explain me the following points:
How do I tranfer the control from one form to another?
I have to make sure when user clicks on the close 'x' , I have to log out and close the windows?
Neeed some rough class information.
Thanks in advance.
This is what i used earlier to carry data from one form to other
public partial class DialPad : Form
{
public MainGUI guiObject;
public DialPad(MainGUI mG)
{
InitializeComponent();
guiObject = mG;
}
By the sounds of it your dialler form should be a dialog..
class MyDiallerDialog : Form
{
public String DialledNumber
{
get { return this.txtNumber.Text; } // Or however the form stores its number...
}
}
class MyMainForm : Form
{
void btnCall_Click(object sender, EventArgs e)
{
using (var dialog = new MyDiallerDialog())
{
if (dialog.ShowDialog() == DialogResult.OK)
{
String number = dialog.DialledNumber;
// do something interesting with the number...
}
}
}
}
For your point no. 2
I have to make sure when user clicks
on the close 'x' , I have to log out
and close the windows?
In the event FormClosing of the form, take a look at e.ClosingReason.
So if user closes using Close Button (X), then ClosingReason would be UserClosing. So check that and then write appropriate code therein.
How do I tranfer the control from one
form to another?
For e.g
If you want to get the number in main form from Dialpad form.
1st in the contructor of main form
public static MainForm instance = null;
public string numberInMainForm = null;
public MainForm()
{
instance = this;
}
now in your dialpad form, when user enters the number, you can pass the number (or any other variable.) to main form from the dialpad form directly.
In dialpad form just write:
MainForm.instance.numberInMainForm = number;
thats it. You are done !!
let us assume you 1st form is loginform,
Suppose User press OK on the login form, so on
OK_click()
event call another form.
suppose your name of the another form is MainForm.cs then you can call using...
MainForm mf = new Mainform()
Suppose you want to close the login form when user press OK of your logIn form you can keep the order in following way..
private void OK_Click(object sender, EventArgs e)
{
. . .
// your validations
//return bool (true or false ) to confirm you have complted validations
MainForm mf = new Mainform();
mf.show(); // or you can use mf.ShowDialog();
. . .
. . .
this.close();
}
When you will close the MainForm,its control will come directly to the next line after mf.show();
To close any form use
this.close() command.
I hope this will help you ands you can start working on your project now.
EDIT:
Add a new class file named commondata.cs and in that use static variables like
public static string myString = "";
You can keep all the static functions and variables in the common file like commonData.cs so that you can modify its value from anywhere and can be used from anywhere.
Before closing your current form store the information in the static myString so even if u close the current form related information will be stored in myString & you can access it in any form using commonData.myString command.
string temp = commonData.myString;
Regards,
Sangram Nandkhile.