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

VB 定制 - 更改 Windows 7 中的登录背景

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.85/5 (12投票s)

2010年1月20日

CPOL

9分钟阅读

viewsIcon

55041

downloadIcon

2421

使用 VB 更改 Windows 7 登录背景

LogonBackgroundChanger_bin

引言

还记得过去的日子吗?那时,当您选择登录屏幕背景时,基本上只有云、云,或者更多的云?现在,有了 Windows 7,那些日子已经一去不复返了!这是第一个内置能力来原生显示自定义登录屏幕背景的 Windows 操作系统,无需任何第三方工具或黑客手段。本文将介绍如何使用注册表在 VB.NET 中操作 Windows 7 登录屏幕,包括一个方便的小工具来更改您的登录屏幕。

背景

在本文中,我将指导您创建一个名为“登录背景更改器”的非常方便的小型软件(好吧,我不太擅长起名,我们继续吧?),该软件能够使用注册表和一点 GDI+ 来更改登录屏幕背景,并为应用程序增加一些额外功能。

Windows 版本

任何版本的 Windows 7 都可以很好地用于本文,但任何其他 Windows 操作系统都不支持此功能。对于其他 Windows 版本,您可能需要依赖复杂的手动方法来获得您想要的登录屏幕背景。

规则

首先,任何要成为 Windows 7 登录屏幕的图像都必须满足某些标准。我敢打赌您在想“我就知道有陷阱!”,但这些标准是合理的(如果有点奇怪的话)。

  1. 图像必须小于 256 千字节(262144 字节)。如果超出此限制,Windows 将根本不显示它,而是使用默认屏幕。
  2. 图像必须是 JPEG 格式(带有*.jpg 扩展名)。
  3. 图像必须位于磁盘上的特定目录中,并且必须具有特定名称(稍后详细介绍)。

除了这些简单的规则外,实际上可以根据需要更改背景。

那么,图像存储在哪里?

背景图像文件通常存储在磁盘上的特定目录中:C:\Windows\System32\oobe\Info\Backgrounds

在此示例中,“C”是包含您的 Windows 7 安装的硬盘。每个文件都根据其应用的分辨率进行命名。

  • backgroundDefault.jpg
  • background768x1280.jpg
  • background900x1440.jpg
  • background960x1280.jpg
  • background1024x1280.jpg
  • background1280x1024.jpg
  • background1024x768.jpg
  • background1280x960.jpg
  • background1600x1200.jpg
  • background1440x900.jpg
  • background1920x1200.jpg
  • background1280x768.jpg
  • background1360x768.jpg

例如,如果您的显示器分辨率设置为 1280x1024,则名称为“background1280x1024.jpg”的背景将被用作您的登录背景;如果分辨率为 1360x768,则名称包含该分辨率的图像文件将被应用于您的登录屏幕。如果找不到与您的分辨率匹配的文件,则“backgroundDefault.jpg”将被缩放到适合您显示器当前分辨率并应用。

别忘了注册表!

就这样,对吧?恐怕不是!在自定义登录屏幕时,有一个非常重要的步骤很容易被遗忘,那就是进行必要的注册表修改。在这种情况下,注册表项:HKLM\Software\Microsoft\Windows\CurrentVersion\Authentication\LogonUI\Background,需要将值“OEMBackground”从0更改为1。如果值为0,Windows 将简单地忽略磁盘上的自定义图像,而是应用内置的登录背景。但是,如果该项包含值为1,Windows 将尝试应用您的自定义背景之一。

现在我们知道了 Windows 7 如何处理和显示登录背景,是时候开始创建我们简单、漂亮且非常有用的软件了。

Using the Code

我们的软件只会更改和操作用户计算机上的三个项目

  1. 位于C:\Windows\System32\oobe\info\backgrounds\backgroundDefault.jpg 的图像;我们可以扩展该软件以处理所有不同的分辨率。但就本文而言,我们将只更改拉伸以适应背景。
  2. 位于HKLM\Software\Microsoft\Windows\CurrentVersion\Authentication\LogonUI\Background 的注册表值OEMBackground,原因不言而喻。
  3. 我们自己创建的一个小型注册表值,用于整洁地存储我们当前登录背景的文件路径,称为PersistFile,它位于注册表项:HKEY_LOCAL_MACHINE\SOFTWARE\LogonBackgroundChanger

