Properties.Settings - Multiple forms - c#

I have two forms:
MainForm
SettingsForm
As you can imagine, MainForm uses values such as Properties.Settings.Default.Path and SettingsForm should be able to configure such a value on runtime.
But somehow SettingsForm: Properties.Settings.Default.Save(); takes effect just after application restart, although I'm reloading those settings in MainForm: Properties.Settings.Default.Reload();
I have this so far:
In MainForm.cs:
// Handles "config button click" => display settings form
private void configStatusLabel_Click(object sender, EventArgs e)
{
SettingsForm form = new SettingsForm();
form.FormClosed += new FormClosedEventHandler(form_FormClosed);
form.Show();
}
// Callback triggered on Settings form closing
void form_FormClosed(object sender, FormClosedEventArgs e)
{
Properties.Settings.Default.Reload();
}
// There are another methods called after form_FormClosed is triggered, for example
// StremWriter = new StreamWriter( Properties.Settings.Default.Path)
And SettingsForm.cs:
// Triggered on "Save button click" in Settings form, after changing values
// Example: Properties.Settings.Default.Path = "C:\\file.txt"
private void saveButton_Click(object sender, EventArgs e)
{
Properties.Settings.Default.Save();
Close();
}
What am I missing? How can I achieve "on demand change"?
More on program flow
In main form, there are several buttons which will trigger function such as ReloadLog() which uses Properties.Settings.Default.Path. So at the end I'm having functions executed at this order:
ReloadLog(); // Triggered by the user (several times)
// This reloads contents of log, say C:\\main.log
configStatusLabel_Click(); // User hit "configure button", there are two active forms
// SettingsForm is now displayed too
// At this point ReloadLog() may be called in MainForm many times
// Meanwhile in SettingsForm:
Properties.Settings.Default.Path = PathTextBox.Text;
private void saveButton_Click(object sender, EventArgs e) // User hit save button
{
Properties.Settings.Default.Save();
Close(); // This will trigger form_FormClosed in main form
}
// Now you would expect that following line will open D:\\another.log
ReloadLog();
// But it still uses original config, however when I turn app off and on again, it works

private void configStatusLabel_Click(object sender, EventArgs e)
{
SettingsForm form = new SettingsForm();
form.FormClosed += new FormClosedEventHandler(form_FormClosed);
form.FormClosed += (s, e) => { MethodThatAppliesTheSettings(); };
form.Show();
}

Related

Restore form from secondary form

I have a form that minimizes when I open a secondary form (using a button click event). I want to be able to restore the original form when closing the secondary form. I have not been able to figure out how to restore the original. Here is the code I have (in example form)
The code from the main form:
private void BtnSecondaryForm_Click(object sender, EventArgs e)
{
// Open the secondary form.
FrmSecondaryForm fsf = new FrmSecondaryForm ();
fsf.Show();
this.WindowState = FormWindowState.Minimized;
}
Code from the secondary form:
private void FrmSecondaryForm_FormClosing(object sender, FormClosingEventArgs e)
{
// I need this code to be able to restore the main form.
}
Please don't just redirect me to someone else's similar question without explaining how I can get this to work in my application. I have looked at the other similar questions here on Stack Overflow already and don't understand how to get this to work.
You should find the form you want or restore, e.g.
using System.Linq;
...
private void FrmSecondaryForm_FormClosing(object sender, FormClosingEventArgs e)
var mainForm = Application
.OpenForms
.OfType<MainForm>()
.LastOrDefault();
if (mainForm != null) {
mainForm.WindowState = FormWindowState.Normal;
}
}
Move FormClosing event handler to primary form. This form is interested in the event anyway. I also changed event from FormClosing to FormClosed. Former can be called many times, but latter is called only once, when the form is actually closed.
private FrmSecondaryForm Fsf = null;
private void BtnSecondaryForm_Click(object sender, EventArgs e)
{
// Open the secondary form.
Fsf = new FrmSecondaryForm();
Fsf.Show();
Fsf.FormClosed += PrimaryForm_SecondaryFormClosed;
this.WindowState = FormWindowState.Minimized;
}
private void PrimaryForm_SecondaryFormClosed(object sender, FormClosedEventArgs e)
{
Fsf.FormClosed -= PrimaryForm_SecondaryFormClosed;
Fsf.Dispose();
Fsf = null;
this.WindowState = FormWindowState.Normal;
}
So you need Form2 to interact with Form1, which means that Form2 needs a reference to it.
Best is to do this during construction. But with forms, you should always keep a default no-parameter constructor, so we need to add a new one and make the original private.
//Add a new property (or field if you wish)
private Form formToMinimise { get; }
//Change this to be private
private SecondaryForm()
{
InitializeComponent();
}
//Add this new constructor as public
public SecondaryForm(Form form): this()
{
formToMinimise = form;
}
Now closing and restore original. We do a null check, just in case
private void FrmSecondaryForm_FormClosing(object sender, FormClosingEventArgs e)
{
formToMinimise?.WindowState = FormWindowState.Normal ;
}
Now you amend the creation and calling of your second form like this
private void BtnSecondaryForm_Click(object sender, EventArgs e)
{
// Create the secondary form with reference to this form
FrmSecondaryForm fsf = new FrmSecondaryForm(this);
fsf.Show();
this.WindowState = FormWindowState.Minimized;
}

