需求:鼠标静止一段时间后,显示浮窗广告。
思路:界面XAML写好一个专门显示浮窗广告的Canvas,先设为不可见Visibility=”Collapsed”,然后用System.Timers.Timer类做计时器,设置该timer每秒钟重复运行一次(检测一次),给计数器自增并判断是否累计达到要显示广告的时间,要显示则修改为Visibility=”Visible”。界面绑定鼠标的移动事件为重置该计数器。广告右上角是关闭按钮,点击按钮修改回Visibility=”Collapsed”即可。
关键代码如下:
前台:
<!-- 浮窗广告:主界面鼠标静止一段时间后,显示该广告 -->
<Canvas x:Name="adCanvas" Width="400" Height="200" Visibility="Collapsed">
<!-- 关闭按钮 -->
<Button Command="{Binding CloseAdCanvasCommand}" Canvas.Right="0" Canvas.Top="0">
<Image Source="/项目名;component/Presentation/Resources/Images/tool.png" />
</Button>
</Canvas>
控制层关键代码
// 静止多少秒显示广告,写在了配置文件里
float adIntervalTime = float.Parse(ConfigurationManager.AppSettings["AD_WINDOW_INTERVAL_TIME"]);
#region 一段时间鼠标静止,浮窗广告
// 主界面鼠标移动事件。一段时间鼠标不移动,则浮窗广告
private void MouseMoveCommand()
{
adStopTime = 0; // 重置计时器
}
// 开始浮窗广告的计时
private void StartAdWindowTimer()
{
Timer timer = new Timer();
timer.Elapsed += new ElapsedEventHandler(TimerTick);
timer.Interval = 1000; // 每1秒重复检测一次
timer.Enabled = true;
}
// 计算是否要显示浮窗广告
private void TimerTick(object sender, EventArgs e)
{
adStopTime++;
if (adStopTime >= adIntervalTime && allowADShow)
{
adCanvasChangeVisibility(true);
allowADShow = false;
}
}
// 改变浮窗广告Canvas的显隐
private void adCanvasChangeVisibility(bool visible)
{
App.Current.Dispatcher.Invoke((Action)delegate // <--- HERE
{
if (visible)
adCanvas.Visibility = Visibility.Visible;
else
adCanvas.Visibility = Visibility.Collapsed;
});
}
// 初始化浮窗广告
private void InitAdCanvas()
{
adCanvas = shellWindow.adCanvas;
adCanvasChangeVisibility(false);
// 背景是广告图片
ImageBrush brush = new ImageBrush();
brush.ImageSource = new BitmapImage(new Uri("pack://application:,,,/项目名;component/Presentation/Resources/Images/logo.jpg"));
adCanvas.Background = brush;
}
// 关闭浮窗广告
private void CloseAdCanvasCommand()
{
adCanvasChangeVisibility(false);
allowADShow = true;
}
#endregion
资料参考MSDN中System.Timers.Timer类的使用:
2018.3.12更新:
另一种思路,用AutoResetEvent控制线程的阻塞、唤醒。
private void TestTimer() { AutoResetEvent autoResetEvent = new AutoResetEvent(false); int limit = 5; int index = 0; while (!autoResetEvent.WaitOne(TimeSpan.FromSeconds(3))) // 每隔3秒钟执行一次循环体 { index++; Console.WriteLine("index = " + index); if (index >= limit) { autoResetEvent.Set(); // 跳出循环体 } } Console.WriteLine("Thread got signal"); }
参考:
- http://blog.csdn.net/hejingyuan6/article/details/39700499
- http://blog.csdn.net/theoldfuture/article/details/52420913
- https://www.cnblogs.com/jicheng/articles/5998244.html
- https://www.cnblogs.com/czytcn/p/8085071.html
- https://docs.microsoft.com/zh-cn/dotnet/api/system.threading.waithandle.waitone?f1url=https%3A%2F%2Fmsdn.microsoft.com%2Fquery%2Fdev15.query%3FappId%3DDev15IDEF1%26l%3DZH-CN%26k%3Dk(System.Threading.WaitHandle.WaitOne);k(TargetFrameworkMoniker-.NETFramework&view=netframework-4.7.1