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

如何开发 C# 中的屏幕保护程序

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.59/5 (81投票s)

2003年8月20日

6分钟阅读

viewsIcon

412204

downloadIcon

6928

本文将介绍如何使用 C# 开发屏幕保护程序,并提供一个可直接使用的屏幕保护程序源代码。

涵盖的问题

本文解释了

  • 屏幕保护程序的基础知识
  • 加载屏幕保护程序
  • 填充整个屏幕
  • 处理多显示器
  • 处理事件
  • 一些小细节

此外,该代码提供了一个基本的屏幕保护程序框架,您可以轻松地在此基础上创建自己的屏幕保护程序。

引言

在 Windows® 中,屏幕保护程序本质上就是一个扩展名为 .scr 的可执行文件。普通可执行文件与屏幕保护程序的唯一区别在于,屏幕保护程序会执行一些特定的操作,即:

  • 解析命令行以确定 Windows® 的意图
  • 根据请求加载相应的屏幕保护程序
  • 在用户使用鼠标或键盘时结束屏幕保护程序(通常情况下)

Windows® 传递给屏幕保护程序的参数包括:

  • /s - 加载屏幕保护程序
  • /c - 加载配置屏幕
  • /p - 加载预览

一旦确定了传递的参数,我们就可以相应地加载屏幕保护程序。当有某种活动发生时,您可以结束屏幕保护程序或执行其他操作。

代码解释

第一步:使 Main 方法接受命令行参数

在 C# 中开发屏幕保护程序的第一个步骤是修改 Main 方法,使其能够接受命令行参数。默认的 Main 方法如下所示:

static void Main() 
{
  ...
}

如您所见,这个 Main 方法不接受任何参数。因此,我们添加一个 string 数组参数,如下所示:

static void Main(string[] args) 
{
  ...
}

第二步:检查参数

现在我们需要找出传递了哪些参数。

首先,我们通过检查 string 数组的长度是否为零来判断 Windows® 是否传递了任何参数。如果长度为零,则没有参数。当用户双击屏幕保护程序文件时,通常会出现没有参数传递给屏幕保护程序的场景。

其次,如果确实有参数传递过来,我们就捕获它们。Windows® 可能传递大写或小写的参数。因此,最好进行某种程度的泛化。我们首先将参数转换为小写(或大写),然后进行检查。完整的 Main 方法看起来应该是这样的:

static void Main(string[] args) 
{
  if (args.Length > 0)
  {
    // load the config stuff
    if (args[0].ToLower().Trim().Substring(0,2) == "/c") 
    {
      ...
    }
    else if (args[0].ToLower() == "/s") // load the screensaver
    {
      ...
    }
    else if (args[0].ToLower() == "/p") // load the preview
    {
      ...
    }
  }
  else // there are no arguments...nevertheless, do something!
  {
    ...
  }
}

非常直接,不是吗?您只需要在这里添加您希望为每个参数执行的代码。

第三步:调用屏幕保护程序

要运行屏幕保护程序,您需要调用 System.Windows.Forms.Application.Run 方法。您将一个新窗体对象作为参数传递。代码将如下所示:

System.Windows.Forms.Application.Run(new frmScreenSaver());

其中 frmScreenSaver 是主要的屏幕保护程序窗体。

当屏幕保护程序加载时,我们希望它能够填充整个屏幕。为此,我们需要弄清楚屏幕保护程序当前正在哪个屏幕上运行以及该屏幕的尺寸。要访问屏幕,我们使用 Screen 类。使用该类的 PrimaryScreen 属性,我们可以访问系统的主要屏幕及其属性。其中一个属性是 Bounds,它代表屏幕的大小。我们的做法是将窗体的 Bounds 属性设置为与该屏幕的 Bounds 属性相同,这样窗体就会被调整大小以占据整个屏幕。这个过程通常在窗体的 Load 事件中执行,例如:

private void frmScreenSaver_Load(object sender, System.EventArgs e)
{
  ...
  Bounds = Screen.PrimaryScreen.Bounds;
  ...
}

不过,我们还需要考虑一种可能性——用户可能使用多个显示器。如果是这样,并且我们只在一个屏幕上加载屏幕保护程序,那么使用这个屏幕保护程序的意义就丧失了。因此,我们找出可用屏幕的数量,并在每个屏幕上加载屏幕保护程序。为此,我们在 Main 方法中遍历系统中所有可用的屏幕,重复调用窗体的构造函数,并传递屏幕的索引。系统中所有可用屏幕的列表可以在 Screen 类的 AllScreens 属性中找到。因此,在 Main 方法中调用屏幕保护程序的代码需要修改为:

...
...
for (int i = Screen.AllScreens.GetLowerBound(0); 
     i <= Screen.AllScreens.GetUpperBound(0); i++)
  System.Windows.Forms.Application.Run(new frmScreenSaver(i));
...
...

请注意,主要的屏幕保护程序窗体的构造函数发生了变化——它接受一个 int 参数,该参数表示屏幕保护程序要运行的屏幕的索引。作为响应,我们通过添加一个 int 成员变量来修改窗体类,该变量将存储屏幕索引。然后,窗体的构造函数将修改为初始化此变量,如下所示:

public frmScreenSaver(int scrn)
{
  ...
  ScreenNumber = scrn;
  ...
}

其中 ScreenNumberint 成员变量。

在此之后,需要修改 Load 事件处理程序,使其将窗体调整到不是主屏幕的边界,而是由索引表示的屏幕的边界,如下所示:

private void frmScreenSaver_Load(object sender, System.EventArgs e)
{
  ...
  Bounds = Screen.AllScreens[ScreenNumber].Bounds;
  ...
}

完成这些操作后,我们就为屏幕保护程序添加了多显示器显示功能。

您可能希望将窗体设置为最顶层并隐藏光标。只需在 Load 处理程序中调用附加方法,如下所示:

private void frmScreenSaver_Load(object sender, System.EventArgs e)
{
  ...
  Bounds = Screen.AllScreens[ScreenNumber].Bounds;
    Cursor.Hide();
    TopMost = true;
  ...
}

第四步:处理事件

加载屏幕保护程序后,您需要处理事件。这是因为当用户移动鼠标或按下键盘时,您可能希望执行一些操作,例如结束屏幕保护程序。为此,您需要将事件处理程序添加到屏幕保护程序窗体的 KeyDownMouseMoveMouseDown 事件中。在事件处理程序中,您可以使用窗体的 Close 方法来结束屏幕保护程序。

这里有一点需要注意。当应用程序执行时,Windows® 会将当前的鼠标参数传递给它。这自然会触发鼠标事件,从而导致屏幕保护程序关闭。为了处理这个问题,请在类中添加一个 Point 变量,在应用程序执行时对其进行初始化,并在鼠标事件发生时检查鼠标位置和鼠标单击。如果发生任何变化,则调用 Close。代码将如下所示:

private void OnMouseMove(object sender, 
                         System.Windows.Forms.MouseEventArgs e)
{
  if (!MouseXY.IsEmpty)
  {
    if (MouseXY != new Point(e.X, e.Y))
       Close();
  }
  MouseXY = new Point(e.X, e.Y);
}

其中 MouseXY 是我们用来临时存储初始鼠标位置的 Point 变量。最初,MouseXY 为 null;因此,通过此代码将其分配为当前鼠标位置。在下次调用此事件处理程序时,MouseXY 不为空;因此,我们检查位置是否已更改;如果已更改,则关闭窗体。

如前所述,您应该在屏幕保护程序中同时处理 MouseMoveMouseDown 事件。但由于它们具有相同的参数,因此您可以为处理这两个事件使用相同的事件处理程序。这样的代码看起来像:

private void OnMouseEvent(object sender, 
                          System.Windows.Forms.MouseEventArgs e)
{
  if (!MouseXY.IsEmpty)
  {
    if (MouseXY != new Point(e.X, e.Y))
      Close();
    if (e.Clicks > 0)
        Close();
  }
  MouseXY = new Point(e.X, e.Y);
}

其中 OnMouseEvent 是在鼠标移动和鼠标单击事件发生时调用的事件处理程序。

第五步:最后...

开发屏幕保护程序的最后一步简短而甜蜜……将文件重命名为 .scr 扩展名。:)

您完成了!

使用捆绑代码

提供的代码只加载一个黑色窗体。要进行更改并实现自己的功能,请遵循以下简单步骤:

  1. 修改 Main 方法中的代码以处理不同的参数
  2. 如有必要,添加一个配置窗体,并在 Main 方法中添加加载该窗体的代码
  3. 修改主要的屏幕保护程序窗体以显示您想要的内容
  4. 将扩展名从 .exe 重命名为 .scr
  5. 开始吧!
© . All rights reserved.