I am using visual studio 2010 to do my C# GUI.
The current problem that I am facing is that after maximizing a window, it stays there but when I go to other forms, the window will go back to its original size.
How do I leave the maximized window all the way for all the forms, once I click the maximize button?
Heres an example:
User maximizes Form A
Form A maximized
User goes to Form B
Form B goes back to original size instead of a maximized window
What I want is when user maximizes a form, it stays that way till the program is closed or resized.
Assuming you're using WinForms, you can have either implement a shared FormWindowState manager or use a Multiple Document Interface (MDI) container.
Shared FormWindowState
You can register each of your forms with a class responsible for propagating changes in forms' FormWindowState.
public class FormWindowStateManager {
List<Form> _Forms;
...
public void Register(Form form) {
if(!_Forms.Contains(form)) {
_Forms.Add(form);
form.Resize += new EventHandler(Form_Resize);
}
}
public void Unregister(Form form) {
if(_Forms.Contains(form)) {
_Forms.Remove(form);
form.Resize -= new EventHandler(Form_Resize);
}
}
private void Form_Resize(object sender, EventArgs e) {
Form form = sender as Form;
if(form != null) {
if(form.FormWindowState == FormWindowState.Maximized || form.FormWindowState == FormWindowState.Normal) {
PropagateWindowState(form.FormWindowState);
}
}
}
private void PropagateWindowState(FormWindowState state) {
foreach(Form form in _Forms) {
if(form.FormWindowState != state) {
form.FormWindowState = state;
}
}
}
}
MDI Container
MdiParentForm.cs
IsMdiContainer = true;
MdiChildForm.cs
MdiParent = myParentForm; // instance of MdiParentForm
You can iterate through a form's MDI children using the form's MdiChildren property such that when on MDI child window changes its FormWindowState, the MDI parent form can apply the change to each of its children, similar to the shared FormWindowState approach.
These ideas are just off the top of my head but maybe they'll get you in the right direction.
Related
On my windows application written with C#, I have written a form named BaseForm. On this form I have a Maximise button, white the following code:
private void btnMaximise_Click(object sender, EventArgs e)
{
WindowState = WindowState == FormWindowState.Normal ?
FormWindowState.Maximized : FormWindowState.Normal;
}
Now I have several forms derived from BaseForm. When I click the Maximise button on Say Form1, all other derived forms are maximized together, and when I click the button again, they all go back to their normal WindowState, TOGETHER.
I do not understand why this happens. I thought when I say this.WindowState I am pointing to the initiated object, but it is acting like a Static one. When I click the button on Form1 I expect only Form1 to get maximized and not all forms with common inheritance.
In the Designer.cs file, the event handler is linked like below:
this.btnMaximise.Click += new System.EventHandler(this.btnMaximise_Click);
By the way, all these forms are MDI children to an MDI Parent form. Maybe that has something to do with the problem.
New test result:
I tried opening 2 forms with MDI Parent set, and 2 other without it. The result is strange. Those which are independant (without MDI Parent) have no conflict, and those with MDI Parent all behave the same. Even when a form with MDI Parent is maximized and I open an entirely new form (not with CTRL+TAB, with instantiating a new form, setting the MDI Parent, and calling its .Show() method) the new form is opened with Maximized state.
I couldn't reproduce your issue; you'll need to post more code as to how you're creating, subclassing and wiring these events up. Here is a complete example code that DOESN'T demonstrate the issue:
using System;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.IsMdiContainer = true;
for (int i = 0; i < 5; i++)
new DerivedForm(this).Show();
}
}
public class DerivedForm : BaseForm {
public DerivedForm(Form parent)
{
this.MdiParent = parent;
}
}
public class BaseForm : Form
{
public BaseForm()
{
Button b = new Button();
b.Text = "Max";
b.Click += B_Click;
this.Controls.Add(b);
}
private void B_Click(object sender, EventArgs e)
{
this.WindowState = this.WindowState == FormWindowState.Normal ? FormWindowState.Maximized : FormWindowState.Normal;
}
}
}
Post something like this that does reproduce your issue and we will tell you why, or examine how this works and make your setup the same
I have a form with the property "MDI container" set to true that opens MDI children when pressing Labels on a MenuStrip, but I have two problems:
The first one is that once I open an MDI Child I can not open another one; I press different labels on the same MenuStrip that I pressed to open the current MDI child and nothing happens.
The second problem is that I can not open an MDI child form from another MDI child form from code.
Following this paragraph, I will show the relevant parts of my code and some things that I have tried (with no solutions)
//Event of the MenuStrip that opens an MDI child (homePage or sellProduct) from the MDI container
HomePage homePage = null;
SellProduct sellProduct = null;
private void HomeToolStripMenuItem_Click(object sender, EventArgs e)
{
if (homePage == null)
{
homePage = new HomePage();
homePage.TopLevel = false;
homePage.MdiParent = this;
}
homePage.Show();
}
private void ToolStripSellPtoduct_click(object sender, EventArgs e)
{
if (sellProduct == null)
{
sellProduct = new SellProduct();
sellProduct.TopLevel = false;
sellProduct.MdiParent = this;
}
sellProduct.Show();
}
I have tried to copy this in a child form but it does not work. something that may be important is that when I load the MDI container I also load the first MDI child:
private void MainPage_Load(object sender, EventArgs e)
{
if (homePage == null)
{
homePage = new HomePage();
homePage.TopLevel = false;
homePage.MdiParent = this;
}
homePage.Show();
}
And that is all the code I consider necesary for the first problem (I can not open a MDI child form from another using my MenuStrip). If you need anything from my code I will provide it.
In the second problem (I can not open an MDI child form from another from code) I am trying to open the MDI child form "HomePage" from the other one "SellProduct" when pressing a button located in the last one:
public partial class SellProduct : Form
{
public SellProduct()
{
InitializeComponent();
}
private void Button_Sale_Click(object sender, EventArgs e)
{
HomePage homePage = new HomePage();
homePage.show();
this.close();
}
}
}
}
The code above closes MDI form SellProduct showing the mdiparent (but it does not execute again the mdi parent, and the MenuStrip still does not work, is weird) and opens a MDI parent (where the MenuStrip actually works). So no, it does not open another mdi child, it just do weird stuffs.
And that is all, thank you for your time, every help is welcome, and hope you have a great day (: .
I have finally solved this, this is my solution:
Problem 1) Once I open an MDI Child I can not open another one; I press different labels on the same MenuStrip that I pressed to open the current MDI child and nothing happens.
Solution: The MDI child forms were not showing because I had to hide the one opened (from the MainPage) before showing another one.
Problem 2) I can not open an MDI child form from another MDI child form from code.
Solution: It is the same problem as the first one If the actual form displayed is not hidden a new one can not be shown, because of that you have to hide the current one, and then open the new one:
//In this case I want to show the HomePage
this.Hide();
HomePage homePage = new HomePage();
homePage.Show();
Is there any possibility to handle an event on a disabled WPF window? The main window is disabled by .ShowDialog() from other windows. In my application there is only one window enabled at a time and I want to improve the usability. If the user clicks on the wrong (disabled) main window the application should auto focus to the enabled window.
I know that disabled means that the window does not respond to any event, but is there a solution like a global event handler or some special WPF event?
I tried a PreviewMouseLeftButtonDown event but that did not work.
// event called from some special/ global event on disabled window
private void Window_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if(App.Current.Windows.Count > 1)
{
foreach(Window w in App.Current.Windows)
{
if(w.IsEnabled)
{
w.Focus();
break;
}
}
}
}
Thanks for your ideas/solutions!
Calling ShowDialog means you want to make window being showed modal, which disables other windows.
Switch this method to Show and you'll be able to use other windows as well.
Refer to this.
Thanks for the hint but as a requirement I've to ensure that the main window is freezed when another window is opened and I've found a solution: Instead of freezing the window with .ShowDialog() I've freezed all controls when a new window is opened with .Show().
private void DisableAllControls()
{
// parallel execution cause of many elements
Parallel.For(0, VisualTreeHelper.GetChildrenCount(this), index =>
{
(VisualTreeHelper.GetChild(this, index)
as UIElement).IsEnabled = false;
});
}
I also added a MouseDownEvent to get focus an the new window if the user clicks on the "freezed" main window. (There will be only one additional window open at the same time).
private void FocusLastOpen_MouseDown(object sender, MouseEventArgs e)
{
if (App.Current.Windows.Count > 1)
{
foreach (Window w in App.Current.Windows)
{
if (w.IsEnabled && w.GetType() != typeof(MainWindow))
{
w.Focus();
}
}
}
}
To reactivate the elements of the main window when the other window has closed I've written a static method which will be executed on the ClosingEvent.
public static void EnableAllControls()
{
MainWindow obj = null;
foreach(Window w in App.Current.Windows)
{
if(w.GetType() == typeof(MainWindow))
{
obj = w as MainWindow;
break;
}
}
if(obj == null) return;
Parallel.For(0, VisualTreeHelper.GetChildrenCount(obj), index =>
{
(VisualTreeHelper.GetChild(obj, index)
as UIElement).IsEnabled = true;
});
}
I'm following this tuto for create a multipage app in Winform. My MdiParent have
MainForm IsMdiParent = true
HomeForm frmHomeForm;
private void HomeIcon_Click(object sender, EventArgs e)
{
if(frmHomeForm == null)
{
frmHomeForm = new HomeForm();
frmHomeForm.MdiParent = this;
frmHomeForm.Show();
}
else
{
frmHomeForm.Activate();
}
}
If someone can help, it's first time I used MDI.
I was trying to show MdiChild on my MdiParent who was covered by another control. I remove the control on my MdiParent and my MdiChild now appear correctly in empty area.
I need to change a menuStrip item text of the main window (mdi container) from a child window,
something like this:
File
-Login
to
File
-Logout
On the main window add these:
public static MainForm Current;
public string FileLogin
{
get { return fileLoginToolStripMenuItem.Text; }
set { fileLoginToolStripMenuItem.Text = value; }
}
Obviously use the name that you set or was automatically set for the menu strip item for the login/logout menu item. then in the form constructor of the main form, set the Current.
public MainForm()
{
InitializeComponent();
Current = this;
}
Then from the other window/form you can call (to set the value):
MainForm.Current.FileLogin = "Logout";
But better than this is that you on your child window make an event,
public event Action UserLoggedIn = delegate { };
And on the MainForm have the MainForm subscribe to that event with a reverse of the above...
ChildForm.Current.UserLoggedIn += () => FileLogin = "Logout";
And have the child raise the event when the user logs in, with UserLoggedIn().
You can add to your MDI container a public method callable from any of its children.
Let's assume that this method is called SetLoggedStatus
(in MDI container)
public void SetLoggedStatus(bool status)
{
ToolStripMenuItem loginMenu = MenuStrip1.Items(0) as ToolStripMenuItem:
loginMenu.DropDownItems[0].Text = (status == true ? "Logout" : "Login");
}
Now we need to call this public method from the MDI Child form.
Every MDIChild form has a property that points back to the MDIParent
We can use that property casting the generic form instance to the correct MDI parent
(in MDIChild after login and supposing the MDIParent is a form class named MyParentForm)
MyParentForm f = this.MDIParent as MyParentForm;
if(f != null)
f.SetLoggedStatus(true);
This is how you can access main menu items from an MDI Child:
// this button in the child form
private void button1_Click(object sender, EventArgs e) {
ToolStripMenuItem tsm;
// file menu
tsm = (ToolStripMenuItem)this.MdiParent.MainMenuStrip.Items[0];
MessageBox.Show( tsm.DropDownItems[0].Name);
// first menu under File Menu
tsm.DropDownItems[0].BackColor = Color.Red;
// second menu under File Menu
tsm.DropDownItems[1].BackColor = Color.Wheat;
}
You can change the font or text same way; instead of back color you can use .text.