Как программировать эффект «Flash» при обновлении текстовых ящиков в форме Windows с C #?

StackOverflow https://stackoverflow.com/questions/4147169

Вопрос

То, что у меня есть форма Windows, в C #, с 7 текстовыми полями. Каждое текстовое поле обновляет 2 или 3 других, когда его значение изменено и принято. То, что я хочу сделать, это как-то снимать эти текстовые поля, которые необходимо обновлять и сделать их «вспышка» со светлым цветом или что-то в этом роде. Цель состоит в том, чтобы показать пользователю, что обновляется с добавленным пластом.

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

jquery ui имеет эффект «выделения», который показывает то, что я хочу достичь (хотя я хочу, чтобы мои были немного медленнее). Просто иди сюда к JQuery UI Effects Demo Page Page, Выберите «Выделите» из раскрывающейся коробки в окне и нажмите «Run Effect».

Редактировать
Мне пришлось пойти с моим собственным решением, основанным на моих ограничениях времени и ресурсов, но текстовые поля не поддерживают прозрачные цвета, как упомянутые Ханс Pastant. Итак, я использовал таймер самозадачи, который увеличивает значения R, G и B, пока элемент управления не будет полностью белым (R = 255, G = 255, B = 255);

Редактировать 2.
Замотано перекодируя событие Flash в качестве метода расширения с использованием вариации решения Джорджа Джонстона после обновления до .NET 4.0. Это гораздо более чистое решение, я чувствую, а метод расширения делает его автоматически доступным для всех using Это.

Это было полезно?

Решение

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

private void Form1_Load(object sender, EventArgs e)
{
    // textBox1 is the control on your form.
    // 1000 is the total interval between flashes
    // Color.LightBlue is the flash color
    // 10 is the number of flashes before the thread quits.
    Flash(textBox1, 1000,Color.LightBlue,10);
    Flash(textBox2, 1500,Color.Green,10);
    Flash(textBox3, 100,Color.Red,10);
    Flash(textBox4, 500,Color.Brown,10);
    Flash(textBox5, 200,Color.Pink,10);
}

public void Flash(TextBox textBox, int interval, Color color, int flashes)
{
    new Thread(() => FlashInternal(textBox, interval, color, flashes)).Start();
}

private delegate void UpdateTextboxDelegate(TextBox textBox, Color originalColor);
public void UpdateTextbox(TextBox textBox, Color color)
{
    if (textBox.InvokeRequired)
    {
        this.Invoke(new UpdateTextboxDelegate(UpdateTextbox), new object[] { textBox, color });
    }
    textBox.BackColor = color;
}

private void FlashInternal(TextBox textBox, int interval, Color flashColor, int flashes)
{
    Color original = textBox.BackColor;
    for (int i = 0; i < flashes; i++)
    {

        UpdateTextbox(textBox, flashColor);
        Thread.Sleep(interval/2);
        UpdateTextbox(textBox, original);
        Thread.Sleep(interval/2);
    }
}

Это позволяет избежать необходимости вводить контроль за таймером в вашей форме.

Другие советы

WPF кажется бы идеальным для этого. Вы можете построить его в WPF и использовать его в WinForms в качестве размера. Добавить новый проект WPF Control, и это в XAML:

<UserControl x:Class="WpfControlLibrary1.UserControl1"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         d:DesignHeight="20" d:DesignWidth="300">
<TextBox>
    <TextBox.Triggers>
        <EventTrigger RoutedEvent="TextBox.TextChanged">
            <BeginStoryboard>
                <Storyboard AutoReverse="False" BeginTime="0" >
                    <DoubleAnimation Storyboard.TargetName="Foo"
                                 Storyboard.TargetProperty="Opacity"
                                 From="0" To="1" Duration="0:0:1"/>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </TextBox.Triggers>
    <TextBox.Background>
        <SolidColorBrush Opacity="1" x:Name="Foo" Color="LightGray" />
    </TextBox.Background>
</TextBox>
</UserControl>

(Это может сделать небольшую работу, но это начало). Там у вас есть - модный текстовый ящик :)

Создайте решение, и в Toolbox появится новый элемент - просто перетащите в форму, WPF будет размещен внутри элемента ElementHost. Красота этого состоит в том, что вы можете сделать гораздо больше в визуальных стилях в WPF, однако, размещены WPF, который добавляет определенный вес вашего решения ...

Вывести свой собственный класс от TextBox. Отказ Дать это Flash() Метод, который начинает мигающий. Просто измените BackColor к пастельному цвету. Не используйте альфа, это не работает на TextBox.

