65.9K
CodeProject 正在变化。 阅读更多。
Home

WPF 屏幕保护程序助手

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (9投票s)

2015 年 11 月 8 日

CPOL

4分钟阅读

viewsIcon

18611

downloadIcon

326

一个帮助器 DLL, 用于简化创建 WPF 屏幕保护程序的(一些)烦恼。

https://nuget.net.cn/packages/ScreenSaver.Helper

引言

这是我的屏幕保护程序助手库的介绍。其目的是尽可能多地处理创建屏幕保护程序相关的琐碎细节。本质上,屏幕保护程序是一个常规的 exe 文件,只是扩展名更改为 .scr。在实际操作中,要使其正常工作需要多个组件。处理各种命令行参数、监听键盘和鼠标事件、允许配置、提供用于预览模式的 Win32 子窗口、多显示器支持等。此助手旨在尽可能简化这些方面。

背景

这是我第一次向 Code Project 贡献内容,但我从这里的所有专家那里受益匪浅,我认为是时候尝试回馈社区了。与其说是“如何做”,不如说这是一个您可以在开发屏幕保护程序时使用的工具。信不信由你,是的,屏幕保护程序的开发仍然有需求。在我的例子中,我有多个面向客户的自助服务终端,为了避免屏幕灼伤,我需要一个自定义的屏幕保护程序。在这种情况下,我想使用我们公司的 Facebook 页面,但这又是另一个话题。

使用代码

一旦您有了一个想要制作成屏幕保护程序的 WPF 应用程序,请引用 ScreenSaver.Helper.dll 和 log4net.dll,然后打开您的 App.xml,删除/注释掉现有的 StartupUri 并添加一个 Startup 方法。

<Application x:Class="WPF_App_Tester.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             Startup="App_OnStartup">
    <!--StartupUri="YourWindow">-->
...
</Application>​

完成此操作后,转到您的 App.xaml.cs 文件,使用 ScreensaverApp 特性将您的应用程序链接到 ScreenSaver 助手子系统。唯一必需的参数是主窗口(您的主要屏幕保护程序窗口),在下面的示例中,我们将其命名为“MainWindow”。有多个可选参数:ConfigWindow(窗口){这是您希望 Windows 使用的配置窗口}、RestartOnUnhandled(布尔值)、RepeatOnEachMonitor(布尔值)、StretchAcrossMonitors(布尔值)。

在您刚刚创建的 **App_OnStartup** 方法中,您应该将现有的参数(sender 和 e)传递给 Core.App_Startup 方法。这将在稍后为您处理多种因素(稍后介绍)。

您可能还希望挂钩 Core.UnhandledException 事件来处理任何意外的异常。默认情况下,该库使用 log4net 并创建一个滚动日志文件,存储在 AppData/AppName 中,在关闭之前记录异常。

using System.Windows;
using ScreenSaver.Helper;

namespace WPF_App_Tester
{
    [ScreensaverApp(typeof(MainWindow),typeof(ConfigWindow))]
    public partial class App : Application
    {
        private void App_OnStartup(object sender, StartupEventArgs e)
        {
            Core.UnhandledException += Core_UnhandledException;
            Core.App_Startup(sender, e);          
        }

        private void Core_UnhandledException(object sender, ref System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
        {
            // Your exception handling logic.
            // If you have resolved the exception 
            // set e.Handled = true;
        }
    }
}      

自定义设置提供程序

屏幕保护程序在访问链接回 WinNT 文件/文件夹的八个字符命名限制的文件/文件夹方面有一个怪癖,这会干扰默认的设置提供程序。与其调整这个,我们不如使用注册表的 HKCU 部分来存储我们的设置。该库提供了一个自定义设置提供程序来实现这一点。要使用它,请导航到您项目的设置文件,然后点击 **<> 查看代码** 按钮。Visual Studio 应该会将您带到您的 Settings.cs 文件。

添加对 **ScreenSaver.Helper.SettingsProviders** 的 using 引用,并添加两个属性。第一个,

[SettingsProvider(typeof(SettingsProviderEx))]

这告诉设置系统使用我们的备用提供程序,第二个,

[SettingsProviderEx.SettingsHelper(typeof(RegCurrentUserHelper))]

通知 **SettingsProviderEx** 使用我们之前讨论过的 HKCU 键。

using System.Configuration;
using ScreenSaver.Helper.SettingsProviders;
namespace WPF_App_Tester.Properties {

    [SettingsProviderEx.SettingsHelper(typeof(RegCurrentUserHelper))]
    [SettingsProvider(typeof(SettingsProviderEx))]

    internal sealed partial class Settings {...} 
...
}

命令行参数

如果您此时构建您的应用程序,它应该可以接受多个命令行参数了。

/s - 这是 Windows 屏幕保护程序必需的参数,它将显示您在 App.xaml.cs 的 MainWindow 属性中标识的窗体。在 IDE 中,它强制将窗口的 TopMost 设置为 false,以便进行调试断点和异常处理。当未附加调试器时,TopMost 设置为 true。

在显示模式下,鼠标和键盘事件监听器会被注入到 MainWindow 中,以允许传统屏幕保护程序通常具有的关闭事件。

默认情况下,如果存在多个显示器,则会在除被识别为主显示器的显示器之外的每个显示器上加载一个“遮罩”窗口。主显示器接收您的 MainWindow。

您可以根据需要使用 RepeatOnEachMonitor(bool) 或 StretchAcrossMonitors(bool) 来覆盖此行为。

/p IntPtr 使用 Windows 在选择屏幕保护程序时通常传递的 IntPtr,助手会将您的 MainWindow 设为预览模式的子窗口,但不注入任何鼠标/键盘关闭事件。

/c 打开您传递给 ScreenSaverApp 属性的 ConfigWindow 参数的 ConfigWindow。

/i 通过首先更改主文件扩展名(如果需要),将 .exe 更改为 .scr,然后更新注册表将您的屏幕保护程序设置为默认值,然后打开 Windows 屏幕保护程序配置窗口来安装屏幕保护程序。

附加助手类

日志记录

如前所述,助手库使用 log4Net 进行日志记录。您可以通过在添加对 **LogHelper** 类和 **log4net** 的引用后,使用提供的扩展方法来提供您自己的附加日志记录。

第一个 **Log()** 仅记录您的消息,并可选择添加一个异常对象。

 this.Log().Warning("YOUR WARNING MESSAGE",ex);

第二个 **LogP()** 也记录您的消息,但还会将调用类的公共属性添加到日志中。

 this.LogP().Error("YOUR ERROR MESSAGE",ex);

AnimationHelper

这是一个基于任务的动画助手,支持异步操作,另外,还提供了一个 Fade 方法,该方法调整 UIElement 或 IEnumerable<UIElement> 的不透明度以实现淡入/淡出。

用法: 

await Image.Fade();   // Fades Image opacity to 0 in 3 seconds
await Image.Fade(1);  // Fades Image opacity to 1 in 3 seconds
await Image.Fade(1,6.Secs());  // Fades Image opacity to 1 in 6 seconds *Using included TimeSpanExtensions

ListExtensions

随机化对象列表的方法。

MyList.Shuffle();

并将 List<string> 转换为 CSV 列表并返回。

string myCsvString = MyList.ToCsvLine();

List<string> MyList = myCsvString.FromCsvLine();

BitmapExtensions

将 Bitmap 转换为 ImageSource。

Image.Source = Properties.Resources.MyResourceBitmap.ToImageSource(); 

历史

2015/11/8 - 初始帖子

2016/7/9 - 清理了一些错别字。

© . All rights reserved.