【问题标题】:Why does the button flicker?为什么按钮会闪烁?
【发布时间】: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 的 EnterLeave 事件。试试看:在您的解决方案资源管理器中,右键单击 Project =&gt; Add... =&gt; User Control。我会看看我是否能找到时间发布一个例子。

标签: c# winforms button controls


【解决方案1】:

主要问题是“OnMouseLeave”不仅在鼠标离开整个控件时被调用,而且在它进入两个小按钮中的任何一个时都会被调用,因为它们与它们的父级重叠。您还应该使用“MouseEnter”事件而不是“MouseHover”。

您会在下面找到一个可以解决问题的简化版本。 “内部”字段包含有关整个控件的“进入”数减去“离开”数。如果它的值大于零,则鼠标在控件内部,包括两个小按钮。

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;
        }
    }
}

【讨论】:

  • 哇,谢谢,它真的很管用!里面的计数是我从来没有想过的,它是纯粹的天才!我非常感谢你的帮助!下次如果出现这种问题我会记住这个方法的!再次感谢您,我真的很感激! ??
猜你喜欢
  • 1970-01-01
  • 2013-05-26
  • 1970-01-01
  • 2022-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多