分享如何使用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 代码如下;

  1. <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";
    • 注意监听鼠标按下键盘按键则退出屏保;
  1. 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]

参考资料

[1]

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/

WPF 制作 Windows 屏保的更多相关文章

  1. C#制作简易屏保(转)

    C#制作简易屏保[原创] 原始网址: http://www.cnblogs.com/drizzlecrj/archive/2006/10/06/522182.html 2006-10-06 16:25 ...

  2. C#制作简易屏保

    前言:前段时间,有个网友问我C#制作屏保的问题,我瞬间懵逼了(C#还可以制作屏保!).于是我去查阅相关资料,下面把C#如何制作屏保的过程及我学习过程的心得也记录下来,希望对需要的人能有帮助. 基本思路 ...

  3. 一个仿windows泡泡屏保的实现

    一个仿windows泡泡屏保的实现 有天看到有人在百度知道上问windows 泡泡屏保该怎么用C#做,一时有趣,就做了一个出来,对于其中几个要点总结如下: 一,屏保程序的制作要求 屏保程序的扩展名是. ...

  4. wpf 制作播放视频的屏保程序、而且能分屏显示

    这个程序用到了WPF里  “visual_Brush”(主要是为了实现分屏显示) , “UserControl” ,这两个知识点: 在屏保状态下播放指定文件夹下的视频,而且能分屏显示: 把编译好的屏保 ...

  5. WPF中桌面屏保的制作(主要代码)

    原文:WPF中桌面屏保的制作(主要代码) 制作要点:(1) 使用System.Windows.Threading.DispatcherTimer;(2) 将Window属性设置为:      this ...

  6. C# 制作屏保(图片位置随机变化)

    最近无所事事,闲着无聊,在网上翻看资料时碰巧看到了屏保制作,根据大神的思路也理解到屏保也不是很难.因此根据我自己的理解,动手谢了一个屏保. 首先,打开VS2010创建一个Windows窗体应用程序,名 ...

  7. 制作Windows XP万能克隆镜像

    制作Windows XP万能克隆镜像 战前分析:对于Windows XP,制作万能克隆时的一个重要问题就是系统激活,因为Windows XP为了防止盗版,采取了激活机制,当硬件发生改变时,系统就会要求 ...

  8. Linux关闭休眠和屏保模式

    本人因为特殊需求,想让某台Linux主机始终显示某个程序,显示器不能关机或者休眠或进入屏保模式. 环境:Ubuntu 11.10 最小化模式安装并安装有轻量级桌面openbox(非gnome).因为X ...

  9. Win XP 如何禁用屏保

    如果你试过 “在桌面空白处点击右键-[属性]-[屏幕保护程序],选择[无],点击[确定]”后,当时是可以去掉屏保.但如果重启计算机或者从待机状态唤醒后,屏保依然会出现,那么你可以试试下面的方法. 首先 ...

随机推荐

  1. SQL注入之information_schema

    在学习SQL注入时, 经常拿出来的例子就是PHP+MySQL这一套经典组合. 其中又经常提到的>=5.0版本的MySQL的内置库: information_schema 简单看一下informa ...

  2. 关于Spring中的useSuffixPatternMatch

    背景 spring-boot的版本是2.1.4.RELEASE,spring的版本是5.1.6.RELEASE 一个例子如下: @Configuration @Import(WebMvcAutoCon ...

  3. 【FAQ】分析服务导出的事件数据和概览页面展示的数据不一致该如何解决?

    华为分析服务面向开发者提供两种数据展现方式:(1)事件数据下载,开发者可以将事件数据下载后导入到自有的分析系统中:(2)直接在AGC概览页面查看用户数和事件数. 问题描述 某开发者想将事件数据导入到自 ...

  4. 使用 AgileConfig 动态配置 NLog

    NLog 是我们在 .NET 领域使用非常广泛的日志组件.它默认使用 xml 来维护它的配置.最近有几个同学问我当使用 AgileConfig 的时候如何配置 NLog .因为 AgileConfig ...

  5. Springboot目录结构分析

    1 src/main/java 存储源码 2 src/main/resource 资源文件夹    (1)src/main/resource/static 用于存放静态资源,如css.js.图片.文件 ...

  6. 设计并实现加法器类 Adder

    学习内容:设计并实现加法器类 Adder 代码示例: package 实验三; import java.util.Scanner; public class Adder { private int n ...

  7. CSS基础学习(一)

    1.设置背景颜色:background-color 例:background-color:#d0e4fe;或background-color:blue; 2.字体颜色·:color 例:color:r ...

  8. 【摸鱼神器】UI库秒变LowCode工具——列表篇(一)设计与实现

    内容摘要: 需求分析 定义 interface 定义 json 文件 定义列表控件的 props 基于 el-table 封装,实现依赖 json 渲染 实现内置功能:选择行(单选.多选),格式化.锁 ...

  9. 接口测试postman深度挖掘应用③--postman终结篇

    上一章节我们介绍了postman的变量测试以及导入数据测试基本上技术性的东西已经差不过了,这篇文章再系统性的介绍一下. 一.下载 官网:https://www.postman.com 1.选择需要下载 ...

  10. React项目配置npm run build命令分环境打包

    使用create-react-app脚手架创建的项目默认隐藏了webpack等配置文件信息,使用npm run eject命令暴露这些隐藏的配置文件信息 项目默认有两个环境:开发环境(npm star ...