Easy Way To Close Form - c#

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();

Related

Disallowing interaction with background form

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.

Pass in parent form to ShowDialog that is called from a class instance

I have a form.
In that form I create an instance of a class on a new thread because it runs some long running logic. The form also gives the user the ability to cancel this logic/thread.
That class opens a new form if input is required.
The new form sometimes appears behind the other form.
I set a property on the class:
public Form ParentForm{get;set;}
I can now do:
MyForm form = new MyForm();
form.ShowDialog(ParentForm);
However I get a cross thread exception when calling ShowDialog(ParentForm).
I know I can use InvokeRequired somehow but not sure how on a property.
Thanks
UPDATE: Have tried doing this but still get exception:
MyForm form = new MyForm();
form.ShowDialog(GetParentForm());
private Form GetParentForm()
{
//You have to Invoke() so you can wait for the function to return and obtain its return value.
if (ParentForm.InvokeRequired)
{
return (Form)ParentForm.Invoke(new Func<Form>(() => GetParentForm()));
}
else
{
return ParentForm;
}
}
Your updated method (GetParentForm) won't work because you're wrapping the task of getting the reference to ParentForm in an InvokeRequired block. You could try wrapping the ShowDialog call in such a block instead, but I think you would still get the cross-threading error.
Your simplest fix would be to move the code that creates and shows the second form out of your class and into ParentForm. So instead of this:
MyForm form = new MyForm();
form.ShowDialog(ParentForm);
you would do this:
ParentForm.showMyNewForm();
and in ParentForm you would have this:
public void showMyNewForm()
{
MyForm form = new MyForm();
form.ShowDialog(this);
}
If MyForm needs to have a reference to the class on the other thread, you would just add a parameter to showMyNewForm() so that the reference to it can be passed in.
What you're trying to do here (creating and showing related, connected forms that are created on different threads) is really going against the grain of how forms are meant to be used in .NET.
you can add async method to a form.
Let's say like this:
public class MyForm : Form
{
public void ShowModalAsync()
{
this.Invoke(new Action(()=> {
ShowDilaog(..);
}));
}
}
and use this, like:
MyForm form = new MyForm();
form.ShowModalAsync(...);
Should work for you.
By the way, if your problem is only the fact that the window appears on bihind of others, try to make use of Form.TopMost property setting it to true. Having in mind that it, yes, will bring it infront of other forms, but not necessary infront of other topmost forms.

Form.Parent and StartPosition.CenterParent

I need to show a form exactly in front of another form, this lead me to the following question.
How come a form can have a start position as CenterParent while having the field this.Parent equals to null?
It must know the parent in order to position itself correctly, which it does, but the Parent field is not set. This is odd. Am I missing something?
Form2 f = new Form2();
f.ShowDialog();
Thats all I do on the child form. The parent is set to default windows position. No matter where I move the parent form, the child is shown in the center of the parent.
The information about the owner is passed to the created dialog via the API call (you can see that in Reflector within the ShowDialog(IWin32Window owner) method):
UnsafeNativeMethods.SetWindowLong(new HandleRef(this, base.Handle), -8, new HandleRef(owner, handle));
When there is no owner specified in ShowDialog call the owner variable is calcualated via the GetActiveWindow API call:
IntPtr activeWindow = UnsafeNativeMethods.GetActiveWindow();
IntPtr handle = (owner == null) ? activeWindow : Control.GetSafeHandle(owner);
To get access to the Owner f dialog form you can use the GetWindowLong API call:
IntPtr ownerHandle = NativeMethods.GetWindowLong(nonModalForm.Handle, -8);
The difference between a parent and an owner of a window is a bit muddled in Winforms. In this context, CenterParent really means CenterOwner. Not a Windows capability, it is implemented in Winforms, done by the base Form.OnLoad() method. A dialog should always have a owner, it goes out hunting for one when you don't specify one in the ShowDialog() call. Which uses GetActiveWindow() as the best guess.
To see this for yourself, overload OnLoad in the dialog form, like this:
public partial class Form2 : Form {
public Form2() {
InitializeComponent();
this.StartPosition = FormStartPosition.CenterParent;
}
protected override void OnLoad(EventArgs e) {
//base.OnLoad(e);
}
}
And note that it no longer centers on the owner.
You can see the relevant code in the Reference Source, Form.cs class, OnLoad method:
if (GetState(STATE_MODAL)) {
FormStartPosition startPos = (FormStartPosition)formState[FormStateStartPos];
if (startPos == FormStartPosition.CenterParent) {
CenterToParent();
}
else if (startPos == FormStartPosition.CenterScreen) {
CenterToScreen();
}
}
I believe this information is stored internally by .NET Framework for some reason. Anyway, if you want to have access to the parent form you can set it to Owner property of the child form:
Form form = new Form();
form.Owner = this;
form.Show();
Then in the child form you can access the parent form using the Owner property. When a form is owned by another form, it is minimized and closed with the owner form. Owned forms are also never displayed behind their owner form, which is exaclty what you need if I understood you right.
This code will open the dialog in the middle of the parent TAG.
ObjectDistrubution od = new ObjectDistrubution();
od.StartPosition = FormStartPosition.CenterParent;
od.ShowDialog();

