[英]Changing Opacity With Reactive Extensions
<rant>是的,我知道在WPF中更容易实现。 我听到很多。 可悲的是,这是不可能的。 </ rant>
我正在编写WinForms应用程序,并且需要“渐入渐出”控件。 在WinForms中,透明度几乎是不可能的,因此我尝试使用不透明度:想法是在一段时间内更改每个子控件的ForeColor属性的Alpha通道。 这似乎是我的Reactive Extensions工作的绝佳时机!
我可能的解决方案是:
private void FadeOut()
{
// our list of values for the alpha channel (255 to 0)
var range = Enumerable.Range(0,256).Reverse().ToList();
// how long between each setting of the alpha (huge value for example only)
var delay = Timespan.FromSeconds(0.5);
// our "trigger" sequence, every half second
Observable.Interval(delay)
// paired with the values from the range - we just keep the range
.Zip(range, (lhs, rhs) => rhs)
// make OnNext changes on the UI thread
.ObserveOn(SynchronizationContext.Current)
// do this every time a value is rec'd from the sequence
.Subscribe(
// set the alpha value
onNext:ChangeAlphaValues,
// when we're done, really hide the control
onCompleted: () => Visible = false,
// good citizenry
onError: FailGracefully);
}
// no need to iterate the controls more than once - store them here
private IEnumerable<Control> _controls;
private void ChangeAlphaValues(int alpha)
{
// get all the controls (via an extension method)
var controls = _controls ?? this.GetAllChildControls(typeof (Control));
// iterate all controls and change the alpha
foreach (var control in controls)
control.ForeColor = Color.FromArgb(alpha, control.ForeColor);
}
...看起来不错,但不起作用。 真正令人印象深刻的部分是它不能以两种方式起作用! 如果我坚持下去,我的下一次性能评测将获得“超额成绩”。 :-)
尚未处理System.InvalidOperationException消息:System.Reactive.Core.dll中发生了'System.InvalidOperationException'类型的未处理异常。其他信息:在创建窗口句柄之前,无法在控件上调用Invoke或BeginInvoke。
我认为这是取消令牌会派上用场的地方-但我不知道如何实现它。
如果序列仍在运行,如何优雅地关闭窗口(即不引发错误),以及如何获取更改后的颜色实际显示的alpha值。
我愿意接受其他建议。
对于WinForms透明性部分,我无能为力。 也许您应该将问题分成两部分。
但是对于Rx部分,您只需要在关闭窗口时取消订阅即可。 Subscribe
返回IDisposable
。 您应该在Closed
事件中处理它。
并且,由于我假设此淡入淡出动画可能在关闭窗口之前被多次调用,因此我们可以使用Rx帮助器SerialDisposable
。
最后, Interval
实际上返回一个计数。 我们可以通过仅计算所需的alpha值来简化可观察性。
private SerialDisposable _fadeAnimation = new SerialDisposable();
private void FadeOut()
{
// how long between each setting of the alpha (huge value for example only)
var delay = Timespan.FromSeconds(0.5);
_fadeAnimation.Disposable = Observable
.Interval(delay)
// 256 animation steps
.Take(256)
// calculate alpha
.Select(i => 255 - i)
.ObserveOn(SynchronizationContext.Current)
.Subscribe(
// set the alpha value
onNext:ChangeAlphaValues,
// when we're done, really hide the control
onCompleted: () => Visible = false,
// good citizenry
onError: FailGracefully);
}
private void Form1_Closed()
{
_fadeAnimation.Dispose();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.