Close Form when not clicking on it

I want to know if there is any event when you click on the rest of the screen and not the Windows Form the Form closes. Is it because of the ShowDialog()?
My Main Form is just with a notifyIcon and when I click it I call Form1.ShowDialog();
Main.cs:
private void ShowForm1(object sender, EventArgs e)
{
form1.Left = Cursor.Position.X;
form1.Top = Screen.PrimaryScreen.WorkingArea.Bottom - form1.Height;
form1.ShowDialog();
}
Form1.cs:
private void Form1_Load(object sender, EventArgs e)
{
label1.Text = "Test";
}
You need to run the dialog box non-modally, not modally. Think about it, when you run it modally, the dialog box takes over the UI and plays games with mouse-clicks elsewhere, preventing you from running. You don't want it to be modal anyway.
I created a simple Windows form with a button that includes this handler to open a small AutoCloseDialog form I created (and populated with a few controls):
private void button1_Click(object sender, EventArgs e)
{
var dlg = new AutoCloseDialog();
dlg.Show(this); //NOTE: Show(), not ShowDialog()
}
Then, in the AutoCloseDialog form, I wired up the Deactivate event. I did it in the designer (where this code is generated):
this.Deactivate += new System.EventHandler(this.AutoCloseDialog_Deactivate);
Finally, here is the handler for the Deactivate event.
private void AutoCloseDialog_Deactivate(object sender, EventArgs e)
{
this.Close();
}
I think this does what you are asking.
Yes, you can create a similar function like this, which closes the Form if the Form lost focus (in Form1.cs)
public void Form_LostFocus(object sender, EventArgs e)
{
Close();
}
and then you add the LoseFocus EventHandler (in Form1.Designer.cs):
this.LostFocus += new EventHandler(Form_LostFocus);

C# - Unable to see Form1 after closing Form2 via the cross

I'm fairly new at C#, and have spent the whole day to find a soultion to this to address the issue I'm having so apologies if this is simple, or has been wlsewhere! I have two Forms, Main and Config. Main loads, and has a button to open the Config form and then hide itself as so:
private void btnConfig_Click(object sender, EventArgs e)
{
Config config = new Config();
config.Show();
this.Visible = false;
}
It works just fine and the Config form opens. The Config from has two buttons (a Save and a Close button). In essence, both buttons have the same end effect, close the Config form and re-show the Main form, coded as so:
private void btnClose_Click(object sender, EventArgs e)
{
this.Hide();
Main main = new Main();
main.Visible = true;
}
The issue is that if I close the Config screen using the 'cross', Config is 'closed' but Main is not displayed and the programcontinues to run. I've tried using OnFormClosing and got stuck in an awful loop! The Cross should do the same as the Save/Close buttons, hide the Config form and open Main again.
If you want to show the config Form and reshow the Main form when the config has changed you normally would want something as a Config Form to show Modal.
To show a Modal Form, you'll to use ShowDialog(). ShowDialog() is also a blocking call, which gives you the ability to pick up where you left of.
In the mainform:
private void btnConfig_Click(object sender, EventArgs e)
{
var config = new Config();
this.Visible = false;
// this call blocks!
var dialogResult = config.ShowDialog();
// when the configform is closed, the code resumes here
this.Visible = true;
}
This also gives you the possibitlity, to cancel the config form, by setting
DialogResult property of the Config form to DialogResult.Cancel just before closing.
I'm not too sure what you're looking for exactly but this is how I would go about it.
Change your function to the following and have a private Config object under your main form class.
private Config config;
private void btnConfig_Click(object sender, EventArgs e)
{
if(config==null || config.IsDisposed)
{
config = new Config(this); // Pass the main form into the constructor of config
}
config.ShowDialog();
this.Visible = false;
}
Create a constructor (for Config) that takes in the main form as a parameter and have the main form as a private object. This allows you to show the original form as apposed to just creating a new one every time.
private Form mainForm;
public Config(Form main)
{
mainForm = main;
}
And change your close action.
private void btnClose_Click(object sender, EventArgs e)
{
this.Hide();
mainForm.Visible = true;
}

