Есть ли альтернатива использованию Paint Event для изменения Disabled ForeColor кнопки? - PullRequest
0 голосов
/ 06 мая 2020

Я столкнулся с проблемой кнопок в моем текущем проекте, «не выглядящих достаточно отключенными», на основании некоторых отзывов. Некоторые люди не сразу узнали, что некоторые кнопки отключены. Это в первую очередь потому, что цвет шрифта не изменился на достаточно светлый, чтобы его можно было заметить (я не уверен, как цвет автоматически определяется при отключении, но это не относится к делу). Вот как это выглядело:

enter image description here

Вот что привело меня к созданию расширения модуля, которое позволяет мне .Enable или .Disable любую кнопку легко и управляйте .ForeColor. В итоге это выглядело так:

enter image description here

Я получил представление о том, как обрабатывать подобные изменения форматирования из этого сообщения , но были некоторые комментарии (и я убедился на собственном опыте), что лучше не связываться с событием Paint (я расскажу об этом подробнее и проиллюстрирую ниже.)

ER GO МОЙ ВОПРОС:

Есть ли разумная альтернатива использованию события Paint для управления форматированием кнопки?

Вот несколько ориентиры:

  1. Я не хочу создавать целый настраиваемый элемент управления, просто чтобы внести небольшие изменения цвета - мое расширение намного проще и может быть применено к любой кнопке.
  2. Я ищу что-то более простое, чем использование события рисования, и это с меньшей вероятностью вызовет проблемы в других реализациях.
  3. Одна основная причина, по которой я хочу избежать чего-либо, связанного с событием Paint, заключается в том, что у вас для "резервного копирования" текста в другую переменную, чтобы вы могли очистите .Text, чтобы он не отображался на кнопке в дополнение к вашей пользовательской визуализации, но после визуализации вы не можете переназначить .Text в событии Paint, потому что это снова вызывает событие, вызывая бесконечное l oop , что означает, что с этого момента вы должны оставить .Text кнопки пустым.

ЗДЕСЬ КОД:

(с излишними комментариями в Paint, чтобы объяснить причину того, как я с этим справляюсь)

Module Extensions
    <System.Runtime.CompilerServices.Extension()>
    Public Sub Enable(ByVal btn As Button)
        If btn.Tag = Nothing Then ' << This ensures we only add the handler once.
            AddHandler btn.EnabledChanged, AddressOf btn_EnabledChanged
            AddHandler btn.Paint, AddressOf btn_Paint
        End If
        btn.Enabled = True
        btn.ForeColor = Color.MidnightBlue
    End Sub

    <System.Runtime.CompilerServices.Extension()>
    Public Sub Disable(ByVal btn As Button)
        If btn.Tag = Nothing Then ' << This ensures we only add the handler once.
            AddHandler btn.EnabledChanged, AddressOf btn_EnabledChanged
            AddHandler btn.Paint, AddressOf btn_Paint
        End If
        btn.Enabled = False
    End Sub

    Private Sub btn_EnabledChanged(sender As Object, e As System.EventArgs)
        Dim btn As Button = DirectCast(sender, Button)
        If sender.enabled = False Then
            btn.ForeColor = Color.DarkGray
        Else
            btn.ForeColor = Color.MidnightBlue
        End If
    End Sub

    Private Sub btn_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs)
        'Dim TextForBtn As String = ""  ' << we don't use a variable because that would only be useful if we could reassign to the .Text property, but that just raises the Paint Event again causing a infinite loop.
        Dim btn As Button = DirectCast(sender, Button)
        If btn.Text > " " Then
            btn.Tag = btn.Text ' << this allows us to redraw the text, the one issue however is the .Text property is empty from here on out.
            'TextForBtn = btn.Text ' << this is part of the failed idea of using a variable and reassigning to the .Text property.
        End If
        btn.Text = String.Empty ' << make sure Text is not written on button as well as rendered below
        Dim flags As TextFormatFlags = TextFormatFlags.HorizontalCenter Or TextFormatFlags.VerticalCenter Or TextFormatFlags.WordBreak  'center the text
        TextRenderer.DrawText(e.Graphics, btn.Tag.ToString, btn.Font, e.ClipRectangle, btn.ForeColor, flags) ' << TextForBtn was replaced with btn.Tag.ToString in the second parameter
        'btn.Text = TextForBtn ' << this is what caused an infinite loop necessitating the use of the .Tag property.
    End Sub
End Module

ЗАКЛЮЧИТЕЛЬНОЕ ПРИМЕЧАНИЕ:

Я открыт для любых советов по оптимизации code Я должен решить свои проблемы, но я совершенно убежден, что единственный способ решить определенные проблемы - это сделать тот же трюк, не касаясь Paint.

...