How do I program a “flash” effect when updating te

2019-06-18 05:25发布

What I have is a Windows form, in C#, with 7 text boxes. Each text box updates 2 or 3 others when its value is changed and accepted. What I want to do is somehow take those text boxes that need to be updated and make them "flash" with a light back color or something. The purpose is to show the user what is being updated with an added bit of flair.

I'm not sure if there is an easy way to do this and that is why I'm asking here. I can use a timer, a while loop, and a back color with a decreasing alpha channel on the text box control back color, I think, but I want to see if there is a better way.

jQuery UI has a "Highlight" effect that shows what I want to accomplish (although I want mine to be a bit slower). Just go here to the jQuery UI Effects Demo page, select "highlight" from the drop-down box in the window, and click "Run Effect".

Edit
I had to go with my own solution based on my time and resource constraints, but text boxes do not support transparent colors as mentioned by Hans Passant. So, I used a self-stopping timer that increases the R, G, and B values until the control is completely white (R=255, G=255, B=255);

Edit 2
Wound up recoding the flash event as an extension method using a variation of George Johnston's solution after we updated to .NET 4.0. This is a much cleaner solution, I feel, and the extension method makes it automatically available to anyone using it.

6条回答
劳资没心,怎么记你
2楼-- · 2019-06-18 05:39

If you are set on your ways in using WinForms, then with my limited knowledge, I can suggest getting third party controls to help out. A few to name are Telerik and ComponentOne. If you want something WinForms like, you can probably utilize WPF, and develop custom animations in XAML (which I think are similar to Silverlight XAML in creating UI states and animations). Other than these, I'm out of experience to provide any help.

查看更多
闹够了就滚
3楼-- · 2019-06-18 05:39

Depending on your app, one flashy way of doing this is by changing the gamma of an image of your textbox. This of course depends on how much time you want to put into this, but it's certainly doable. I've seen several tutorials on how to adjust the gamma of an image and getting an image of your control is trivial.

That said, I also believe it's nontrivial to set the backcolor of the textbox to transparent. From your wording I can only guess you want to fade the color from the underlying control's backcolor to the textbox' backcolor, in which case the problem is trivial again. But if you have i.e. a background image, you should perhaps reconsider. Nonetheless, it's still possible and I can dig up a link for you on how to do this if that's what you're trying to accomplish.

The quick'n easy solution would be to animate the text color and the back color from white to your current foreground color.

查看更多
乱世女痞
4楼-- · 2019-06-18 05:45

Derive your own class from TextBox. Give it a Flash() method that starts the flashing. Just change the BackColor to a pastel color. Don't use alpha, that doesn't work on a TextBox.

You ought to have all instances of this class share a common Timer so they will flash at the same time. Make the timer static and reference-count the number of instances you have. Add up in the constructor, down in the Dispose(bool) override.

查看更多
SAY GOODBYE
5楼-- · 2019-06-18 05:45

If you're not interested in using threading, building on George Johnston's answer here my implementation is as follows:

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;
}
查看更多
兄弟一词,经得起流年.
6楼-- · 2019-06-18 05:46

You could spin off a seperate thread per flashing textbox as to not block your form from being used during the flashing of your textbox(s). Be sure to invoke your form as spinning of the thread will require cross threading. Full solution below.

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

This avoids having to put supporting timer controls on your form.

查看更多
三岁会撩人
7楼-- · 2019-06-18 06:00

The WPF would seem perfect for this. You can build it in WPF and use it in WinForms as a HostedElement. Add new project WPF User Control, and this in 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>

(it could do a little work, but it's a start). There you have it - a fancy textbox :)

Build the solution, and a new item will appear in Toolbox - just drag & drop to your Form, the WPF will be hosted inside ElementHost element. The beauty of it is that you can do much much more in visual styles in WPF, however, it's hosted WPF which adds certain weight to your solution...

查看更多
登录 后发表回答