I have an MDI form in which I create two MDIChild forms, cf1 and cf2.
I have a button which, when clicked, should toggle the "focus" (i.e. which form is "on top") between cf1 and cf2.
In the constructor of the MDI parent, I assign the MDIParent of the respective cf1 and cf2. Then I execute cf1.Show() then cf2.Show(), thus cf2 ends up "on top" or "focused."
When I press the toggle button the first time, cf1 becomes focused and cf2 becomes inactive.
Any further attempts to change the z-order after this are unsuccessful.
I have tried Activate, ActivateMdiChild, TopMost and BringToFront, all without success.
using System;
using System.Windows.Forms;
namespace MDITest
{
public partial class Form1 : Form
{
private readonly ChildForm cf1 = new ChildForm();
private readonly ChildForm cf2 = new ChildForm();
public Form1()
{
InitializeComponent();
cf1.MdiParent = this;
cf2.MdiParent = this;
cf1.Text = "Window 1";
cf2.Text = "Window 2";
cf1.Show();
cf2.Show();
}
private void Child_WMSize(object sender, EventArgs e)
{
LblWindow1State.Text = $"Window 1 - {cf1.WindowState.ToString()}";
LblWindow2State.Text = $"Window 2 = {cf2.WindowState.ToString()}";
}
private void BtnFocus_Click(object sender, EventArgs e)
{
//if (ActiveMdiChild == cf1) cf2.Activate();
//if (ActiveMdiChild == cf2) cf1.Activate();
//if (ActiveMdiChild == cf1) ActivateMdiChild(cf2);
//if (ActiveMdiChild == cf2) ActivateMdiChild(cf1);
//if (ActiveMdiChild == cf1) cf2.TopMost = true;
//if (ActiveMdiChild == cf2) cf1.TopMost = true;
if (ActiveMdiChild == cf1) cf2.BringToFront();
if (ActiveMdiChild == cf2) cf1.BringToFront();
}
}
}
The expected result would be to toggle the focus between the two forms as needed. The actual result is that I can only change from cf2 to cf1, not the other way around.
I even tried the shotgun approach:
if (ActiveMdiChild == cf1)
{
cf2.BringToFront();
cf2.Activate();
ActivateMdiChild(cf2);
cf2.TopMost = true;
cf1.TopMost = false;
}
if (ActiveMdiChild == cf2)
{
cf1.BringToFront();
cf1.Activate();
ActivateMdiChild(cf1);
cf1.TopMost = true;
cf2.TopMost = false;
}
With no change in my results.
You can use the following code to toggle between any number of Mdi children windows:
if (MdiChildren.Length == 0)
return;
var i = Array.IndexOf(MdiChildren, ActiveMdiChild);
MdiChildren[(MdiChildren.Length + i + 1) % MdiChildren.Length].Activate();
Or
this.Controls.OfType<MdiClient>().First()
.SelectNextControl(ActiveMdiChild, true,true, true, true);
Or
SendKeys.SendWait("^{TAB}"); // Control + TAB as well as Control + F6
Related
I am trying to create an alarm clock and I want a second form to show when the alarm starts.
The problem is that it partialy loads and I get the loading cursor when I hover over it. At first I though I should just wait but nothing changes.
this is how it should be:
this is the function that calls the second form:
private void ring()
{
if (System.DateTime.Now.ToString("HH:mm") == temp && songisplaying == false)
{
soundplayer.PlayLooping();
songisplaying = true;
if (WindowState == FormWindowState.Minimized)
{
this.Show();
WindowState = FormWindowState.Normal;
}
wakeupForm win = new wakeupForm();
win.Show();
}
This is the code of the second form
public partial class wakeupForm : Form
{
public wakeupForm()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
}
}
This is the code that calls the ring function:
public Form1()
{
InitializeComponent();
num1.Maximum = 2;
num3.Maximum = 5;
num4.Maximum = 9;
var timer2 = new System.Threading.Timer(e => ring(),null,TimeSpan.Zero,TimeSpan.FromSeconds(10));
ofd.Filter = "WAV | *.wav";
}
System.Threading.Timer runs ring() on a thread from the thread pool. ring() in turn tries to instantiate a form which should always be done on the main thread (all access to windows forms should be done from the main thread).
Use the following instead:
private void ring()
{
if (System.DateTime.Now.ToString("HH:mm") == temp && songisplaying == false)
{
songisplaying = true;
if (this.InvokeRequired)
this.Invoke(new MethodInvoker(()=>{ringOnMainThread()}));
else
ringOnMainThread();
}
}
private void ringOnMainThread()
{
soundplayer.PlayLooping();
timer1.Start();
if (WindowState == FormWindowState.Minimized)
{
this.Show();
WindowState = FormWindowState.Normal;
}
wakeupForm win = new wakeupForm();
win.Show();
}
Note that I have moved songisplaying = true; to avoid a race condition.
I believe that you should stop your timer when the form is shown.
(Check your timer interval. If it ticks more than one time in one minute, it will hit your ring() method more than one time).
You should stop your timer in the ring() method and restart on FormClosing of your wakeupForm.
private void ring() {
if (System.DateTime.Now.ToString("HH:mm") == temp && songisplaying == false) {
soundplayer.PlayLooping();
timer1.Stop();//Stop your timer.
songisplaying = true;
if (WindowState == FormWindowState.Minimized)
{
this.Show();
WindowState = FormWindowState.Normal;
}
wakeupForm win = new wakeupForm();
win.Form_Closed += win_Closed;
win.Show();
}
private void wnd_Closed(object sender, EventArgs e)
{
timer1.Start();
}
this is my problem: I have a main form where I have a panel that contains some buttons, when the user clicks a button a form is opened.( I have some buttons and clicking these buttons the user can open different forms )If the user click again the same button he can close the form.
this is what I do:
in the main form I have a method that is invoked when one of these buttons is clicked by the user, the method checks the text associated to the button in order to decide which is the button clicked. Once I have discovered which is the button that has been clicked it launches the form associated with the button.
this is the code
private void tlStBtn_Click(object sender, EventArgs e)
{
//// loop through all items in the ToolStrip
//foreach (Object item in toolStripMain.Items)
//{
// // if this item is a ToolStripButton object, check it
// if (item is ToolStripButton)
// {
// // cast the item to a ToolStripButton object and check it if the sender of the event is the currently looked at button in the loop
// ToolStripButton button = (ToolStripButton)item;
// button.Checked = (button == sender);
// }
//}
foreach (ToolStripItem item in this.VerticalToolBox.Items)
{
if ((item != sender) &&
(item is ToolStripButton))
{
((ToolStripButton)item).Checked = false;
}
}
if (sender_old != sender)
{
sender_old = sender;
if ((sender as ToolStripButton).Text == "Protection")
{
if (!Application.OpenForms.OfType<frm_Protection>().Any())
{
frm_Protection Newf = new frm_Protection(ref CurrentProject);
Newf.Show();
}
}
else
{
if (Application.OpenForms.OfType<frm_Protection>().Any())
{
Application.OpenForms.OfType<frm_Protection>().First().Close();
Properties.Settings.Default.Save();
}
GC.Collect();
GC.WaitForPendingFinalizers();
}
if ((sender as ToolStripButton).Text == "Info")
{
if (!Application.OpenForms.OfType<Frm_ObjectInfo>().Any())
{
Frm_ObjectInfo Newform = new Frm_ObjectInfo();
Newform.Show();
}
}
else
{
if (Application.OpenForms.OfType<Frm_ObjectInfo>().Any())
{
Application.OpenForms.OfType<Frm_ObjectInfo>().First().Close();
Properties.Settings.Default.Save();
}
GC.Collect();
GC.WaitForPendingFinalizers();
}
if ((sender as ToolStripButton).Text == "Layers")
{
if (!Application.OpenForms.OfType<Frm_LayersManage>().Any())
{
Frm_LayersManage Newform = new Frm_LayersManage();
Newform.Show();
Application.OpenForms.OfType<Frm_LayersManage>().First().UpdateLayers(null, CurrentProject.layers);
}
}
else
{
if (Application.OpenForms.OfType<Frm_LayersManage>().Any())
{
Application.OpenForms.OfType<Frm_LayersManage>().First().Close();
Properties.Settings.Default.Save();
UpdateScreen = true;
}
GC.Collect();
GC.WaitForPendingFinalizers();
}
if (Properties.Settings.Default.Grip2Enabled && (sender as ToolStripButton).Text == "Insert Grip")
{
gbx_SelectGrip.Visible = true;
}
else
{
gbx_SelectGrip.Visible = false;
}
//SelectedPoints.Clear();
//MousePointList.Clear();
//myIDs.Clear();
//IdxPointsEnt.Clear();
//RatiosLines.Clear();
//CadSource.cuts_tmp.Clear();
//IDAddedCutList.Clear();
//ZoomPort.SetValue(0, 0);
//ZoomPort.SetValue(0, 1);
//ZoomPort.SetValue(0, 2);
//ZoomPort.SetValue(0, 3);
//// Reset index of scrap selected by moving gripper
//idxScrap = -1;
//pnl_OpenTK.Refresh();
//// Se ho evidenziato uno SCRAP , annullo l'evidenziazione.
//if (IdsScrapDisablePath[0] != -1)
//{
// int identifiedScrap = CadSource.IdToIdx_Scrap(IdsScrapDisablePath[0]);
// if (CadSource.scraps[identifiedScrap].GripExists())
// {
// CadSource.scraps[identifiedScrap].Enabled = ScrapAbilitation.Enabled; // Disable clicked scrap
// }
// else
// {
// CadSource.scraps[identifiedScrap].Enabled = ScrapAbilitation.WithoutGrip; // Disable clicked scrap
// }
//}
//numScrap = 0;
//IdsScrapDisablePath = new List<int>() { -1, -1 };
}
else
{
(sender as ToolStripButton).Checked = false;
(sender as ToolStripButton).BackColor = Color.Transparent;
sender_old = new object() { };
if (Application.OpenForms.OfType<frm_Protection>().Any())
{
Application.OpenForms.OfType<frm_Protection>().First().Close();
Properties.Settings.Default.Save();
}
if (Application.OpenForms.OfType<Frm_ObjectInfo>().Any())
{
Application.OpenForms.OfType<Frm_ObjectInfo>().First().Close();
Properties.Settings.Default.Save();
}
if (Application.OpenForms.OfType<Frm_LayersManage>().Any())
{
Application.OpenForms.OfType<Frm_LayersManage>().First().Close();
Properties.Settings.Default.Save();
}
gbx_SelectGrip.Visible = false;
GC.Collect();
GC.WaitForPendingFinalizers();
}
SelectedPoints.Clear();
MousePointList.Clear();
myIDs.Clear();
IdxPointsEnt.Clear();
RatiosLines.Clear();
CurrentProject.cuts_tmp.Clear();
IDAddedCutList.Clear();
ZoomPort.SetValue(0, 0);
ZoomPort.SetValue(0, 1);
ZoomPort.SetValue(0, 2);
ZoomPort.SetValue(0, 3);
// Reset index of scrap selected by moving gripper
idxScrap = -1;
pnl_OpenTK.Refresh();
// Se ho evidenziato uno SCRAP , annullo l'evidenziazione.
if (IdsScrapDisablePath[0] != -1)
{
int identifiedScrap = CurrentProject.IdToIdx_Scrap(IdsScrapDisablePath[0]);
if (CurrentProject.scraps[identifiedScrap].GripExists())
{
CurrentProject.scraps[identifiedScrap].Enabled = ScrapAbilitation.Enabled; // Disable clicked scrap
}
else
{
CurrentProject.scraps[identifiedScrap].Enabled = ScrapAbilitation.WithoutGrip; // Disable clicked scrap
}
}
numScrap = 0;
IdsScrapDisablePath = new List<int>() { -1, -1 };
}
the forms that are opned clicking the buttons are forms where I have set the controlbox at false because I don't want that the user is able to close the forms without clicking again the button that has clicked to open it, but I have found a problem because if the user closes the form in this way (see the picture below) the status of the button remains checked but the form has been closed manually
To solve this problem I have thought to add this method associated to the event closing of my forms this is the code
private void frm_Protection_FormClosed(object sender, FormClosedEventArgs e)
{
////// if user closes manually the window without using the button I have to change the state of the button
Frm_Main f = new Frm_Main();
f = Application.OpenForms.OfType<Frm_Main>().Last();
f.tlsBut_Protection.Checked = false;
}
with this code if I close manually the form the status of the button it becomes false again in the main form
but I have discovered that It causes some problems to my program , one of this problem is that after closing the form if I click again the button it seems that the method associated to the clicking event is not called and the form is not opened I have to click it twice before it works again.
do you know why what do I do in the wrong way???
thanks for your help
To prevent a Form from closing, you can subscribe to the FormClosing event, which fires before the Form closes, and intercept (and cancel) the user's action.
private void frm_Protection_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.UserClosing)
e.Cancel = true;
}
Unfortunately, clicking the "X" (in the Taskbar preview or in the program itself) and calling this.Close() are both treated as "UserClosing" close reasons, so we need to modify it slightly.
Add a property to frm_Protection, and use that to determine whether the Form can be closed:
public bool CanClose { private get; set; }
private void frm_Protection_FormClosing(object sender, FormClosingEventArgs e)
{
e.Cancel = !CanClose;
}
And then only set the property to true when you want to allow the Form to be closed:
var frmP = Application.OpenForms.OfType<frm_Protection>().FirstOrDefault();
if (frmP != null)
{
frmP.CanClose = true;
frmP.Close();
}
I am using .NET 3.5 with c# winforms. in this i am using MDI child tab control. it works fine if i open a form, it will open successfully. if i open same form again it opens. that means duplication of tabs.
My code is like below...
private void Main_MdiChildActivate(object sender, EventArgs e)
{
if (this.ActiveMdiChild == null)
tabForms.Visible = false; // If no any child form, hide tabControl
else
{
this.ActiveMdiChild.WindowState = FormWindowState.Maximized; // Child form always maximized
if (this.ActiveMdiChild.Tag == null)
{
TabPage tp = new TabPage(this.ActiveMdiChild.Text);
tp.Tag = this.ActiveMdiChild;
tp.Parent = tabForms;
tabForms.SelectedTab = tp;
this.ActiveMdiChild.Tag = tp;
this.ActiveMdiChild.FormClosed += new FormClosedEventHandler(ActiveMdiChild_FormClosed);
}
if (!tabForms.Visible) tabForms.Visible = true;
}
}
in this, every time this.ActiveMdiChild.Tag takes the value of null so it opens new form again and again. that means duplication of forms in tab control
Add the above method in order to check if the form with the name is as child in the mdi parent.
public static bool FormExist(string formName, out Form frm)
{
frm = null;
bool exist = false;
Form[] f = yourMdiParent.ActiveForm.MdiChildren;
foreach (Form ff in f)
{
if (ff.Name == formName)
{
frm = ff;
exist = true;
break;
}
}
return exist;
}
and add the check on adding the child form.
Form forma;
if(FormExist("yourchildformid",out forma) && forma !=null)
{
forma.Focus();
return;
}
I'm late to the party, but I use:
private void serviceManagerToolStripMenuItem_Click(object sender, EventArgs e)
{
// prevent duplicates
if (Application.OpenForms.OfType<ServiceManager>().FirstOrDefault() != null)
{
return;
}
ServiceManager serviceManager = new ServiceManager { MdiParent = this, WindowState = FormWindowState.Maximized };
serviceManager.Show();
}
I was able to get this to work with a few tweeks by combining other solutions
add this function to your Parent MDI Form
private bool checkTabExists(string tabVal)
{
foreach (TabPage tab in tabForms.TabPages)
{
if (tab.Text == tabVal)
return true;
}
return false;
}
Then Modify the original Form_MdiChildActivate to include an additional check
private void Main_MdiChildActivate(object sender, EventArgs e)
{
if (this.ActiveMdiChild == null)
tabForms.Visible = false; // If no any child form, hide tabControl
else
{
this.ActiveMdiChild.WindowState = FormWindowState.Maximized; // Child form always maximized
if(checkTabExists(this.ActiveMdiChild.Name))
{
//If the Child Form already Exists Go to it
foreach (TabPage tab in tabForms.TabPages)
{
if (tab.Text == this.ActiveMdiChild.Name)
tabForms.SelectedTab = tab;
}
}
// If child form is new and has no tabPage, create new tabPage
else if (this.ActiveMdiChild.Tag == null)
{
ActiveMdiChild.TopLevel = false;
ActiveMdiChild.Dock = DockStyle.Fill;
ActiveMdiChild.FormBorderStyle = FormBorderStyle.None;
// Add a tabPage to tabControl with child form caption
TabPage tp = new TabPage(this.ActiveMdiChild.Text);
tp.Tag = this.ActiveMdiChild;
tp.Parent = tabForms;
tabForms.SelectedTab = tp;
this.ActiveMdiChild.Tag = tp;
this.ActiveMdiChild.FormClosed += new FormClosedEventHandler(Main_FormClosed);
}
if (!tabForms.Visible) tabForms.Visible = true;
//tabForms.AutoSize = true;
//tabForms.TabPages[0].Height = 38;
}
}
on Mdi parent form i am calling my child forms using menu items. on Child form Load my Menu item should be disabled on child form closed it will again Enabled.., i try FormClosing event handler i get the answer..,
private void btnMn1_Click(object sender, EventArgs e)
{
Forms.Cnblfrm cnbfrm = new Cnsmblfrm();
cnsmbfrm.MdiParent = this;
cnsmbfrm.Text = btnMn1.Text;
cnsmbfrm.Show();
this.btnMn1.Enabled = false;
cnbfrm.FormClosed += new FormClosedEventHandler(cnsmbfrm_FormClosed);
}
void cnbfrm_FormClosed(object sender, FormClosedEventArgs e)
{
btnMn1.Enabled = true;
//throw new NotImplementedException();
}
by using the above code i am getting the answer but i have morethan 20 ChildForms. By using this method My coding is increasing...., there is any method instead of this....,
If I understand you right: you have 20 buttons where every button opens a specific form, right?
If so, you can set the tag-property of each button to the form it opens. then you have to iterate through all buttons and set the click-event. All buttons have the same click-event. (let's call it btn_click)
the code of btn_click can look like:
private void btn_click(object sender, EventArgs e)
{
Button button = sender as Button;
if(button == null)
return;
Form form = button.Tag as Form;
if(form == null)
return;
form.MdiParent = this;
form.Text = button.Text;
form.Show();
button.Enabled = false;
form.Tag = button;
form.FormClosed += FormClosed;
}
private void FormClosed(object sender, FormClosedEventArgs e)
{
Form form = sender as Form;
if(form == null)
return;
Button button = form.Tag as Button;
if(button == null)
return;
button.Enabled = true;
}
Actually Its my first project. While I want to convert my VB.Net2008 to C#2010 I have few clarification pls.
In Form2 Properties I set - IsMDIContainer = True. Then the below code to open my MdiChild and now what is my problem when I click the close button, it's also closing the MDIParent. But I need to close only mdichild... for that I tried as like Vb.Net2008 style by the following codes placed in MDIParent Form2, Its not working. Any right directions ...
private void toolStripButton1_Click(object sender, EventArgs e)
{
Form3 NwMdiChild2 = new Form3;
NwMdiChild2.MdiParent = this;
NwMdiChild2.Dock = System.Windows.Forms.DockStyle.Fill;
NwMdiChild2.Show();
}
private void Form2_FormClosing(object sender, System.Windows.Forms.FormClosingEventArgs e)
{
Form[] MdiChildForms = this.MdiChildren;
int kkk1 = MdiChildForms.Length;
int x = 0;
for (x = 0; x <= MdiChildForms.Length - 1; x += 1)
{
if (MdiChildForms[x].Name == "Form1")
{
kkk1 = kkk1 - 1;
}
MdiChildForms[x].Close();
}
if (kkk1 > 0)
{
// For Not Closing
e.Cancel = true;
}
else
{
// For Closing
e.Cancel = false;
Application.Exit();
}
}
Any Right Directions for Me?
I'm not sure if I understand well what you want to achieve: do you want, when click Parent Form close button, insteed of closing parent form, to close all the child's form? Form2 is your main form (parent MDI container), Form3 is the MDI children, isn't it?
Please try following code and tell if it's what you are asking for:
private void toolStripButton1_Click(object sender, EventArgs e)
{
Form3 NwMdiChild2 = new Form3(); //don't forget ()
NwMdiChild2.MdiParent = this;
NwMdiChild2.Dock = System.Windows.Forms.DockStyle.Fill;
NwMdiChild2.Show();
}
private void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
//if no MDI child - this is going to be skipped and norlmal Form2 close takes place
if (this.MdiChildren.Length > 0) //close childrens only when there are some
{
foreach (Form childForm in this.MdiChildren)
childForm.Close();
e.Cancel = true; //cancel Form2 closing
}
}