Run Form1 for 5 times than close Form1, restart

I'd like to add a loop to:
private void button5_Click(object sender, EventArgs e)
{
}
This will run Form1 for 5 times with 3 second delay than close all, than do it again.
I'm using this code to open them manually;
Form1 form = new Form1();
form.Show();
And I need to stop the loop with;
private void button6_Click(object sender, EventArgs e)
{
}
I'm new to coding and if you can explain it with code examples I would be grateful.
Im not sure why you ever want this. But here is the way.
You need a Timer with interval of 3000 milliseconds (3 seconds) that will fire an Event at every interval. Inside that Event you will Open up forms and will close all the forms if 5 forms are opened.
Timer _timer = new Timer(); // This is the timer
List<Form> forms = new List<Form>(); // This will hold list of forms.
private void button1_Click(object sender, EventArgs e)
{
_timer.Enabled = !_timer.Enabled; // toggle event with this button.
}
private void Form1_Load(object sender, EventArgs e) // initialize timer with form load event
{
_timer.Interval = 3000; // set interval
_timer.Tick += OpenUpForm; // set event
}
private void OpenUpForm(object sender, EventArgs e) // this is the event that should be fired every 3 seconds
{
if (forms.Count == 5) // if forms reached 5 attempt to close all
{
// ForEach will perform this actions for every form in forms list
forms.ForEach(f =>
{
f.Close(); // close form
f.Dispose(); // free resources
});
forms.Clear(); // clear the list
return;
}
forms.Add(new Form()); // add a new form to list
forms.Last().Show(); // show the form
}
Note that this will just open empty forms. If you want to open specific form you should create a 5 copy of that and put them inside list. and just open and close them.

form not closing immediately after listening to FormClosed event

I have two windows forms. I am calling the second form from a button click on the first form using Form.Show(). I want to show a messagebox after the form is closed. I subscribed to the FormClosed event but the form only closes after the messagebox is displayed.
any reasons why this happens?
private void button1_Click(object sender, EventArgs e)
{
Form2 fr2 = new Form2();
fr2.FormClosed += new FormClosedEventHandler(fr2_FormClosed);
fr2.Show();
}
void fr2_FormClosed(object sender, FormClosedEventArgs e)
{
MessageBox.Show("second form closed");
}
This happens because the event fires before the form is removed from the screen and MessageBox.Show( blocks until you press the ok button.
Here is from the decompiled source code of the .NET framework for the private function WmClose which handles the closing of a form.
private void WmClose(ref Message m)
{
//Snip...
FormClosedEventArgs e3 = new FormClosedEventArgs(this.CloseReason);
this.OnClosed((EventArgs) e3);
this.OnFormClosed(e3);
base.Dispose();
}
protected virtual void OnFormClosed(FormClosedEventArgs e)
{
Application.OpenFormsInternalRemove(this);
FormClosedEventHandler closedEventHandler = (FormClosedEventHandler) this.Events[Form.EVENT_FORMCLOSED];
if (closedEventHandler == null)
return;
closedEventHandler((object) this, e); //This line is what calls fr2_FormClosed
}
The form is still visible on the screen until base.Dispose() is called and the code does not return from this.OnFormClosed(e3); until your code returns from fr2_FormClosed.
The easiest work around is defer the showing of the message box by putting it on the message queue via a BeginInvoke(
void fr2_FormClosed(object sender, FormClosedEventArgs e)
{
this.BeginInvoke(new Action(() =>
{
MessageBox.Show("second form closed");
}));
}
This now puts the action of showing the message box on to the message pump queue and continues on its work of closing Form2, once it has finished closing it will look for more work to do on the message queue and then display the message box.

Categories

Resources