前一段看Acer笔记本的广告,看到笔记本全屏了一个音乐的波形图。脑子里闪过了一个念头,用音乐做屏保加上音乐波谱的屏幕效果应该很不错,作为程序员,往往脑子里想的是:如果要我写这个东西要怎样怎样做。于是就有了我今天要谈论的话题。
从网上查找了一下关于如何做屏保程序的资料,不是很多,好多都是写好的软件。代码级别的就找到一个微软的,不过Microsoft还不错,把思想讲清楚了,最让人感动的是居然有全部的代码。链接如下:http://support.microsoft.com/kb/818359/zh-cn
参照上面的文章,还要搞清楚windows是怎么设定和启动屏保程序的。桌面上右击,在弹出菜单中选择“属性”,出现“显示属性”窗口,选择“屏幕保护程序”页,有一个选择屏保程序的下拉框,其选项对应系统盘\WINDOWS\system32下以scr为后缀名的文件(应用程序)。你选择了某个选项作为屏保后,系统的Timer就会计时,满足启动屏保的条件时,被选择的屏保程序就启动运行,启动后它会做一些动作,比如全屏,在所有窗口前,黑底,显示字或者图形并运动起来。所有的屏保共通点是:必须在点击或移动鼠标,按下键盘上的任意键时结束,这个时候屏保程序的任务就完成了。如果你在先前设置屏保时,在“密码保护”前的复选框上打上钩,那么此时程序将回到系统的欢迎界面让你输入密码,我想这不是屏保的工作,而是由Timer来做的,在屏保程序结束的地方进行判断是否需要做密码保护。上面都是我查阅资料加上我自己的理解,搞不好Windows就是这么做的,呵呵。
按照上面的理解,还需要可行性分析。自己写一个程序,以scr为后缀名,把他放到系统盘\WINDOWS\system32下,然后在刚才那个屏保的下拉框里选择我们自己的屏保可行吗?能用吗?事实证明还真的可以,可行性分析OK了。
分析上面链接里的资料,先读懂它的代码先。示例代码有一个对话框窗体(设置滚动文字内容),一个屏保窗体和一个Module。从程序代码中我们可以学到不少东西。①程序入口Sub Main在Module中,从这里我们可以了解到原来设置屏保程序时,在“屏幕保护程序”属性页点击设定时windows向屏保程序传递的第一个启动参数包含"/c",而预览和实绩运行时,windows向屏保程序传递的第一个启动参数包含"/s"。②对话框窗体frmcnfg和屏保窗体frmscr分别提供了如何写入系统注册表和读取注册表的方法。③PrevInstance()函数提供了如何防止一个程序被启动多个的方法④屏保窗体frmscr类中提供了关闭和打开Windows的CTRL+ALT+DEL 和 ALT+TAB组合键的方法(使用了API函数)。⑤对于移动鼠标时程序结束的处理。如果要自己写程序,可能会在这个地方遇到问题,如果在MouseMove事件中只有me.close(),那么屏保程序总是闪一下就停了。参照上面的资料我们就能知道原因了,因为窗体启动之后有个初始化鼠标位置的动作,其动作应该是一格一格的(我根据代码猜的),所以我们看到微软提供的方法是移动鼠标的幅度大于3才结束程序。⑥美中不足的是这个程序没有响应鼠标MouseDown事件,自己加上就行了。
还是把完整的代码贴在下面,方便查阅,再次声明是转自以下链接: http://support.microsoft.com/kb/818359/zh-cn1
Imports Microsoft.Win322
Imports Microsoft.VisualBasic3
Imports System.Math4

Public Class frmscrClass frmscr5
Inherits System.Windows.Forms.Form6

7

Windows Form Designer generated code#Region " Windows Form Designer generated code "8

9

Public Sub New()Sub New()10
MyBase.New()11

12
'The Windows Form Designer requires this call.13
InitializeComponent()14

15
'Add any initialization after the InitializeComponent() call.16