听起来很简单,对吧?确实如此,但我们会添加一些有用的代码来增强我们用户的体验。

用户界面

这是我们完成的用户界面的示意图,并简要说明了每个控件的作用(本文后面有更多详细信息)。

LabelledUI.png

整个窗体上只有一个重要的控件,那就是“应用”按钮。当该按钮被点击时,所有的操作都会在事件处理程序中进行:例如,修改注册表和将选定的文件转换为.jpg 文件,这些都发生在按下此按钮时。

步骤 1:检查操作系统!

在我们对注册表进行任何操作或处理文件系统之前,最好检查一下计算机的操作系统版本,因为我们的程序在 Windows 7 之前的任何 Windows 版本上都将毫无用处。这很简单,只需将其放在“应用”按钮点击事件的事件处理程序的开头即可。

'Check OS Version [
If Not My.Computer.Info.OSFullName.StartsWith("Microsoft Windows 7") Then
    MessageBox.Show("You must be running Microsoft Windows 7 in order " & _ 
                    "to use this program", "Error", _
                    MessageBoxButtons.OK, MessageBoxIcon.Error, _
                    MessageBoxDefaultButton.Button1)
    Exit Sub
End If
']

这将阻止任何人尝试在错误的操作系统上使用此实用程序,因为虽然它不会造成任何损害,但除非在 Windows 7 上使用,否则它肯定毫无用处。

步骤 2:获取 Windows 安装目录...

现在,这一步稍微复杂一些。我们必须考虑到用户安装 Windows 7 操作系统的位置可能有所不同。甚至可能不在 C 盘,或者根本不在名为“Windows”的文件夹中。这时就需要用到 Windows API 了。

Private Declare Function GetWindowsDirectory Lib "kernel32" Alias _
  "GetWindowsDirectoryA" (ByVal lpBuffer As String, ByVal nSize As Long) As Long

此函数接受一些略显复杂的参数,用于正确检索 Windows 安装文件夹,但它缺乏程序员的友好性,却能消除用户拥有与常用目录不同的 Windows 目录的微小风险。

但是,为了简化操作,最好将此 API 调用包装在一个方便的小函数中,由该函数为我们处理缓冲区的设置,如下所示:

''' <summary>
''' Returns the path of the windows installation directory.
''' </summary>
''' <returns></returns>
''' <remarks></remarks>
Private Function GetPath() As String

'Create Buffer [
GetPath = Space(255)
']

'Return Windows Directory Path [
Call GetWindowsDirectory(GetPath, Len(GetPath))
']

End Function

因此,在“应用”事件处理程序中,我们将在操作系统检查后放入此代码:

'Get Windows Directory [
 Dim WindowsInstallPath As String
 WindowsInstallPath = GetPath().Trim().TrimEnd(Chr(0)) & "\"
']

现在,此函数的作用是删除GetPath()返回的string末尾的所有null字符。这是因为如果我们尝试在下一段代码中使用它们,我们会收到“无效字符”的错误。

步骤 3:创建缺失的文件夹

对于稳健的代码来说,我们在编程中不应有任何假设,这就是为什么我们接下来使用以下代码来确保我们的用户拥有设置登录背景的正确文件夹:

'Create Missing Folders [
If Not My.Computer.FileSystem.DirectoryExists(WindowsInstallPath & _
                   "System32\oobe\info") Then
  My.Computer.FileSystem.CreateDirectory(WindowsInstallPath & _
                         "System32\oobe\info")
End If
If Not My.Computer.FileSystem.DirectoryExists(WindowsInstallPath & _
                   "System32\oobe\info\backgrounds") Then
  My.Computer.FileSystem.CreateDirectory(WindowsInstallPath & _
                         "System32\oobe\info\backgrounds")
End If
']

如果我们的用户没有正确的文件夹,我们会创建它们,从而确保我们稍后不会尝试将图像保存到不存在的文件夹中。

步骤 4:检查文件路径

接下来,在事件处理程序中,我们将检查为背景指定的图片文件是否确实存在于磁盘上,以及用户是否输入了任何内容!我们这样做如下:

'Check For Blank Box [
If FileSelectionBox.Text.Trim = "" Then

'Ask To Select [
Dim MyResult As DialogResult = MessageBox.Show("There is no picture file" & _ 
             " selected, would you like to select one now?", _
             "No File Selected", MessageBoxButtons.YesNo, _
             MessageBoxIcon.Warning)
']

'Confirmation [
Select Case MyResult
Case Windows.Forms.DialogResult.Yes

'Offer Selection [
ButtonBrowse_Click(Me, e)
']

End Select
']

'Exit Method [
Exit Sub
']

End If
']

'Check File Exists [
If Not My.Computer.FileSystem.FileExists(FileSelectionBox.Text) Then

'Show Error And Abort [
MessageBox.Show("The image file specified does not exist, please ensure " & _ 
                "that it is present on your computer.", _
                "Error - File Not Found", MessageBoxButtons.OK, _
                MessageBoxIcon.Error)
Exit Sub
']

End If
']

如果用户未输入任何内容,我们将通过调用“浏览...”按钮的事件处理程序来提供打开对话框以选择文件,前提是用户对我们显示的对话框回答“是”。如果他们的文件路径不存在,我们将要求他们更正。

步骤 5:检查文件大小

现在,这听起来真的很简单,对吧?我们只需使用一些标准代码来获取文件大小并检查它是否足够小。但是,在这种情况下,情况并非如此简单。我们将使用Bitmap对象将我们获得的任何 PNG 或 BMP 文件(如果需要)转换为 JPEG。这意味着文件(在大多数情况下)会缩小很多。我们需要将重新格式化的 JPEG 保存到一个临时文件中,以检查它是否足够小,可以使用以下代码:

Try

'Create Temporary File [
Dim TemporaryName As String = FileIO.FileSystem.GetTempFileName
']

'Reformat [
Dim ChangeToJPEG As New Bitmap(FileSelectionBox.Text)
']

'Save Reformatted File [
ChangeToJPEG.Save(TemporaryName, System.Drawing.Imaging.ImageFormat.Jpeg)
']

'Release Bitmap [
ChangeToJPEG.Dispose()
']

'Get Temporary File Size [
Dim MyInformation As New IO.FileInfo(TemporaryName)
If MyInformation.Length > 262144 Then

'Delete Temporary File [
If MyInformation.Exists() Then
MyInformation.Delete()
End If
']

'Error [
MessageBox.Show("The image file specified would be over 256KB " & _ 
    "when converted to a JPG file and too large to use. " & _ 
    "Please select another file.", "Error - File Too Large", _
    MessageBoxButtons.OK, MessageBoxIcon.Error)
Exit Sub
']

End If
']

'Delete Temporary File [
If MyInformation.Exists() Then
MyInformation.Delete()
End If
']

Catch MyException As Exception

'Format Error [
MessageBox.Show("The image file specified is not of the correct format. " & _
   "Logon Background Changer cannot convert it to JPG format " & _ 
   "for use as a logon screen. Please select another file.", _
   "Error - Incorrect Format", MessageBoxButtons.OK, MessageBoxIcon.Error)
Exit Sub
']

End Try

这将简单地获取文件并尝试将其重新格式化并临时保存为 JPEG,仅用于检查其大小。如果无法转换为 JPEG 或转换后的 JPEG 太大,将显示一个消息框并中止操作。

步骤 6:启用或禁用背景

这一部分代码紧随其后,根据我们窗体上复选框的状态,简单地将自定义背景从非活动切换到活动,反之亦然。

'Enable Or Disable Background [
Dim MyEnableSelection As Integer
If UseScreenCheck.Checked Then
  MyEnableSelection = 1
Else
  MyEnableSelection = 0
End If

My.Computer.Registry.SetValue("HKEY_LOCAL_MACHINE\SOFTWARE\" & _ 
  "Microsoft\Windows\CurrentVersion\Authentication\LogonUI\Background", _
  "OEMBackground", MyEnableSelection)
']
步骤 7:更改背景

现在,经过所有这些检查和转换后,我们终于准备好更改磁盘上的“backgroundDefault.jpg”文件以反映我们的更改,使用以下代码:

'Finally Change Screen [
Try

'Reformat [
Dim MyFinalPath As String = WindowsInstallPath & _
    "System32\oobe\info\backgrounds\backgroundDefault.jpg"
Dim ChangeToJPEG As New Bitmap(FileSelectionBox.Text)
']

'Delete Old File [
If My.Computer.FileSystem.FileExists(MyFinalPath) Then
My.Computer.FileSystem.DeleteFile(MyFinalPath)
End If
']

'Save Reformatted File [
ChangeToJPEG.Save(MyFinalPath, System.Drawing.Imaging.ImageFormat.Jpeg)
']

'Release Bitmap [
ChangeToJPEG.Dispose()
']

'Set Registry File Containing Path [            
My.Computer.Registry.SetValue(_
  "HKEY_LOCAL_MACHINE\SOFTWARE\LogonBackgroundChanger", _
  "PersistFile", FileSelectionBox.Text)
']

Catch MyException As Exception

MessageBox.Show("The image file specified is not of the correct format. " & _ 
   "Logon Background Changer cannot convert it to JPG format for use " & _ "
   as a logon screen. Please select another file.", _
   "Error - Incorrect Format", MessageBoxButtons.OK, MessageBoxIcon.Error)
Exit Sub

End Try
']

'Show Success [
MessageBox.Show("The changes were successfully applied.", _
  "Changes Saved", MessageBoxButtons.OK, MessageBoxIcon.Information)
']

此代码会重新格式化图像文件为 JPEG,并将其保存在正确的位置,以便 Windows 将其识别为登录背景。它还会更改一个仅供我们的程序使用的小注册表项,该注册表项在我们将选定的文件复制到登录背景文件夹之前存储了其文件路径。这只是为了方便我们的用户,并在我们主窗体的Load事件处理程序中再次访问和使用。

Private Sub Form_Main_Load(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles MyBase.Load

'Get Registry Values [
FileSelectionBox.Text = My.Computer.Registry.GetValue("HKEY_LOCAL_MACHINE\SOFTWARE" & _ 
    "\LogonBackgroundChanger", "PersistFile", "")
Dim MyEnableSelection As Integer = _
    My.Computer.Registry.GetValue("HKEY_LOCAL_MACHINE\SOFTWARE" & _ 
    "\Microsoft\Windows\CurrentVersion\Authentication\LogonUI\Background", _
    "OEMBackground", 0)
If MyEnableSelection > 0 Then
UseScreenCheck.Checked = True
Else
UseScreenCheck.Checked = False
End If
']

End Sub

此代码仅检索注册表中的任何值(即决定是否使用自定义背景的OEMBackground值,以及存储最近选定的背景文件的文件路径的我们自己的小值),并更新我们的 UI 以反映它们。

总结

以上就是我们软件最重要功能的详细介绍,希望代码中的注释能提供更多关于其内部工作原理的见解。我不会用“帮助”窗体或“退出”按钮的细节来烦扰您,但请随时自行进行分析。此应用程序可以大大扩展,以包含登录屏幕的预览以及不同分辨率的可自定义登录屏幕。但目前,我为您留下一个起点和一个使用 VB 操作注册表和文件系统以实现您想要的登录屏幕的示例!

致谢

  • 非常感谢 Mark James 为他提供的丝绸图标包(在应用程序中使用)。请访问他的网站 此处

历史

  • 2010 年 1 月 20 日 - 文章上传
  • 2010 年 1 月 22 日 - 文章更新
  • 2010 年 1 月 23 日 - 文章更新
© . All rights reserved.