前一段看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-cn
frmscr
1
Imports Microsoft.Win32
2
Imports Microsoft.VisualBasic
3
Imports System.Math
4
Public Class frmscrClass frmscr
5
Inherits System.Windows.Forms.Form
6
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 Sub
18
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 Then
22
If Not (components Is Nothing) Then
23
components.Dispose()
24
End If
25
End If
26
MyBase.Dispose(disposing)
27
End Sub
28
29
'Required by the Windows Form Designer.
30
Private components As System.ComponentModel.IContainer
31
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.Label
36
Friend WithEvents Timer1 As System.Windows.Forms.Timer
37
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()Sub InitializeComponent()
38
Me.components = New System.ComponentModel.Container
39
Me.lblMessage = New System.Windows.Forms.Label
40
Me.Timer1 = New System.Windows.Forms.Timer(Me.components)
41
Me.SuspendLayout()
42
'
43
'lblMessage
44
'
45
Me.lblMessage.AutoSize = True
46
Me.lblMessage.BackColor = System.Drawing.Color.Black
47
Me.lblMessage.ForeColor = System.Drawing.Color.Yellow
48
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 = 1
52
Me.lblMessage.Text = "screen saver"
53
Me.lblMessage.TextAlign = System.Drawing.ContentAlignment.MiddleCenter
54
'
55
'Timer1
56
'
57
Me.Timer1.Enabled = True
58
'
59
'frmscr
60
'
61
Me.AutoScaleBaseSize = New System.Drawing.Size(15, 33)
62
Me.BackColor = System.Drawing.Color.Black
63
Me.ClientSize = New System.Drawing.Size(292, 273)
64
Me.ControlBox = False
65
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 = False
68
Me.MinimizeBox = False
69
Me.Name = "frmscr"
70
Me.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen
71
Me.TopMost = True
72
Me.WindowState = System.Windows.Forms.FormWindowState.Maximized
73
Me.ResumeLayout(False)
74
75
End Sub
76
77
#End Region
78
79
Private Sub frmscr_Load()Sub frmscr_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
80
81
Dim tmpLng As Integer
82
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.CurrentUser
87
pRegKey = pRegKey.OpenSubKey("Software\\Test Screen Saver")
88
Dim val As Object = pRegKey.GetValue("Message")
89
pRegKey.Close()
90
lblMessage.Text = val.ToString
91
92
'Make the cursor disappear.
93
94
Me.Cursor.Current.Hide()
95
End Sub
96
97
Private Sub frmscr_KeyDown()Sub frmscr_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyDown
98
'Immediately end when any key is pressed.
99
Me.Close()
100
End Sub
101
102
Private Sub frmscr_Activated()Sub frmscr_Activated(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Activated
103
'Center the lblMessage label to the form.
104
lblMessage.Left = GetScaleWidth(Me)
105
lblMessage.Top = (GetScaleWidth(Me) - lblMessage.Height) / 3
106
End Sub
107
108
Private Sub frmscr_Closing()Sub frmscr_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
109
'System.Windows.Forms.Cursor.Current.Show
110
''Restore the mouse cursor.
111
Dim tmplng As Integer
112
Me.Cursor.Current.Show()
113
114
tmplng = SystemParametersInfo(SPI_SCREENSAVERRUNNING, 0&, 0&, 0&)
115
End Sub
116
117
Private Sub Timer1_Tick()Sub Timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer1.Tick
118
'Determine whether the Message has moved completely off the left side of the screen.
119
If lblMessage.Left < (0 - lblMessage.Width) Then
120
lblMessage.Left = GetScaleWidth(Me) 'ScaleWidth
121
End If
122
123
'Moves lblMessage to the left.
124
lblMessage.Left = lblMessage.Left - 10
125
126
127
End Sub
128
129
Private Sub frmscr_MouseMove()Sub frmscr_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseMove
130
131
Static OldX As Integer
132
Static OldY As Integer
133
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) Then
137
Me.Close()
138
139
End If
140
141
'Assigns the current X and Y locations to OldX and OldY.
142
OldX = e.X
143
OldY = e.Y
144
145
End Sub
146
End Class
frmcnfg
1
Imports Microsoft.Win32
2
Public Class frmcnfgClass frmcnfg
3
Inherits System.Windows.Forms.Form
4
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 Sub
16
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 Then
20
If Not (components Is Nothing) Then
21
components.Dispose()
22
End If
23
End If
24
MyBase.Dispose(disposing)
25
End Sub
26
27
'Required by the Windows Form Designer.
28
Private components As System.ComponentModel.IContainer
29
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.TextBox
34
Friend WithEvents cmdcancel As System.Windows.Forms.Button
35
Friend WithEvents cmdOk As System.Windows.Forms.Button
36
Friend WithEvents label1 As System.Windows.Forms.Label
37
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()Sub InitializeComponent()
38
Me.cmdOk = New System.Windows.Forms.Button
39
Me.cmdcancel = New System.Windows.Forms.Button
40
Me.label1 = New System.Windows.Forms.Label
41
Me.txtmessage = New System.Windows.Forms.TextBox
42
Me.SuspendLayout()
43
'
44
'cmdOk
45
'
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 = 0
50
Me.cmdOk.Text = "&OK"
51
'
52
'cmdcancel
53
'
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 = 1
58
Me.cmdcancel.Text = "&Cancel"
59
'
60
'label1
61
'
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 = 2
66
Me.label1.Text = "Enter Message"
67
'
68
'txtmessage
69
'
70
Me.txtmessage.Location = New System.Drawing.Point(32, 64)
71
Me.txtmessage.Multiline = True
72
Me.txtmessage.Name = "txtmessage"
73
Me.txtmessage.Size = New System.Drawing.Size(296, 96)
74
Me.txtmessage.TabIndex = 3
75
Me.txtmessage.Text = ""
76
'
77
'frmcnfg
78
'
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 Sub
90
91
#End Region
92
93
94
Private Sub cmdcancel_Click()Sub cmdcancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdcancel.Click
95
Me.Close()
96
End Sub
97
98
Private Sub cmdOk_Click()Sub cmdOk_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdOk.Click
99
'Save the current settings to
100
'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 Sub
110
End Class
Module1
1
Imports System.Runtime.InteropServices
2
Imports System.Environment
3
4
Module Module1Module Module1
5
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 Boolean
7
Public Const SPI_SCREENSAVERRUNNING = 97&
8
Public Const frmedge As Integer = 4
9
Public nMouseMoves&
10
Dim sStartType
11
12
13
Public Sub Main()Sub Main(ByVal args As String())
14
Dim Inst As Boolean = False
15
16
17
If args.Length > 0 Then
18
sStartType = args(0).ToLower.Trim().Substring(0, 2)
19
20
If sStartType = "" Then
21
'This will occur when a user right-clicks the .SCR
22
'file and chooses "configure"
23
sStartType = "/c"
24
End If
25
26
' Determine whether the screen saver should show user-definable options.
27
If sStartType = "/c" Then
28
Dim usercnfg As New frmcnfg
29
usercnfg.ShowDialog()
30
31
' Exit the application.
32
Exit Sub
33
End If
34
35
' Determine whether the screen saver should just execute.
36
If sStartType = "/s" Then
37
'Check for previous instance.
38
Inst = PrevInstance()
39
If Not (Inst) Then
40
' Create a Screen Saver form and display the form.
41
Dim scrsvr As New frmscr
42
scrsvr.ShowDialog()
43
Else
44
'If a previous instance exists, exit the application.
45
Exit Sub
46
End If
47
End If
48
End If
49
End Sub
50
51
52
Function PrevInstance()Function PrevInstance() As Boolean
53
If UBound(Diagnostics.Process.GetProcessesByName(Diagnostics.Process.GetCurrentProcess.ProcessName)) > 0 Then
54
Return True
55
Else
56
Return False
57
End If
58
End Function
59
Public Function GetScaleWidth()Function GetScaleWidth(ByVal frm As Form) As Integer
60
61
Dim ctl As Control
62
Dim w As Integer = frm.ClientSize.Width
63
64
For Each ctl In frm.Controls
65
With ctl
66
If .GetContainerControl() Is frm Then
67
If .Dock = DockStyle.Left Or .Dock = DockStyle.Right Then
68
w = w - .Size.Width
69
End If
70
End If
71
End With
72
Next
73
GetScaleWidth = w - frmedge
74
End Function
75
76
77
78
End Module
上面的
东
西就是屏保程序的基本框架了,窗体启
动
之后就是我
们
可以DIY的部分了,可以加个Timer做一些移
动
文字,
图
形的
动
作,
这
些都是数学的算法游
戏
,我
们
可以充分
发挥
自己的想象力,
还
可以操作音
频
放音
乐
,系
统
的
资
源
应该
都是可以用的
。
大家一起
DIY
吧。