【发布时间】:2019-09-07 06:23:07
【问题描述】:
当我进入主按钮时,我有 2 个按钮(从现在开始的自定义按钮)添加到按钮的控件(从现在开始的主按钮)我希望自定义按钮出现 ImageBackground,它可以正常工作。现在,当我用鼠标进入自定义按钮时,我希望 2 ImageBackground 再次出现,当发生这种情况时,我希望主按钮保持与我第一次用鼠标输入时相同的颜色,这发生在我想要它,但按钮闪烁,有时当我输入另一个主按钮的自定义按钮时,前一个按钮仍处于 mouseEnter 状态。这是为什么?我需要使用 async/await 或类似的东西吗?
我想可能是因为它必须在它发生时进行编译,这需要一点时间,这就是它闪烁的原因,这就是我认为我需要使用 async/await 的原因,但这对我来说真的很新,所以不知道怎么用。
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;
}
}
这是这段代码的输出 当我输入自定义按钮时,您可以看到闪烁,即使我离开了前一个按钮,它仍处于 MouseEnter 状态!
非常感谢每一个帮助!
【问题讨论】:
-
当您将光标移到一个小按钮上时,您会触发容器(main 按钮)的
MouseLeave事件,该事件会将子按钮。较小的按钮MouseEnter重置图像并更改容器的背景颜色(因此,闪烁)。当鼠标离开较小的按钮区域时,当光标没有进入其客户区域时,容器的MouseLeave事件不会被触发,因此较深的颜色会持续存在。如果你构建一个用户控件而不是自定义控件会更容易。 -
那里的 Graphics 对象存在重大问题。
Resources对象是一个工厂:每次调用Resources.[SomeImage]时,都会创建一个新的位图,但永远不会丢弃它,而是将控件的 image 属性设置为null(这对释放之前的资源没有任何作用)分配)。您应该将每个 Bitmap 分配给一个 Bitmap 对象,并使用该对象分配控件的 Image 属性,然后在释放主控件时释放这些 Bitmap(实现IDisposable)。 -
而且你不应该一直设置自定义按钮的背景图片,但你应该改变按钮的可见性。
-
@Jimi
You should assign each Bitmaps to a Bitmap object and use this object to assign the Image property of your controls, then dispose of these Bitmaps when you main control is disposed (implementing IDisposable).所以我要做的是,实现 IDisposable。所以(public class MyButton : Button , IDisposable),但除此之外,我不知道该怎么办。你能帮我看看代码吗?我在这里只是一个菜鸟:'(另外,你说过如果我构建一个用户控件而不是自定义控件会更容易,这不是一回事吗? -
自定义控件和用户控件不是一回事。您现在有一个自定义控件,一个派生自现有 .Net 本机控件(按钮)的类。 UserControl 有它自己的设计器,就像一个窗体。您可以在其上放置控件,定义它们的布局、行为、添加事件处理程序。好吧,就像一个表单设计器 :) 例如,您可以更轻松地处理 UserControl 的
Enter和Leave事件。试试看:在您的解决方案资源管理器中,右键单击Project => Add... => User Control。我会看看我是否能找到时间发布一个例子。
标签: c# winforms button controls