I am creating a Windows app that will have multiple forms in it. Initially, I have set WindowState Maximized for all.
My problem here is that when I minimise one form, size of the other forms stay same. So, if I minimize the main screen go to the next screen, the size of the next screen remains unchanged. All I need to do is change size of all the windows at once.
I tried this:
Mainscreen mainscreen = new Mainscreen();
this.WindowsState = mainscreen.WindowsState;
But I am finding a way to do it for all screens.
A very ugly demo for your reference
private List<Form> Windows { get; set; }
public Form1()
{
InitializeComponent();
this.Text = "Main Window";
this.Windows = new List<Form>();
var defaultSize = new Size(200, 100);
for (var i = 0; i < 3; i++)
{
var form = new Form() { Size = defaultSize, Text = "Resize Me" };
var suppressEvent = false;
form.SizeChanged += (sender, e) =>
{
if (suppressEvent)
return;
suppressEvent = true;
defaultSize = (sender as Form).Size;
foreach (var otherForm in this.Windows)
{
if (otherForm != sender as Form)
otherForm.Size = defaultSize;
}
suppressEvent = false;
};
this.Windows.Add(form);
form.Show();
}
}
If the minimization is the concern and all sub forms launch from a previous form the quickest way would be to have the main form be the owner of the sub form.
If you make a simple project with two forms Form1 and Form2 and add a button onto Form1 that launches Form2 it would look like the following.
private void button1_Click(object sender, EventArgs e)
{
Form2 lForm = new Form2();
lForm.Show(this);
}
Passing "this" (which is reference to Form1) into the constructor of show will make sure that when it minimizes the subform (Form2) will also minimize. You can also change the setting of Form2 and set
lForm.ShowInTaskbar = false;
if you wanted to help make it clear that all of the forms are tied together.
If you are instead talking about having all forms maintain the same size regardless of who started the change and what the size ends up being then it gets a bit trickier and the simplest way would be to make a form manager of some sort that listens to the OnSizeChanged event and updates all forms whenever any form updates. Keep in mind with this that you'll also need to have a test in the form to know whether or not it is the one that started the update otherwise you would get in a sort of infinite loop where Form1 updates causing Form2 to update which then sends out another message which tries to make Form1 update etc...
Related
I apologize if this has been addressed already, but I could not find a case that fit my exact situation. So here goes...
I have a MainForm that contains a toolStrip1 docked to the left that functions as a vertical navigation bar. I have a panel (pnlMain) filling up the remainder of the form. I want to use pnlMain to display different forms which are made up of win form classes. Right now, I can click on the labels/buttons on toolStrip1 to display different forms within pnlMain.
private void tsLblCustomers_Click(object sender, EventArgs e)
{
hidePanels();
CustomerReport cr = new CustomerReport();
cr.TopLevel = false;
cr.AutoScroll = true;
cr.BackColor = Color.White;
pnlMain.Controls.Add(cr);
cr.Show();
}
What I want to do now is display additional forms within pnlMain by clicking on a button on another form rather than a label/button on toolStrip1. Some of my forms are as follows: CustomerReport, AddCustomer, EmployeeReport, AddEmployee. The Report forms are linked to my tool strip buttons. The Add forms are linked to buttons on the Reports forms. I tried several things including the following:
1) On CustomerReport, I tried creating an instance of MainForm, then I'll create an instance of AddCustomer, and then add that instance to the panel on MainForm.
2) I also tried creating a method in MainForm to create the instance of AddCustomer, and then call that method from the Add button on CustomerReport. Even though the code was the same as the toolstrip buttons on MainForm, it did not work.
I tried different variations of hiding forms, showing forms, clearing the panel, setting Visible to true or false, and I can't get it to work right. In some cases, I've managed to hide the CustomerReport, but AddCustomer will not come up. At some point I think I created a NEW instance of MainForm and my code wasn't impacting the original form that is already open. I'm just lost. Should I be using a different design? Originally I set up my application to just hide one form then show the other but I read that that is a 'terrible design'.
This sounds very similar to this thread here: Creating Form Inside the Form
You'd want to look into MDI.
Although it sounds like you're aiming for one cohesive interactive window. Otherwise, if you just want separate windows to popup, you can create properties within that other form and read them after returning a DialogResult. I'm not sure why this would be bad design without knowing more about the context of the program.
//Optionally do a hide(); here.
AddCustomer customer = new AddCustomer();
DialogResult result = customer.ShowDialog();
if(result == DialogResult.OK)
{
var name = customer.Name;
//More properties or whatever here.
}
//The properties would still be accessible here, too.
I ended up keeping the toolstrip nav bar on the left side of the primary window, and I created a panel in the main part of the window. All forms are displayed in the panel. Each time one of the label options in the nav bar is clicked on, the current form is cleared off the panel and the active form is displayed.
private void tsLblCustomers_Click(object sender, EventArgs e)
{
pnlMain.Controls.Clear();
CustomerReport cr = new CustomerReport();
cr.TopLevel = false;
cr.AutoScroll = true;
cr.BackColor = Color.White;
pnlMain.Controls.Add(cr);
cr.Show();
}
private void tsLblEmployees_Click(object sender, EventArgs e)
{
pnlMain.Controls.Clear();
EmployeeReport emp = new EmployeeReport();
emp.TopLevel = false;
emp.AutoScroll = true;
emp.BackColor = Color.White;
pnlMain.Controls.Add(emp);
emp.Show();
}
private void tsLblVendors_Click(object sender, EventArgs e)
{
pnlMain.Controls.Clear();
VendorReport vend = new VendorReport();
vend.TopLevel = false;
vend.AutoScroll = true;
vend.BackColor = Color.White;
pnlMain.Controls.Add(vend);
vend.Show();
}
private void MainForm_Load(object sender, EventArgs e)
{
WelcomeForm welcome = new WelcomeForm();
welcome.TopLevel = false;
welcome.AutoScroll = true;
welcome.BackColor = Color.White;
pnlMain.Controls.Add(welcome);
welcome.Show();
}
In VB.NET, you can freely Hide/Show/ShowDialog (for a fresh form). But in C#, you always have to create new form instance to do this. Even your previosly hidden form can't show back, you have to create new instance again. Resulting in your previously hidden form will run as background process until you kill it.
My question is how can I create a function that will unhide a form that doesn't need a new instance when I close the current form using the default exit in form's title bar.
Edit: I solved it on my own. It's just confusing. And what difference between c# and vb.net is that I never have to use form_closed in vb.net. Why do I always see it in c#.
You can always display an hidden form in C#. There are many ways to this.
For example you could check the Application.OpenForms collection that keeps track of all forms owned by your application and still not closed. (An hidden form is not closed). This approach means that you need to identify you form between the ones included in the collection OpenForms
MyFormClass f = Application.OpenForms.OfType<MyFormClass>().FirstOrDefault();
if ( f != null) f.Show();
Another approach, more lengthy, is to keep track yourself of the form to hide/show with a variable inside your application. This requires extra care in handling correctly the various situations in which you global variable becomes invalid (what if the user closes effectively the form instead of hiding it?)
This is an example that you can test easily with LinqPAD
// Your form instance to hide/show
Form hidingForm = null;
void Main()
{
Form f = new Form();
Button b1 = new Button();
Button b2 = new Button();
b1.Click += onClickB1;
b2.Click += onClickB2;
b1.Location = new System.Drawing.Point(0,0);
b2.Location = new System.Drawing.Point(0, 30);
b1.Text = "Hide";
b2.Text = "Show";
f.Controls.AddRange(new Control[] {b1, b2});
f.ShowDialog();
}
void onClickB1(object sender, EventArgs e)
{
// Hide the global instance if it exists and it is visible
if(hidingForm != null && hidingForm.Visible)
hidingForm.Hide();
}
void onClickB2(object sender, EventArgs e)
{
// Create and show the global instance if it doesn't exist
if (hidingForm == null)
{
hidingForm = new Form();
hidingForm.Show();
// Get informed here if the user closes the form
hidingForm.FormClosed += onClosed;
}
else
{
// Show the form if it is not visible
if(!hidingForm.Visible)
hidingForm.Show();
}
}
void onClosed(object sender, FormClosedEventArgs e)
{
// Uh-oh.... the user has closed the form, don't get fooled...
hidingForm = null;
}
Well, OpenForms seems a lot better.
I have an app with 2 forms, the main window and a second Form.
What I want is to open up the second Form on a button click and it's location must be right beside the main form (so if the main form is 600px wide, the X of the new Form will be main.X + 600)
Have tried this but it doesn't seem to take, it opens on top of the main form still:
private void button1_Click(object sender, EventArgs e)
{
var form = new SecondForm();
var main = this.Location;
form.Location = new Point((main.X + 600), main.Y);
form.Show();
}
Is Location not the correct attribute?
Set your form's StartPosition to FormStartPosition.Manual. You can do it in the designer or from the constructor:
StartPosition = FormStartPosition.Manual;
Clearly you didn't count on the StartPosition property. Changing it to Manual is however not the correct fix, the second form you load may well rescale itself on another machine with a different video DPI setting. Very common these days. Which in turn can change its Location property.
The proper way is wait for the Load event to fire, rescaling is done by then and the window is not yet visible. Which is the best time to move it in the right place. StartPosition no longer matters now. Like this:
var frm = new SecondForm();
frm.Load += delegate {
frm.Location = new Point(this.Right, this.Top);
};
frm.Show();
Location is right property, but you must set
Form.StartPosition = FormStartPosition.Manual;
too.
How can I close an opened window when I call a new window? That means I want only 1 child window at the time. I don't allow multi-window.
public partial class Main_Usr : Form
{
public Main_Usr()
{
InitializeComponent();
this.IsMdiContainer = true;
if (Program.IsFA) barSubItem_Ordre.Visibility = DevExpress.XtraBars.BarItemVisibility.Never;
Ordre_Liste f = new Ordre_Liste();
f.MdiParent = this;
f.Show();
}
private void barButtonItem_CreateOrdre_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
{
Program.AllerRetour = "Ordre Aller";
Ordre_Fiche f = new Ordre_Fiche();
f.MdiParent = this;
f.Show();
}
private void barButtonItem_OrdreListe_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
{
Ordre_Liste f = new Ordre_Liste();
f.MdiParent = this;
f.Show();
}
private void barButtonItem_CreateOrdRet_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
{
Program.AllerRetour = "Ordre Retour";
Ordre_Fiche f = new Ordre_Fiche();
f.MdiParent = this;
f.Show();
}
}
There are different ways to implement pseudo masterpage:
You can create BaseForm form with desired layout. Then inherit other forms from this BaseForm and provide custom content.
You can create MainForm form with desired layout. Then create content controls as UserControls and show them in panel.
You can create MasterUserControl with desired layout. Then create content controls by inheriting from MasterUserControl (they will have same layout). Then use your main form as browser for displaying different content controls like pages.
EXAMPLE:
Create desired layout on Main_Usr form.
Do not set it as MdiContainer
If you want to access some controls (e.g. footer or header from child forms, set property Modifiers of those controls to protected)
Open Ordre_Liste form code and change it to inherit from Main_Usr form, instead of Form
Add custom content to Ordre_Liste form
voila! you have 'masterpage'
UPDATE (for 3rd option)
Create new user control with name MasterUserControl
Create desired layout on this control, keeping space for custom content (btw don't use TableLayoutPanels - they have issue with designer inheritance).
Create new user control with name HomeUserControl and change it to inherit from your MasterUserControl.
Open HomeUserControl designer and add custom content. Also you can modify parent controls, which has protected modifier.
On your main form place HomePageUserControl
There different ways to implement navigation between controls (aka pages). Simplest way - have menu on main form. Other way - define event 'Navigate' on master control, subscribe to that event on main form, and raise it from 'pages'.
Create Form instances on a class level.
Then you can access to them from events or methods.
Form1 f1;
Form2 f2;
void OpenForm1()
{
f1 = new Form1()
f1.Show();
}
void OpenForm2()
{
f1.Dispose(); //or Hide if you want to show it again later
f2 = new Form2();
f2.Show();
}
Like:
List<Form> openForms = new List<Form>();
foreach (Form f in Application.OpenForms)
openForms.Add(f);
foreach (Form f in openForms)
{
if (f.Name != "Menu")
f.Close();
}
Note, do NOT close them directly, becuase there will come to an error, if you would try to close (or dispose) them in the 1st foreach loop. Thats why you need to put them into a list and close them there.
Methods opening forms :
form1 --> form2 --> form3
ChecklistBox on the form1 there. How to know the form3 That is active or not?
If the forms you are referencing are MDI child forms, you could use
Form activeChild = this.ActiveMdiChild;
else you could use the following code if not using MDI child forms.
Form currentForm = Form.ActiveForm;
I understand that you are asking if form 3 is opened. If that is incorrect, please enlighten me.
There are probably dozens of ways to do so, it all depends on what you want to do.
One simple way would be to leave a flag somewhere, say in your Program.cs file:
public static bool Form3IsOpen = false;
Then:
private void Form3_Load(sender object, EventArgs e)
{
Program.Form3IsOpen = true;
}
And:
private void Form3_Close(sender object, EventArgs e)
{
Program.Form3IsOpen = false;
}
Supplemental:
You can also keep a reference to your subform:
In form1.cs:
private Form2 FormChild;
//In the function that opens the Form2:
FormChild = new Form2();
FormChild.Show();
Form2 will have something similar to retain Form3. If one form can open several, just use an array or collection.
When i usually have many different forms and only one instance to be created, i put them in dictonary and check it if there is a form.
Something like this:
public static Dictonary<string, Form> act_forms_in_app = new Dictonary<string, Form>();
now in every forms creation i do it like this
Form1 frm = new Form1();
frm.Name = "Myformname"
//set its properties etc.
frm.Load => (s,ev) { act_forms_in_app.Add(frm.Name, frm);};
frm.Load += new EventHandler(frm_Load);
frm.Disposed => (s, ev) { act_forms_in_app.Remove(frm.Name)};
//your usual form load event handler
public void frm_Load(object sender, EventArguments e)
{
...
}
somewhere where you want to check
Form frm = //Your form object
if(act_forms_in_app.ContainsKey(frm.Name))
{
//Perform as required
}