Как мне запрограммировать эффект «flash» при обновлении текстовых полей в форме окна с помощью C #? - PullRequest
6 голосов
/ 10 ноября 2010

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

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

jQuery UI имеет эффект «Highlight», который показывает, чего я хочу достичь (хотя я хочу, чтобы мой был немного медленнее). Просто перейдите на демонстрационную страницу jQuery UI Effects , выберите «выделить» в раскрывающемся окне и нажмите «Запустить эффект».

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

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

Ответы [ 6 ]

11 голосов
/ 10 ноября 2010

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

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

Это избавляет от необходимости помещать в форму вспомогательные элементы управления таймером.

3 голосов
/ 10 ноября 2010

WPF кажется идеальным для этого.Вы можете построить его в WPF и использовать в WinForms в качестве HostedElement.Добавьте новый проект WPF User 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, что добавляет вашему решению определенный вес ...

2 голосов
/ 10 ноября 2010

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

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

0 голосов
/ 19 сентября 2013

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

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;
}
0 голосов
/ 10 ноября 2010

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

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

Быстрое и простое решение - анимировать цвет текста изадний цвет от белого до текущего цвета переднего плана.

0 голосов
/ 10 ноября 2010

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

...