分享如何使用WPF 制作 Windows 屏保
WPF 制作 Windows 屏保
作者:驚鏵
原文链接:https://github.com/yanjinhuagood/ScreenSaver
-
框架使用
.NET452
; -
Visual Studio 2019
; -
项目使用 MIT 开源许可协议;
-
更多效果可以通过GitHub[1]|码云[2]下载代码;
-
也可以自行添加天气信息等。
正文
-
屏保程序的本质上就是一个
Win32
窗口应用程序;-
把编译好一个窗口应用程序之后,把扩展名更改为 scr
,于是你的屏幕保护程序就做好了;
-
-
选中修改好的 scr
程序上点击右键,可以看到一个安装
选项,点击之后就安装了;

处理屏幕保护程序参数如下
-
/s 屏幕保护程序开始,或者用户点击了 预览
按钮; -
/c 用户点击了 设置
按钮; -
/p 用户选中屏保程序之后,在预览窗格中显示;
1)MainWindow.xaml
代码如下;
<Window x:Class="ScreenSaver.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:system="clr-namespace:System;assembly=mscorlib" xmlns:drawing="http://www.microsoft.net/drawing" xmlns:local="clr-namespace:ScreenSaver" mc:Ignorable="d" WindowStyle="None" Title="MainWindow" Height="450" Width="800"> <Grid x:Name="MainGrid"> <drawing:PanningItems ItemsSource="{Binding stringCollection,RelativeSource={RelativeSource AncestorType=local:MainWindow}}" x:Name="MyPanningItems"> <drawing:PanningItems.ItemTemplate> <DataTemplate> <Rectangle> <Rectangle.Fill> <ImageBrush ImageSource="{Binding .}"/> </Rectangle.Fill> </Rectangle> </DataTemplate> </drawing:PanningItems.ItemTemplate> </drawing:PanningItems> <Grid HorizontalAlignment="Center" VerticalAlignment="Top" Margin="0,50,0,0"> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition/> </Grid.RowDefinitions> <Grid.Resources> <Style TargetType="TextBlock"> <Setter Property="FontSize" Value="90"/> <Setter Property="FontWeight" Value="Black"/> <Setter Property="Foreground" Value="White"/> </Style> </Grid.Resources> <WrapPanel> <TextBlock Text="{Binding Hour,RelativeSource={RelativeSource AncestorType=local:MainWindow}}"/> <TextBlock Text=":" x:Name="PART_TextBlock"> <TextBlock.Triggers> <EventTrigger RoutedEvent="FrameworkElement.Loaded"> <BeginStoryboard> <Storyboard> <DoubleAnimation Duration="00:00:01" From="1" To="0" Storyboard.TargetName="PART_TextBlock" Storyboard.TargetProperty="Opacity" RepeatBehavior="Forever" FillBehavior="Stop"/> </Storyboard> </BeginStoryboard> </EventTrigger> </TextBlock.Triggers> </TextBlock> <TextBlock Text="{Binding Minute,RelativeSource={RelativeSource AncestorType=local:MainWindow}}"/> </WrapPanel> <TextBlock Grid.Row="1" FontSize="45" HorizontalAlignment="Center" Text="{Binding Date,RelativeSource={RelativeSource AncestorType=local:MainWindow}}"/> </Grid> </Grid></Window>
2) MainWindow.xaml.cs
代码如下;
-
当屏保启动后需要注意如下 -
将鼠标设置为不可见 Cursors.None
; -
将窗体设置为最大化 WindowState.Maximized
; -
WindowStyle
设置为"None"
; -
注意监听 鼠标按下
和键盘按键
则退出屏保;
-
using System;using System.Collections.ObjectModel;using System.Globalization;using System.IO;using System.Windows;using System.Windows.Input;using System.Windows.Threading;namespace ScreenSaver{ /// <summary> /// MainWindow.xaml 的交互逻辑 /// </summary> public partial class MainWindow : Window { public static readonly DependencyProperty stringCollectionProperty = DependencyProperty.Register("stringCollection", typeof(ObservableCollection<string>), typeof(MainWindow), new PropertyMetadata(null)); public static readonly DependencyProperty HourProperty = DependencyProperty.Register("Hour", typeof(string), typeof(MainWindow), new PropertyMetadata(null)); public static readonly DependencyProperty MinuteProperty = DependencyProperty.Register("Minute", typeof(string), typeof(MainWindow), new PropertyMetadata(null)); public static readonly DependencyProperty SecondProperty = DependencyProperty.Register("Second", typeof(string), typeof(MainWindow), new PropertyMetadata(null)); public static readonly DependencyProperty DateProperty = DependencyProperty.Register("Date", typeof(string), typeof(MainWindow), new PropertyMetadata()); private readonly DispatcherTimer timer = new DispatcherTimer(); public MainWindow() { InitializeComponent(); Loaded += delegate { WindowState = WindowState.Maximized; Mouse.OverrideCursor = Cursors.None; var date = DateTime.Now; Hour = date.ToString("HH"); Minute = date.ToString("mm"); Date = $"{date.Month} / {date.Day} {CultureInfo.CurrentCulture.DateTimeFormat.GetDayName(date.DayOfWeek)}"; stringCollection = new ObservableCollection<string>(); var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Images"); var directoryInfo = new DirectoryInfo(path); foreach (var item in directoryInfo.GetFiles()) { if (Path.GetExtension(item.Name) != ".jpg") continue; stringCollection.Add(item.FullName); } timer.Interval = TimeSpan.FromSeconds(1); timer.Tick += delegate { date = DateTime.Now; Hour = date.ToString("HH"); Minute = date.ToString("mm"); Date = $"{date.Month} / {date.Day} {CultureInfo.CurrentCulture.DateTimeFormat.GetDayName(date.DayOfWeek)}"; }; timer.Start(); }; MouseDown += delegate { Application.Current.Shutdown(); }; KeyDown += delegate { Application.Current.Shutdown(); }; } public ObservableCollection<string> stringCollection { get => (ObservableCollection<string>)GetValue(stringCollectionProperty); set => SetValue(stringCollectionProperty, value); } public string Hour { get => (string)GetValue(HourProperty); set => SetValue(HourProperty, value); } public string Minute { get => (string)GetValue(MinuteProperty); set => SetValue(MinuteProperty, value); } public string Second { get => (string)GetValue(SecondProperty); set => SetValue(SecondProperty, value); } public string Date { get => (string)GetValue(DateProperty); set => SetValue(DateProperty, value); } }}
参考①[3] 参考②[4]
参考资料
GitHub: https://github.com/yanjinhuagood/ScreenSaver
[2]
码云: https://gitee.com/yanjinhua/ScreenSaver
[3]
参考①: https://blog.walterlv.com/post/write-a-windows-screen-saver-using-wpf.html
[4]
参考②: https://wbsimms.com/create-screensaver-net-wpf/