Reputation: 111
I have 2 buttons (custom buttons from now on) added to a button's control (main button from now on) when I enter to the main button I want the custom buttons to have an ImageBackground appear, which is working as excepted. Now, when I enter with the mouse into the custom buttons I want the 2 ImageBackground to appear again and when this happens I want the main button to stay on the same color as it was when I first entered it with my mouse which is happening as I wanted it, but the buttons are flickering AND sometimes when I enter another main button's custom button the previous button is still in the mouseEnter state. Why is that? Do I need to use async/await or something like that?
I think maybe it's because it has to compile when it happens, and it takes a little time and that's why it flickers and that's the reason I think I need to use async/await, but that is really new to me, so I don't know how to use it.
public class MyButton : Button
{
public MyButton()
{
SetStyle(ControlStyles.StandardClick | ControlStyles.StandardDoubleClick | ControlStyles.UserMouse, true);
Margin = new Padding(0);
TextAlign = ContentAlignment.TopCenter;
ImageAlign = ContentAlignment.TopLeft;
TextImageRelation = TextImageRelation.ImageBeforeText;
Font = new Font("Century Gothic", 11f, FontStyle.Bold);
Size = new Size(200, 75);
FlatStyle = FlatStyle.Flat;
BackColor = Color.FromArgb(0, 255, 255, 255);
FlatAppearance.MouseOverBackColor = ColorTranslator.FromHtml("#64A4B3B6");
FlatAppearance.BorderSize = 2;
FlatAppearance.BorderColor = Color.FromArgb(0, 255, 255, 255);
Button[] custom = CustomButtons();
for (int i = 0; i < 2; i++)
{
Controls.Add(custom[i]);
Controls[i].MouseHover += CustomOnMouseEnter;
}
MouseEnter += OnMouseEnter;
MouseLeave += OnMouseLeave;
}
private Button[] CustomButtons()
{
Button delete = new Button();
delete.Name = "delete";
delete.Location = new Point(this.Size.Width - 22, 2);
delete.Size = new Size(20, 20);
delete.FlatStyle = FlatStyle.Flat;
delete.BackColor = Color.Transparent;
delete.FlatAppearance.MouseOverBackColor = ColorTranslator.FromHtml("#64A4B3B6");
delete.FlatAppearance.BorderSize = 0;
Button customize = new Button();
customize.Name = "customize";
customize.Location = new Point(delete.Left - 20, delete.Top);
customize.Size = new Size(20, 20);
customize.FlatStyle = FlatStyle.Flat;
customize.BackColor = Color.Transparent;
customize.FlatAppearance.MouseOverBackColor = ColorTranslator.FromHtml("#64A4B3B6");
customize.FlatAppearance.BorderSize = 0;
Button[] buttons = { delete, customize };
return buttons;
}
private void OnMouseLeave(object sender, EventArgs e)
{
if (Controls.Count != 0)
{
Controls[0].BackgroundImage = null;
Controls[1].BackgroundImage = null;
}
if (BackColor != ColorTranslator.FromHtml("#64389eed"))
{
BackColor = Color.FromArgb(0, 255, 255, 255);
}
}
private void OnMouseEnter(object sender, EventArgs e)
{
if (Controls.Count != 0)
{
Controls[0].BackgroundImage = Resources.cross;
Controls[1].BackgroundImage = Resources.settings;
}
}
private void CustomOnMouseEnter(object sender, EventArgs e)
{
this.BackColor = ColorTranslator.FromHtml("#64A4B3B6");
Controls[0].BackgroundImage = Resources.cross;
Controls[1].BackgroundImage = Resources.settings;
}
}
Here is the output of this code
you can see the flickering when I enter the custom buttons AND the way the previous button is in the state of MouseEnter even tho I left it!
Every help is greatly appreciated!
Upvotes: 2
Views: 186
Reputation: 1099
The main problem is that "OnMouseLeave" gets called not only when the mouse leaves the entire control, but also when it enters any of the two small buttons, because they overlap their parent. You should also use "MouseEnter" event instead of "MouseHover".
Below you'll find a bit simplified version that should do the trick. The "inside" field holds the number of "enters" minus the number of "leaves" regarding the whole control. If it's value is greater then zero, the mouse is inside the control, including the two small buttons.
public class MyButton : Button
{
Image[] images;
Button[] custom;
Color hilited = ColorTranslator.FromHtml("#64A4B3B6");
int inside;
public MyButton()
{
SetStyle(ControlStyles.StandardClick | ControlStyles.StandardDoubleClick | ControlStyles.UserMouse, true);
Margin = new Padding(0);
TextAlign = ContentAlignment.TopCenter;
ImageAlign = ContentAlignment.TopLeft;
TextImageRelation = TextImageRelation.ImageBeforeText;
Font = new Font("Century Gothic", 11f, FontStyle.Bold);
Size = new Size(200, 75);
FlatStyle = FlatStyle.Flat;
BackColor = Color.Transparent;
FlatAppearance.MouseOverBackColor = hilited;
FlatAppearance.BorderSize = 2;
FlatAppearance.BorderColor = Color.FromArgb(0, 255, 255, 255);
images = new Image[] { Resources.cross, Resources.settings };
custom = CustomButtons();
for (int i = 0; i < 2; i++)
{
Controls.Add(custom[i]);
Controls[i].MouseEnter += CommonEnter;
Controls[i].MouseLeave += CommonLeave;
}
MouseEnter += CommonEnter;
MouseLeave += CommonLeave;
}
private Button[] CustomButtons()
{
Button delete = new Button();
delete.Name = "delete";
delete.Location = new Point(this.Size.Width - 22, 2);
delete.Size = new Size(20, 20);
delete.FlatStyle = FlatStyle.Flat;
delete.BackColor = Color.Transparent;
delete.FlatAppearance.MouseOverBackColor = hilited;
delete.FlatAppearance.BorderSize = 0;
Button customize = new Button();
customize.Name = "customize";
customize.Location = new Point(delete.Left - 20, delete.Top);
customize.Size = new Size(20, 20);
customize.FlatStyle = FlatStyle.Flat;
customize.BackColor = Color.Transparent;
customize.FlatAppearance.MouseOverBackColor = hilited;
customize.FlatAppearance.BorderSize = 0;
return new Button[] { delete, customize };
}
void CommonEnter(object sender, EventArgs e)
{
if (inside++ == 0)
{
BackColor = hilited;
custom[0].BackgroundImage = images[0];
custom[1].BackgroundImage = images[1];
}
}
void CommonLeave(object sender, EventArgs e)
{
if (--inside == 0)
{
BackColor = Color.Transparent;
custom[0].BackgroundImage = null;
custom[1].BackgroundImage = null;
}
}
}
Upvotes: 1