Need to define control flow and functionalities

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.

c# Windows form application forms problem

I have a c# windows form app which contains several forms.
Generally, for example, in form1, I create a instance of form2 and then
form1.hide();
form2.show();
But sometimes I want the previous form to show and dispose current form. How can I call the previous form?
Thanks in advance.
To answer your question, you need to maintain references in your views to each other. While this might work it's messy and error prone. It sounds like all your control logic is probably contained within your form class code and I would suggest moving away from that and separate your concerns.
Solving your form management issues becomes very simple if you create a controller class that, at a minimum, manages the creation and disposal of your forms in whatever way you see fit.
So your code sample would actually be launched from a controller class as something like:
public class FormsController
{
private Form form1 = new Form();
private Form form2 = new Form();
public void SwitchForms()
{
form1.hide();
form2.show();
}
}
For further edification checkout the MVC architectural pattern for cleanly working with data, biz logic and UI.
You might consider extending Form to include some properties/fields that allow you to access other forms. the Form class can be inherited from just like most other .Net classes.
You may also consider doing some of that management in the Program.cs file that is part of you project, if neither form is really supposed to be a child of the other.
If you inherit a new class for your form1 from Form and add a method like closeSecondForm you can have it close and dispose the second form.
There are probably a bunch of different ways to solve the issue. These are just a few.
If you set the new form's Owner to a reference to the current form, you can reference that Owner from the new form. You could also subscribe to the new form's Closed() event from the old form, with code to dispose it (though the form can dispose itself by overriding OnClosed, if it doesn't happen there anyway).
This logic should be handled in Program.cs. The Main() method initializes Form1. You want to take control there instead of passing control to the form.
Example:
static class Program
{
internal static Form1 MyForm1;
internal static Form2 MyForm2;
///
/// The main entry point for the application.
///
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
//Application.Run(new Form1());
// Initialize Form1
MyForm1 = new Form1();
MyForm1.FormClosing += new FormClosingEventHandler(MyForm1_FormClosing);
// You may want to initialize Form2 on-demand instead of up front like here.
MyForm2 = new Form1();
MyForm2.FormClosing += new FormClosingEventHandler(MyForm2_FormClosing);
// Show Form1 first
MyForm1.Show();
// Now we need to occupy the thread so it won't exit the app. This is normally the job of Application.Run.
// An alternative to this is to have a third form you pass on control to.
while (true)
{
Application.DoEvents();
System.Threading.Thread.Sleep(10);
}
}
static void MyForm1_FormClosing(object sender, FormClosingEventArgs e)
{
// Do something, for example show Form2
MyForm2.Show();
// EXAMPLE: We only want to hide it?
e.Cancel = true;
MyForm1.Visible = false;
}
static void MyForm2_FormClosing(object sender, FormClosingEventArgs e)
{
// Do something, for example show Form1
MyForm1.Show();
// EXAMPLE: We only want to hide it?
e.Cancel = true;
MyForm2.Visible = false;
}
}
Since Program is static you can access MyForm1 and MyForm2 anywhere in that project by:
Program.MyForm1.Show();
Program.MyForm2.Hide();
If you plan to have many forms/complex logic I suggest moving this to a separate class. Also consider using a single form and rotate user controls inside it instead.
Form2 myform = new Form2();
myform.show();
this.hide();
You could do this in form1:
...
var form2 = new form2();
form2.Closing += (form2_Closing);
this.hide();
form2.show();
...
private void form2_Closing(object sender, System.EventArgs e)
{
this.show();
}

Categories