17
End Sub18

19
'Form overrides dispose to clean up the component list.20

Protected Overloads Overrides Sub Dispose()Sub Dispose(ByVal disposing As Boolean)21
If disposing Then22
If Not (components Is Nothing) Then23
components.Dispose()24
End If25
End If26
MyBase.Dispose(disposing)27
End Sub28

29
'Required by the Windows Form Designer.30
Private components As System.ComponentModel.IContainer31

32
'NOTE: The Windows Form Designer requires the following procedure.33
'It can be modified by using the Windows Form Designer. 34
'Do not modify the procedure by using the Code editor.35
Friend WithEvents lblMessage As System.Windows.Forms.Label36
Friend WithEvents Timer1 As System.Windows.Forms.Timer37

<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()Sub InitializeComponent()38
Me.components = New System.ComponentModel.Container39
Me.lblMessage = New System.Windows.Forms.Label40
Me.Timer1 = New System.Windows.Forms.Timer(Me.components)41
Me.SuspendLayout()42
'43
'lblMessage44
'45
Me.lblMessage.AutoSize = True46
Me.lblMessage.BackColor = System.Drawing.Color.Black47
Me.lblMessage.ForeColor = System.Drawing.Color.Yellow48
Me.lblMessage.Location = New System.Drawing.Point(72, 118)49
Me.lblMessage.Name = "lblMessage"50
Me.lblMessage.Size = New System.Drawing.Size(193, 36)51
Me.lblMessage.TabIndex = 152
Me.lblMessage.Text = "screen saver"53
Me.lblMessage.TextAlign = System.Drawing.ContentAlignment.MiddleCenter54
'55
'Timer156
'57
Me.Timer1.Enabled = True58
'59
'frmscr60
'61
Me.AutoScaleBaseSize = New System.Drawing.Size(15, 33)62
Me.BackColor = System.Drawing.Color.Black63
Me.ClientSize = New System.Drawing.Size(292, 273)64
Me.ControlBox = False65
Me.Controls.Add(Me.lblMessage)66
Me.Font = New System.Drawing.Font("Microsoft Sans Serif", 21.75!, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, CType(0, Byte))67
Me.MaximizeBox = False68
Me.MinimizeBox = False69
Me.Name = "frmscr"70
Me.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen71
Me.TopMost = True72
Me.WindowState = System.Windows.Forms.FormWindowState.Maximized73
Me.ResumeLayout(False)74

75
End Sub76

77
#End Region78

79

Private Sub frmscr_Load()Sub frmscr_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load80

81
Dim tmpLng As Integer82
tmpLng = SystemParametersInfo(SPI_SCREENSAVERRUNNING, 1&, 0&, 0&)83

84
'Get the user's previous preference for the marquee message.85

86
Dim pRegKey As RegistryKey = Registry.CurrentUser87
pRegKey = pRegKey.OpenSubKey("Software\\Test Screen Saver")88
Dim val As Object = pRegKey.GetValue("Message")89
pRegKey.Close()90
lblMessage.Text = val.ToString91

92
'Make the cursor disappear.93

94
Me.Cursor.Current.Hide()95
End Sub96

97

Private Sub frmscr_KeyDown()Sub frmscr_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyDown98
'Immediately end when any key is pressed.99
Me.Close()100
End Sub101

102

