Is there a way to detect changes to MDI child when one of the child is closed?
I'm trying to create a dynamic dropdown menu item in the toolstrip menu item that can be add or remove programatically from the MDI child.
Because of the instance is dispose when the child is close,i couldn't cross check with the toolstrip menu item.The adding part is successful but the removing part is a problem.
ToolStripMenuItem temp = new ToolStripMenuItem();
if(form.Visible == true)
{
this.SuspendLayout();
temp.Name = form.Text;
temp.Size = new System.Drawing.Size(112, 22);
temp.Text = form.Text;
this.windowsToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { temp });
this.ResumeLayout();
}
You should use FormClosing event. It executes before disposing the instance of the form. FormClosed event fires after disposing of the form's instance.
Related
I want to open a WPF ContextMenu when the user clicks the system tray icon. With Windows Forms this is straight-forward, just call notifyIcon.ContextMenu = contextMenu and you're set.
On WPF we can not set the ContextMenu that easily because WPF's ContextMenu class is not related to Forms ContextMenu. The alternative I have been pursuing is to handle NotifyIcon's Click event to open the WPF-style ContextMenu.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
// This is intended to be a system tray application so we hide the window
this.Visibility = Visibility.Hidden;
// Winform context menu
// The context menu closes when the user clicks anywhere outside the menu
// The user can navigate the menu with the keyboard arrows and close with ESC
var notifyIcon1 = new System.Windows.Forms.NotifyIcon();
var contextMenu = new System.Windows.Forms.ContextMenu();
var menuItem = new System.Windows.Forms.MenuItem();
menuItem.Text = "WinForm Menu Item";
contextMenu.MenuItems.Add(menuItem);
notifyIcon1.ContextMenu = contextMenu;
notifyIcon1.Icon = Properties.Resources.ico;
notifyIcon1.Visible = true;
// WPF context menu
// The user cannot close the menu by clicking outside its bounds
// Does not detect any keyboard input
var notifyIcon2 = new System.Windows.Forms.NotifyIcon();
notifyIcon2.Icon = Properties.Resources.ico;
notifyIcon2.Visible = true;
notifyIcon2.Click += NotifyIcon2_Click;
}
private void NotifyIcon2_Click(object sender, EventArgs e)
{
var contextMenu = new ContextMenu();
var menuItem = new MenuItem();
menuItem.Header = "WPF Menu Item";
contextMenu.Items.Add(menuItem);
contextMenu.IsOpen = true;
}
}
The issue with this approach is that the WPF ContextMenu never gets any hint that the user has navigated away from the menu and should close (Eg, when the user clicks outside the bounds of the menu). None of the Focus or MouseCapture events are ever triggered and I am unable to close the menu other than by clicking on one of its items.
So the question here, to put slightly different, is: how do I properly emulate the NotifyIcon's ContextMenu closing behavior using WPF's ContextMenu?
I faced similar issue. You can try if you want
notifyIcon1.ContextMenuStrip = new Forms.ContextMenuStrip();
notifyIcon1.ContextMenuStrip.Items.Add("YourMenuItem",null, MenuItemEvent);
I hope this will solve the problem.
I have a program with a horizontal dropbox with 4 options to choose from in which "sub buttons" will appear when I click on one of these buttons:
Here is the interface:
And what I want to do is that when I click on one of the drop down menu options, I want a childform to spawn on the black area, using this:
private Form activeForm = null;
private void openChildForm(Form childForm)
{
if (activeForm != null)
activeForm.Close();
activeForm = childForm;
childForm.TopLevel = false;
childForm.FormBorderStyle = FormBorderStyle.None;
childForm.Dock = DockStyle.Fill;
MainInterfacePanel.Controls.Add(childForm);
MainInterfacePanel.Tag = childForm;
childForm.BringToFront();
childForm.Show();
}
However, when I do so, the childform does appear normally, but it covers the dropdown menu, preventing me to select other functions:
Here's how it looks like(the childform is still a blank form, thus the whiteness):
I tried solving this issue by using item.bringToFront() on the buttons, but it dosent seem to work.
Basically, I want the Parent Form to stay behind the childform, while having the buttons be infront of the childform, like an overlap. Is there a way to do so?
Also, when I remove the 'childForm.BringToFront()', for whatever reason it spawns behind the interface.
You should have to use Panel in which child form may appear. Simply add Panel from Toolbox and change its Dock property to top and place all your menu items in that Panel and also add new Panel i.e. MainPanel to display forms and than use following code to display form inside the Panel
SubForm objForm=new SubForm();
objForm.TopLevel = false;
MainPanel.Controls.Add(objForm);
objForm.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
objForm.Dock = DockStyle.Fill;
objForm.Show();
In my application I dynamically create buttons and add them to a flow control that is later cleared. I have this on a timer to refresh every X seconds to clear then add buttons. This is all being done on the main form.
The problem is when I have a child form launched the main form will steal focus every time the controls are added to the flow control.
Here is the code I have that dynamically clears and adds the controls on the main form.
I call this before adding the controls
flw_users.Controls.Clear();
This is what I call to dynamically create/add the buttons to the flow control.
private void DisplayNewMobileUser(string MobileUserName)
{
// Set Button properties
Button button = new Button();
button.Text = MobileUserName;
button.Size = new System.Drawing.Size(171, 28);
button.Name = MobileUserName;
button.BackColor = System.Drawing.Color.White;
button.FlatAppearance.BorderColor = System.Drawing.Color.White;
button.Font = new System.Drawing.Font("Segoe UI", 12F, System.Drawing.FontStyle.Bold);
button.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
button.ForeColor = System.Drawing.Color.Black;
button.Margin = new System.Windows.Forms.Padding(0, 1, 0, 1);
button.TextAlign = System.Drawing.ContentAlignment.TopLeft;
button.Click += new EventHandler(MobileUserName_OnClick);
flw_users.Controls.Add(button);
}
Is there a way to add buttons to a flow control with out it always stealing focus ?
Thanks to LarsTech I researched how to properly dispose each control added to flw_users. The main issues was fixed by changing the OnClick event to change focus to a label, which in turn didn't cause the main form to gain topmost every time the controls were cleared and re added. So everytime I clicked a button that button still had focus while the new form appeared.
Thanks everyone !
Here is the code I used to properly clear the controls
private void ClearUsers()
{
List<Control> ctrls = new List<Control>();
foreach (Control c in flw_users.Controls)
{
ctrls.Add(c);
}
flw_users.Controls.Clear();
foreach (Control c in ctrls)
{
c.Dispose();
}
}
I Create a Windows Forms application with C#.
I have a general Form and a panel on it.
I show subForm into this panel with code:
SubForm objForm= SubForm.InstanceForm();
this.IsMdiContainer = true;
objForm.TopLevel = false;
pnlSubSystem.Controls.Add(objForm);
objForm.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
objForm.Dock = DockStyle.Fill;
objForm.Show();
now I want to show other form on subForm of this panel, But I dont know how to do it.
I think your problem resolved by this code:
SubForm objForm= SubForm.InstanceForm();
objForm.TopLevel = false;
pnlSubSystem.Controls.Add(objForm);
objForm.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
objForm.Dock = DockStyle.Fill;
objForm.Show();
As I understand, you're very close. To add another form into subform try the same code instead:
pnlSubSystem.Controls.Add(objForm);
use (where objForm2 is the new subForm)
SubForm objForm2 = new SubForm();
objForm.Controls.Add(objForm2);
Since you already got the answer that by removing this.IsMdiContainer = true; your code would run perfectly fine. Because IsMdiContainer property changes the display and behavior of the form to an MDI parent form. When this property is set to true, the form displays a submerged client area. All MDI child forms assigned to the parent form are displayed within its client area.
SubForm objForm= SubForm.InstanceForm();
objForm.TopLevel = false;
pnlSubSystem.Controls.Add(objForm);
objForm.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
objForm.Dock = DockStyle.Fill;
objForm.Show();
objForm form which will be the template for the child forms. Each time you want to create a new child window to your application, you can create a new instance of this template form and make the first form as its parent form.
//Create a new instance of the MDI child template form
SubForm objForm = new SubForm();
//Set parent form for the child window
objForm.MdiParent=this; // Last ObjForm or something
//Display the child window
objForm.Show();
Another way:
objForm.TopLevel = false;
objForm.Parent = pnlSubSystem;
objForm.Show();
This is my first answer on Stackoverflow.
I have a Windows Form shown as a model dialog. It has a context menu of class ContextMenuStrip. I set shortcuts to several items in the context menu. But this shortcuts works only when context menu is shown. How to make them work even if the context menu is not activated?
The only way I know is to handle KeyPress event of the form, iterate recursively through all the items in the context menu and compare its ShortcutKeys property with the actual key pressed. If the match, manually call OnClick event for this item. Any better ideas?
Use the ToolStripMenuItem.ShortCutKeys property, so that you no need to iterate and call the event handlers.
Sample Code:
ContextMenuStrip _contextMenuStrip = new ContextMenuStrip();
var menuItem = new ToolStripMenuItem("Copy");
menuItem.ShortcutKeys = Keys.Control | Keys.C;
_contextMenuStrip.Items.Add(menuItem);
Are you opening the ContextMenuStrip in code or is the ContextMenuStrip property of the Form set to the ContextMenuStrip you created? If it's being opened in code, are you able to set the Form property instead? That should let you do the shortcut without having to open the menu first.
Finally, I've implemented manual iteration in the KeyPressed event handler:
Action<ToolStripMenuItem> check_shortcut = null;
check_shortcut = (node) =>
{
if (node.ShortcutKeys == e.KeyData)
{
node.PerformClick();
}
foreach (ToolStripMenuItem child in node.DropDownItems)
{
check_shortcut(child);
}
};
foreach (ToolStripMenuItem item in MyContextMenuStrip.Items)
{
check_shortcut(item);
}