I am struggling to figure out why my User Control events are not executing. I have a dynamic UserControl, "MainMenu", within a dynamic UserControl, "MainControl".
In MainMenu I have the following:
public partial class MainMenu : UserControl
{
public MainMenu()
{
InitializeComponent();
///
///Event Subscriptions
///
this.LostFocus += this.MainMenu_LostFocus;
}
public void MainMenu_LostFocus(object sender, EventArgs e)
{
this.Visible = false;
}
}
In MainControl:
public partial class MainControl : UserControl
{
private Custom_UI.MainMenu mainMenu = new Custom_UI.MainMenu();
public MainControl()
{
InitializeComponent();
mainMenu.Visible = false;
mainMenu.BringToFront();
this.Controls.Add(mainMenu);
mainMenu.BringToFront();
}
private void menuButton1_Click(object sender, EventArgs e)
{
if (mainMenu.Visible)
{
mainMenu.Visible = false;
}
else
{
mainMenu.Visible = true;
this.Focus();
}
}
}
And finally the main Form:
public partial class Form1 : Form
{
MainControl mainControl = new MainControl() {
Dock = DockStyle.Fill
};
public Form1()
{
InitializeComponent();
this.Controls.Add(mainControl);
}
}
So basically, the method MainMenu_LostFocus
is not being invoked when I click elsewhere on the form. I have also tried using this.MouseLeave
instead of this.LostFocus
.
Hopefully this I was clear enough and thanks in advance.
OK... lest try another, improved approach. the reason is the fact we don't want to be forced to handle click on each and every control added to MainControl
and force it to receive focus. it's just clumsy.
We'd also like to encapsulate the whole code in a single control ( MainMenu
) - not "must have", but surely "nice to have"
this is my new idea:
public partial class MainMenu : UserControl
{
//this class will be checking native windows messages, the one we're interested in is "MouseDown" with 0x0201 code
//(i won't be describing the whole stuff what is going inside: have that checked if you wish in documentation :)
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
public class TestMessageFilter : IMessageFilter
{
const int WM_MOUSEMOVE = 0x200;
const int WM_LBUTTONDOWN = 0x0201;
public event EventHandler MouseMoved;
public event EventHandler MouseDown;
public bool PreFilterMessage(ref Message m)
{
// Blocks all the messages relating to the left mouse button.
if (m.Msg == WM_LBUTTONDOWN)
{
MouseDown?.Invoke(this, new EventArgs());
}
return false;
}
}
public MainMenu()
{
InitializeComponent();
//use our class that checks Windows Messages, subscribe it's event
var tmf = new TestMessageFilter();
tmf.MouseDown += UserControl1_MouseDown;
//and add our class to Application's messages filter.
Application.AddMessageFilter(tmf);
//use "ordinary" events to detect mouse enter/mouse leave over control
this.MouseLeave += UserControl1_MouseLeave;
this.MouseEnter += UserControl1_MouseEnter;
}
private void UserControl1_MouseDown(object sender, EventArgs e)
{
//if mouse is not over control make it's visible false
if (mouseLeft)
{
this.Visible = false;
}
}
//variable to save mouse state (if that is over the control, or left)
private bool mouseLeft;
private void UserControl1_MouseEnter(object sender, EventArgs e)
{
mouseLeft = false;
}
private void UserControl1_MouseLeave(object sender, EventArgs e)
{
mouseLeft = true;
}
}
hope this solution will be better and more usable