Private Sub frmscr_Activated()Sub frmscr_Activated(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Activated103
'Center the lblMessage label to the form.104
lblMessage.Left = GetScaleWidth(Me)105
lblMessage.Top = (GetScaleWidth(Me) - lblMessage.Height) / 3106
End Sub107

108

Private Sub frmscr_Closing()Sub frmscr_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing109
'System.Windows.Forms.Cursor.Current.Show110
''Restore the mouse cursor.111
Dim tmplng As Integer112
Me.Cursor.Current.Show()113

114
tmplng = SystemParametersInfo(SPI_SCREENSAVERRUNNING, 0&, 0&, 0&)115
End Sub116

117

Private Sub Timer1_Tick()Sub Timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer1.Tick118
'Determine whether the Message has moved completely off the left side of the screen.119
If lblMessage.Left < (0 - lblMessage.Width) Then120
lblMessage.Left = GetScaleWidth(Me) 'ScaleWidth121
End If122

123
'Moves lblMessage to the left.124
lblMessage.Left = lblMessage.Left - 10125

126

127
End Sub128

129

Private Sub frmscr_MouseMove()Sub frmscr_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseMove130

131
Static OldX As Integer132
Static OldY As Integer133

134
'Determines whether the mouse was moved and whether the movement was large.135
'if so, the screen saver is ended.136
If (OldX > 0 And OldY > 0) And (Abs(e.X - OldX) > 3 Or Abs(e.Y - OldY) > 3) Then137
Me.Close()138

139
End If140

141
'Assigns the current X and Y locations to OldX and OldY.142
OldX = e.X143
OldY = e.Y144

145
End Sub146
End Class1
Imports Microsoft.Win322

Public Class frmcnfgClass frmcnfg3
Inherits System.Windows.Forms.Form4

5

Windows Form Designer generated code#Region " Windows Form Designer generated code "6

7

Public Sub New()Sub New()8
MyBase.New()9

10
'The Windows Form Designer requires this call.11
InitializeComponent()12

13
'Add any initialization after the InitializeComponent() call.14

15
End Sub16

17
'Form overrides dispose to clean up the component list.18

Protected Overloads Overrides Sub Dispose()Sub Dispose(ByVal disposing As Boolean)19
If disposing Then20
If Not (components Is Nothing) Then21
components.Dispose()22
End If23
End If24
MyBase.Dispose(disposing)25
End Sub26

27
'Required by the Windows Form Designer.28
Private components As System.ComponentModel.IContainer29

30
'NOTE: The Windows Form Designer requires the following procedure.31
'It can be modified by using the Windows Form Designer. 32
'Do not modify the procedure by using the Code editor.33
Friend WithEvents txtmessage As System.Windows.Forms.TextBox34
Friend WithEvents cmdcancel As System.Windows.Forms.Button35
Friend WithEvents cmdOk As System.Windows.Forms.Button36
Friend WithEvents label1 As System.Windows.Forms.Label37

<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()Sub InitializeComponent()38
Me.cmdOk = New System.Windows.Forms.Button39
Me.cmdcancel = New System.Windows.Forms.Button40
Me.label1 = New System.Windows.Forms.Label41
Me.txtmessage = New System.Windows.Forms.TextBox42
Me.SuspendLayout()43
'44
'cmdOk45
'46
Me.cmdOk.Location = New System.Drawing.Point(200, 184)47
Me.cmdOk.Name = "cmdOk"48
Me.cmdOk.Size = New System.Drawing.Size(56, 24)49
Me.cmdOk.TabIndex = 050
Me.cmdOk.Text = "&OK"51
'52
'cmdcancel53
'54
Me.cmdcancel.Location = New System.Drawing.Point(272, 184)55
Me.cmdcancel.Name = "cmdcancel"56
Me.cmdcancel.Size = New System.Drawing.Size(56, 24)57
Me.cmdcancel.TabIndex = 158
Me.cmdcancel.Text = "&Cancel"59
'60
'label161
'62
Me.label1.Location = New System.Drawing.Point(24, 40)63
Me.label1.Name = "label1"64
Me.label1.Size = New System.Drawing.Size(152, 24)65
Me.label1.TabIndex = 266
Me.label1.Text = "Enter Message"67
'68
'txtmessage69
'70
Me.txtmessage.Location = New System.Drawing.Point(32, 64)71
Me.txtmessage.Multiline = True72
Me.txtmessage.Name = "txtmessage"73
Me.txtmessage.Size = New System.Drawing.Size(296, 96)74
Me.txtmessage.TabIndex = 375
Me.txtmessage.Text = ""76
'77
'frmcnfg78
'79
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)80
Me.ClientSize = New System.Drawing.Size(344, 221)81
Me.Controls.Add(Me.txtmessage)82
Me.Controls.Add(Me.label1)83
Me.Controls.Add(Me.cmdcancel)84
Me.Controls.Add(Me.cmdOk)85
Me.Name = "frmcnfg"86
Me.Text = "CONFIGURATION"87
Me.ResumeLayout(False)88

