Đây có thể là nhiều hơn bạn cần, đây là mã cho lớp tôi sử dụng:
public class ControlColorAnimator
{
private const int INTERVAL = 100;
private readonly decimal _alphaIncrement;
private readonly decimal _blueIncrement;
private readonly Color _endColor;
private readonly decimal _greenIncrement;
private readonly int _iterations;
private readonly decimal _redIncrement;
private readonly Color _startColor;
private decimal _currentAlpha;
private decimal _currentBlueValue;
private decimal _currentGreenValue;
private decimal _currentRedValue;
private Timer _timer;
public ControlColorAnimator(TimeSpan duration, Color startColor, Color endColor)
{
_startColor = startColor;
_endColor = endColor;
resetColor();
_iterations = duration.Milliseconds/INTERVAL;
_alphaIncrement = ((decimal) startColor.A - endColor.A)/_iterations;
_redIncrement = ((decimal) startColor.R - endColor.R)/_iterations;
_greenIncrement = ((decimal) startColor.G - endColor.G)/_iterations;
_blueIncrement = ((decimal) startColor.B - endColor.B)/_iterations;
}
public Color CurrentColor
{
get
{
int alpha = Convert.ToInt32(_currentAlpha);
int red = Convert.ToInt32(_currentRedValue);
int green = Convert.ToInt32(_currentGreenValue);
int blue = Convert.ToInt32(_currentBlueValue);
return Color.FromArgb(alpha, red, green, blue);
}
}
public event EventHandler<DataEventArgs<Color>> ColorChanged;
public void Go()
{
disposeOfTheTimer();
OnColorChanged(_startColor);
resetColor();
int currentIteration = 0;
_timer = new Timer(delegate
{
if (currentIteration++ >= _iterations)
{
Stop();
return;
}
_currentAlpha -= _alphaIncrement;
_currentRedValue -= _redIncrement;
_currentGreenValue -= _greenIncrement;
_currentBlueValue -= _blueIncrement;
OnColorChanged(CurrentColor);
}, null, TimeSpan.FromMilliseconds(INTERVAL), TimeSpan.FromMilliseconds(INTERVAL));
}
public void Stop()
{
disposeOfTheTimer();
OnColorChanged(_endColor);
}
protected virtual void OnColorChanged(Color color)
{
if (ColorChanged == null) return;
ColorChanged(this, color);
}
private void disposeOfTheTimer()
{
Timer timer = _timer;
_timer = null;
if (timer != null) timer.Dispose();
}
private void resetColor()
{
_currentAlpha = _startColor.A;
_currentRedValue = _startColor.R;
_currentGreenValue = _startColor.G;
_currentBlueValue = _startColor.B;
}
}
này sử dụng DataEventArgs<T>
(hình dưới đây)
/// <summary>
/// Generic implementation of <see cref="EventArgs"/> that allows for a data element to be passed.
/// </summary>
/// <typeparam name="T">The type of data to contain.</typeparam>
[DebuggerDisplay("{Data}")]
public class DataEventArgs<T> : EventArgs
{
private T _data;
/// <summary>
/// Constructs a <see cref="DataEventArgs{T}"/>.
/// </summary>
/// <param name="data">The data to contain in the <see cref="DataEventArgs{T}"/></param>
[DebuggerHidden]
public DataEventArgs(T data)
{
_data = data;
}
/// <summary>
/// Gets the data for this <see cref="DataEventArgs{T}"/>.
/// </summary>
public virtual T Data
{
[DebuggerHidden]
get { return _data; }
[DebuggerHidden]
protected set { _data = value; }
}
[DebuggerHidden]
public static implicit operator DataEventArgs<T>(T data)
{
return new DataEventArgs<T>(data);
}
[DebuggerHidden]
public static implicit operator T(DataEventArgs<T> e)
{
return e.Data;
}
}
sử dụng trong hình thức của bạn như thế này:
private ControlColorAnimator _animator;
private void runColorLoop()
{
endCurrentAnimation();
startNewAnimation();
}
private void endCurrentAnimation()
{
ControlColorAnimator animator = _animator;
_animator = null;
if (animator != null)
{
animator.ColorChanged -= _animator_ColorChanged;
animator.Stop();
}
}
private void startNewAnimation()
{
_animator = new ControlColorAnimator(TimeSpan.FromSeconds(.6), Color.Yellow, BackColor);
_animator.ColorChanged += _animator_ColorChanged;
_animator.Go();
}
private void _animator_ColorChanged(object sender, DataEventArgs<Color> e)
{
invokeOnFormThread(delegate { setColor(e); });
}
private void setColor(Color color)
{
// code to set color of the controls goes here
}
private void invokeOnFormThread(MethodInvoker method)
{
if (IsHandleCreated)
Invoke(method);
else
method();
}
Nguồn
2009-04-02 18:18:24
Điều này rất thông minh, cảm ơn :) Tôi đã sửa đổi nó (để vượt qua một tham số Ẩn để khi hoạt ảnh kết thúc, kiểm soát được ẩn) và thêm nó vào baseclass của tôi, bây giờ tất cả các hình thức kế thừa của tôi có khả năng ghi đè setColor và sử dụng nó . Tôi đã không tìm thấy một cách thanh lịch để có thể vượt qua một điều khiển nơi các hình ảnh động sẽ xảy ra, thay vì "hardcoding" nó trong setColor. Bất kỳ ý tưởng? –
Đã không thử nó, nhưng có lẽ một phương pháp mở rộng trên điều khiển ... sau đó bạn có thể gọi nó như thế này "invokeOnFormThread (myControl.SetColor (e));" –
Cảm ơn, sẽ điều tra.Trong thời gian đó, tôi đã sửa đổi runColorLoop() để tôi có thể chuyển màu, thời lượng, điều khiển và nếu tôi muốn ẩn sau khi hoạt ảnh kết thúc, theo cách đó tôi có thể sử dụng tất cả điều này trong lớp cơ sở và mọi thứ được thừa hưởng biểu mẫu có thể sử dụng base.runColorLoop (x, y, z, f); –