Вы должны иметь все экземпляры этого класса, поделитесь общим таймером, поэтому они будут мигать одновременно. Сделайте таймер статическим и ссылочным подсчетом количества экземпляров, которые у вас есть. Сожмите в конструктор, вниз в Dispose(bool) переопределить.

Если вы устанавливаете свои способы использования WinForms, то с моими ограниченными знаниями я могу предложить, чтобы получить третий контроль контроля. Несколько к названию - Telerik и Componentone. Если вы хотите что-то подобное WINFORMS, вы, вероятно, можете использовать WPF и разработать пользовательские анимации в XAML (что, я думаю, похоже на Silverlight XAML в создании состояний пользовательского интерфейса и анимации). Кроме того, у меня есть опыт, чтобы предоставить любую помощь.

В зависимости от вашего приложения, один яркий способ сделать это, изменяя гамма изображения вашего TextBox. Это, конечно, зависит от того, сколько времени вы хотите вложить в это, но это, безусловно, выполнимо. Я видел несколько учебных пособий о том, как настроить гамма изображения и получить изображение вашего управления тривиальным.

Тем не менее, я также верю, что это нетривиально, чтобы установить Backcolor из текстового поля для прозрачного. Из вашей формулировки я могу только догадываться, что вы хотите исчезнуть цвет от базового контроля на заднем фоном к Backcolor TextBox, в этом случае проблема снова тривиальна. Но если у вас есть фоновое изображение, вы, возможно, должны пересмотреть. Тем не менее, это все еще возможно, и я могу выкопать ссылку для вас, о том, как это сделать, если это то, что вы пытаетесь сделать.

Quick'n Easy Solution будет для анимирования цвета текста и задний цвет от белого до вашего текущего цвета переднего плана.

Если вы не заинтересованы в использовании резьбы, создание ответа Джорджа Джонстона здесь, моя реализация выглядит следующим образом:

private bool CurrentlyFlashing = false;
private void FlashInternal(TextBox textBox, int interval, Color flashColor, int flashes)
{
    if (CurrentlyFlashing) return;

    CurrentlyFlashing = true;
    Color original = textBox.BackColor;
    for (int i = 0; i < flashes; i++)
    {
        UpdateTextbox(textBox, flashColor);
        Application.DoEvents();
        Thread.Sleep(interval / 2);
        UpdateTextbox(textBox, original);
        Application.DoEvents();
        Thread.Sleep(interval / 2);
    }
    CurrentlyFlashing = false;
}
private delegate void UpdateTextboxDelegate(TextBox textBox, Color originalColor);
public void UpdateTextbox(TextBox textBox, Color color)
{
    if (textBox.InvokeRequired)
    {
        this.Invoke(new UpdateTextboxDelegate(UpdateTextbox), new object[] { textBox, color });
    }
    textBox.BackColor = color;
}

Довольно старый вопрос, но я подумал, что я бы обновился с более современным ответом, поскольку Async / await не существовал в 2010 году, когда ответил последние ответы

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

Поскольку он использует Async / ждут, безопасно делать на главной ните без необходимости делегата или InvokeRequired чек об оплате. Даже если вы устанавливаете продолжительность исчезновения на что-то длинное, вы все равно сможете взаимодействовать с приложением, пока запущена затухание.

    private bool CurrentlyFlashing = false;
    private async void FlashControl(Control control)
    {
        Color flashColor = Color.Yellow;

        float duration = 500; // milliseconds
        int steps = 10;
        float interval = duration / steps;

        if (CurrentlyFlashing) return;
        CurrentlyFlashing = true;
        Color original = control.BackColor;

        float interpolant = 0.0f;
        while (interpolant < 1.0f)
        {
            Color c = InterpolateColour(flashColor, original, interpolant);
            control.BackColor = c;
            await Task.Delay((int) interval);
            interpolant += (1.0f / steps);
        }

        control.BackColor = original;

        CurrentlyFlashing = false;
    }

    public static Color InterpolateColour(Color c1, Color c2, float alpha)
    {
        float oneMinusAlpha = 1.0f - alpha;
        float a = oneMinusAlpha * (float)c1.A + alpha * (float)c2.A;
        float r = oneMinusAlpha * (float)c1.R + alpha * (float)c2.R;
        float g = oneMinusAlpha * (float)c1.G + alpha * (float)c2.G;
        float b = oneMinusAlpha * (float)c1.B + alpha * (float)c2.B;
        return Color.FromArgb((int)a, (int)r, (int)g, (int)b);
    }

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top