¿Cómo se programa un efecto “flash” en la actualización de los cuadros de texto en una ventana de formulario con C #?

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

Pregunta

Lo que tengo es una forma de Windows, en C #, con 7 cuadros de texto. Cada cuadro de texto actualiza 2 o 3 otros cuando se cambia su valor y aceptado. Lo que quiero hacer es de alguna manera tomar esos cuadros de texto que necesitan ser actualizados y hacerlos "flash" con un color de la luz de fondo o algo así. El propósito es mostrar al usuario lo que está siendo actualizado con un bit adicional de estilo.

No estoy seguro de si hay una manera fácil de hacer esto y es por eso que estoy pidiendo aquí. Puedo utilizar un temporizador, un bucle while, y un color de vuelta con una disminución de canal alfa en la parte posterior del color de control de cuadro de texto, creo, pero quiero ver si hay una manera mejor.

jQuery UI tiene un efecto de "Lo mejor" que muestra lo que quiere lograr (aunque quiero que la mía sea un poco más lento). Sólo tienes que ir aquí para el jQuery UI Efectos página de prueba , seleccione "punto culminante" de la caja desplegable en la ventana y haga clic en "Ejecutar Efecto".

Editar
Tenía que ir con mi propia solución basada en mis tiempo y recursos, pero los cuadros de texto no son compatibles con colores transparentes como se ha mencionado por Hans Passant. Por lo tanto, he usado un temporizador de parada que los aumentos de la R, G, y los valores de B hasta que el control es completamente blanco (R = 255, G = 255, B = 255);

Editar 2
Liquidación recodificar el evento flash como un método de extensión usando una variación de la solución de George Johnston después de que actualiza para .NET 4.0. Esta es una solución más limpia mucho, me siento, y el método de extensión hace que sea automáticamente disponible para cualquier persona que using.

¿Fue útil?

Solución

Se podría escindir un hilo separado por cada cuadro de texto a parpadear para no bloquear su forma de ser utilizado durante el parpadeo de su campo respectivo (s). Asegúrese de invocar su formulario como el hilado del hilo requerirá la rosca. solución completa a continuación.

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

Esto evita tener que poner el apoyo a los controles de temporizador en el formulario.

Otros consejos

El FPM parecería perfecto para esto. Se puede construir en WPF y utilizarlo en Windows Forms como HostedElement. Añadir nuevo proyecto WPF Control de Usuario, y esto en 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>

(que podría hacer un poco de trabajo, pero es un comienzo). Ahí lo tienes - un cuadro de texto de fantasía:)

Construir la solución, y un nuevo elemento aparecerá en la caja de herramientas - simplemente arrastrar y soltar a su forma, el WPF será conducido dentro elemento ElementHost. La belleza de esto es que se puede hacer mucho más en los estilos visuales en WPF, sin embargo, se aloja WPF que añade cierto peso a la solución ...

Derivar su propia clase de TextBox. Darle un método Flash() que se inicia el parpadeo. Sólo cambia el BackColor a un color pastel. No utilice alfa, que no funciona en un TextBox.

Usted debe tener todas las instancias de esta clase comparten un temporizador común para que parpadean al mismo tiempo. Hacer que el temporizador estático y referencia-contar el número de casos que tiene. Sume en el constructor, en la anulación Dispose(bool).

Si se fijan en sus formas en el uso de Windows Forms, luego con mi limitado conocimiento, puedo sugerir conseguir controles de terceros para ayudar. Algunos por mencionar son Telerik y ComponentOne. Si quieres algo WinForms gusta, es probable que pueda utilizar WPF, y desarrollar animaciones personalizadas en XAML (que creo que son similares a Silverlight XAML en la creación de estados de interfaz de usuario y animaciones). Aparte de estas, estoy fuera de la experiencia para proporcionar cualquier ayuda.

Dependiendo de su aplicación, de una manera llamativa de hacer esto es mediante el cambio de gamma de una imagen de su campo respectivo. Por supuesto, esto depende de la cantidad de tiempo que desea poner en esto, pero es ciertamente factible. He visto varios tutoriales sobre cómo ajustar la gamma de una imagen y obtener una imagen de su control es trivial.

Dicho esto, también creo que es trivial para establecer el color de fondo del cuadro de texto a transparente. Desde su redacción sólo puedo adivinar desea hacer desaparecer el color del color de fondo del control subyacente al color de fondo de texto', en cuyo caso el problema es trivial de nuevo. Pero si la imagen de fondo es decir, una que tenga, tal vez debería reconsiderar. Sin embargo, todavía es posible y que puede cavar un enlace para usted acerca de cómo hacer esto si eso es lo que estamos tratando de lograr.

La solución más sencilla sería Quick'n para animar el color del texto y el color de fondo de blanco a su color de primer plano actual.

Si usted no está interesado en el uso de roscado, basándose en la respuesta de George Johnston aquí mi aplicación es el siguiente:

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

Bastante vieja pregunta, pero pensé que iba a actualizar con una respuesta más moderna, ya que asíncrono / Await no existía en 2010, cuando respondieron a las últimas respuestas

También actualizándolo a usos un solo flash muy bien la decoloración en lugar de una de inducir convulsiones encendido-apagado parpadeo, y la tipificación y ha cambiado para que no se limita a ser utilizado en cuadros de texto.

Dado que se usa asíncrono / esperan, es seguro hacerlo en el hilo principal sin necesidad del delegado o el cheque InvokeRequired. Incluso si se establece la duración del fundido a algo largo, usted todavía será capaz de interactuar con la aplicación, mientras que el bucle de fundido está en marcha.

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

Me modificable el color y el momento en lugar de exponerlos como parámetros de función al igual que otros que responden, ya que en general, quiero que sean de la misma a través de mi solicitud si la reutilización de estas.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top