Comment programmer un effet « flash » lors de la mise à jour des zones de texte dans une fenêtre formulaire avec C #?

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

Question

Ce que j'est une forme Windows en C #, avec 7 zones de texte. Chaque zone de texte met à jour 2 ou 3 autres lorsque sa valeur est modifiée et acceptée. Ce que je veux faire est de prendre en quelque sorte ces zones de texte qui doivent être mis à jour et de les rendre « flash » avec une couleur de rétro-éclairage ou quelque chose. Le but est de montrer à l'utilisateur ce qui est mis à jour avec un peu de flair ajouté.

Je ne sais pas s'il y a un moyen facile de faire ceci et cela est la raison pour laquelle je demande ici. Je peux utiliser une minuterie, une boucle while, et une couleur arrière avec une diminution de canal alpha sur la couleur arrière de contrôle de zone de texte, je pense, mais je veux voir s'il y a une meilleure façon.

jQuery UI a un effet « highlight » qui montre ce que je veux accomplir (bien que je veux moi d'être un peu plus lent). Il suffit d'aller ici à la effets jQuery UI Page de démonstration , sélectionnez « highlight » dans la zone de liste déroulante dans la fenêtre, et cliquez sur "Exécuter Effect".

Modifier
Je devais aller avec ma propre solution basée sur mes contraintes de temps et de ressources, mais les zones de texte ne supporte pas les couleurs transparentes comme mentionné par Hans Passant. Donc, j'utilisé un retardateur d'arrêt qui augmente le R, G et B des valeurs jusqu'à ce que le contrôle est complètement blanc (R = 255, V = 255, B = 255);

Modifier 2
Liquidée recoder l'événement flash comme une méthode d'extension en utilisant une variante de la solution de George Johnston après avoir mis à jour à .NET 4.0. Ceci est une solution beaucoup plus propre, je me sens, et la méthode d'extension rend automatiquement accessible à tous using il.

Était-ce utile?

La solution

Vous pourriez essaimer un fil séparé par clignotement textbox pour ne pas bloquer votre formulaire d'être utilisé pendant le clignotement de votre zone de texte (s). Assurez-vous d'appeler votre formulaire en rotation du fil nécessitera le filetage. Solution complète ci-dessous.

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

On évite ainsi d'avoir à mettre soutenir les commandes de minuterie sur votre formulaire.

Autres conseils

Le WPF semble parfait pour cela. Vous pouvez le construire en WPF et l'utiliser dans WinForms comme HostedElement. Ajouter un nouveau projet WPF Control utilisateur, et ceci 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>

(il pourrait faire un peu de travail, mais il est un début). Là, vous avez - une zone de texte de fantaisie:)

Générez la solution, et un nouvel élément apparaît dans Toolbox - il suffit de glisser-déposer à votre formulaire, le WPF sera hébergé à l'intérieur élément ElementHost. La beauté de ce que vous pouvez faire beaucoup plus encore dans des styles visuels dans WPF, cependant, il est hébergé WPF qui ajoute du poids à votre certaine solution ...

Derive votre propre classe de TextBox. Donnez-lui une méthode de Flash() qui commence le clignotement. Il suffit de changer le BackColor à une couleur pastel. Ne pas utiliser alpha, qui ne fonctionne pas sur un TextBox.

Vous devriez avoir toutes les instances de cette classe partagent une commune de minuterie afin qu'ils clignotent en même temps. Faire le compte de référence statique minuterie et le nombre d'instances que vous avez. Additionnez dans le constructeur, dans la override Dispose(bool).

Si vous définissez vos moyens à utiliser WinForms, puis avec mes connaissances limitées, je conseille de prendre les commandes de tiers pour aider. Quelques noms sont à Telerik et ComponentOne. Si vous voulez WinForms quelque chose comme, vous pouvez probablement utiliser WPF, et de développer des animations personnalisées en XAML (qui je pense sont semblables à Silverlight XAML dans la création d'états de l'interface utilisateur et animations). Autre que ces derniers, je suis hors de l'expérience pour fournir toute aide.

En fonction de votre application, d'une façon flashy de le faire est en changeant le gamma d'une image de votre zone de texte. Bien sûr, cela dépend de combien de temps vous voulez mettre dans cela, mais il est certainement faisable. Je l'ai vu plusieurs tutoriels sur la façon de régler le gamma d'une image et d'obtenir une image de votre contrôle est trivial.

Cela dit, je crois aussi qu'il est difficile à configurer le backcolor de la zone de texte à la transparence. À partir de votre texte, je ne peux que deviner que vous voulez effacer la couleur de la backcolor de contrôle sous-jacent à la zone de texte » backcolor, dans ce cas, le problème est à nouveau trivial. Mais si vous avez à savoir une image d'arrière-plan, vous devriez peut-être reconsidérer. Néanmoins, il est toujours possible et je peux creuser un lien pour vous sur la façon de le faire si c'est ce que vous essayez d'accomplir.

La solution facile Quick'n serait d'animer la couleur du texte et la couleur arrière du blanc à votre couleur de premier plan en cours.

Si vous n'êtes pas intéressé à utiliser le filetage, la construction sur la réponse de George Johnston ici ma mise en œuvre est la suivante:

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

question assez vieux, mais je pensais que je voudrais mettre à jour une réponse plus moderne, puisque async / Attendent n'existaient en 2010, lorsque les dernières réponses ont répondu

Je l'ai mise à jour aussi utilise un seul flash bien fondu plutôt qu'une induisant saisie-arrêt clignote et changé et la frappe de sorte qu'il ne se limite pas à utiliser sur zones de texte.

Comme il utilise async / Attendent, il est sûr de le faire sur le thread principal sans avoir besoin du délégué ou du contrôle de InvokeRequired. Même si vous définissez la durée du fondu à quelque chose de long, vous serez toujours en mesure d'interagir avec l'application tandis que la boucle de fondu est en cours d'exécution.

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

I codé en dur la couleur et le calendrier plutôt que de les exposer en tant que paramètres de fonction comme d'autres l'ont fait answerers, puisque je veux qu'ils soient généralement les mêmes dans ma demande si je réutilise cela.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top