Почему кнопка мерцает?

#c# #winforms #button #controls

#c# #winforms #кнопка #элементы управления

Вопрос:

У меня есть 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, даже если я ее оставил!

Мы будем благодарны за любую помощь!

Комментарии:

1. Когда вы наводите курсор на одну из маленьких кнопок, вы запускаете MouseLeave событие контейнера ( главной кнопки), которое присваивает значение null изображениям дочерней кнопки. Меньшая кнопка MouseEnter сбрасывает изображения и изменяет задний цвет контейнера (таким образом, мерцание ). Когда мышь покидает область меньших кнопок, MouseLeave событие контейнера не запускается, когда курсор не входит в его клиентскую область, поэтому более темный цвет сохраняется. Было бы проще, если бы вы создали UserControl вместо пользовательского элемента управления.

2. У вас там серьезная проблема с графическими объектами. Resources Объект — это фабрика: каждый раз, когда вы вызываете Resources.[SomeImage] , вы создаете новое растровое изображение и никогда не удаляете его, устанавливая вместо null этого свойство image элементов управления (которое ничего не делает для освобождения ранее выделенных ресурсов). Вы должны назначить каждое растровое изображение объекту Bitmap и использовать этот объект для присвоения свойства изображения вашим элементам управления, а затем удалить эти растровые изображения при удалении основного элемента управления (реализации IDisposable ).

3. И вы не должны постоянно настраивать фоновое изображение пользовательской кнопки, но вы должны изменить видимость кнопки.

4. @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 ), но кроме этого, я не знаю, что делать. Не могли бы вы, пожалуйста, помочь мне с кодом? Я здесь просто новичок:'(Кроме того, вы сказали, что было бы проще, если бы я создал UserControl вместо пользовательского элемента управления, разве это не одно и то же?

5. Пользовательский элемент управления и пользовательский элемент управления — это не одно и то же. Теперь у вас есть пользовательский элемент управления, класс, производный от существующего . Чистый собственный элемент управления (кнопка). Пользовательский элемент управления имеет свой собственный конструктор, как форма. Вы можете поместить на нее элементы управления, определить их расположение, поведение, добавить обработчики событий. Хорошо, как дизайнер форм 🙂 Например, вы можете легче обрабатывать Enter Leave события и пользовательского элемента управления. Попробуйте: в обозревателе решений щелкните правой кнопкой мыши Project => Add... => User Control . Я посмотрю, смогу ли я найти время для публикации примера.

Ответ №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;
        }
    }
}
 

Комментарии:

1. Вау, спасибо, это действительно делает свою работу! Это внутреннее количество — это то, о чем я бы никогда не подумал, это чистая гениальность! Я так благодарен за вашу помощь! Я запомню этот метод в следующий раз, если возникнет какая-то подобная проблема! Еще раз спасибо, я действительно благодарен! 😁🙌