89
End Sub90

91
#End Region92

93

94

Private Sub cmdcancel_Click()Sub cmdcancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdcancel.Click95
Me.Close()96
End Sub97

98

Private Sub cmdOk_Click()Sub cmdOk_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdOk.Click99
'Save the current settings to100
'HKEY_CURRENT_USER\Software\101
'in the registry.102

103

104
Dim key As RegistryKey = Registry.CurrentUser.OpenSubKey("Software", True)105
Dim newkey As RegistryKey = key.CreateSubKey("Test Screen Saver")106
newkey.SetValue("Message", txtmessage.Text)107
newkey.Close()108
Me.Close()109
End Sub110
End Class1
Imports System.Runtime.InteropServices2
Imports System.Environment3

4

Module Module1Module Module15

6

Public Declare Auto Function SystemParametersInfo()Function SystemParametersInfo Lib "user32" (ByVal uAction As Integer, ByVal uParam As Integer, ByRef pvParam As Integer, ByVal fuWinIni As Integer) As Boolean7
Public Const SPI_SCREENSAVERRUNNING = 97&8
Public Const frmedge As Integer = 49
Public nMouseMoves&10
Dim sStartType11

12

13

Public Sub Main()Sub Main(ByVal args As String())14
Dim Inst As Boolean = False15

16

17
If args.Length > 0 Then18
sStartType = args(0).ToLower.Trim().Substring(0, 2)19

20
If sStartType = "" Then21
'This will occur when a user right-clicks the .SCR22
'file and chooses "configure"23
sStartType = "/c"24
End If25

26
' Determine whether the screen saver should show user-definable options.27
If sStartType = "/c" Then28
Dim usercnfg As New frmcnfg29
usercnfg.ShowDialog()30

31
' Exit the application.32
Exit Sub33
End If34

35
' Determine whether the screen saver should just execute.36
If sStartType = "/s" Then37
'Check for previous instance.38
Inst = PrevInstance()39
If Not (Inst) Then40
' Create a Screen Saver form and display the form.41
Dim scrsvr As New frmscr42
scrsvr.ShowDialog()43
Else44
'If a previous instance exists, exit the application.45
Exit Sub46
End If47
End If48
End If49
End Sub50
51

52

Function PrevInstance()Function PrevInstance() As Boolean53
If UBound(Diagnostics.Process.GetProcessesByName(Diagnostics.Process.GetCurrentProcess.ProcessName)) > 0 Then54
Return True55
Else56
Return False57
End If58
End Function59

Public Function GetScaleWidth()Function GetScaleWidth(ByVal frm As Form) As Integer60

61
Dim ctl As Control62
Dim w As Integer = frm.ClientSize.Width63

64
For Each ctl In frm.Controls65
With ctl66
If .GetContainerControl() Is frm Then67
If .Dock = DockStyle.Left Or .Dock = DockStyle.Right Then68
w = w - .Size.Width69
End If70
End If71
End With72
Next73
GetScaleWidth = w - frmedge74
End Function75

76
77

78
End Module上面的东西就是屏保程序的基本框架了,窗体启动之后就是我们可以DIY的部分了,可以加个Timer做一些移动文字,图形的动作,这些都是数学的算法游戏,我们可以充分发挥自己的想象力,还可以操作音频放音乐,系统的资源应该都是可以用的。大家一起DIY吧。
浙公网安备 33010602011771号