气泡屏保






3.46/5 (10投票s)
这个项目展示了如何在 VB.NET 中创建类似于 Windows 7 气泡屏保。
引言
很多用户都有关于为他们的项目创建屏保的问题。 许多用户希望创建与透明 PNG、GIF 等形状相同的启动画面。 这个项目是一个 Windows 7 气泡屏保。 用户也可以使用这段代码来制作透明窗体。
背景
之前,我尝试过创建类似于 Windows 7 超级工具栏的超级工具栏。 那时我得到了使窗体透明的代码。 然后,我决定使用这段代码创建这个令人惊叹的屏保。
Using the Code
首先,我将讨论如何创建一个透明窗体。 我使用了 CodePlex 上的 Sbar
中的 PerPixelFrom
库来创建透明窗体。
PerPixelAlphaForm.vb
Imports System.Windows.Forms
Imports system.Runtime.InteropServices
Imports Screen_Saver.Win32
Public Class PerPixelAlphaForm
Inherits Form
Public StartLeft As Integer
Public StartTop As Integer
Public Ang As Double
Public WithEvents tim As New Timer
' Methods
Public Sub New()
MyBase.FormBorderStyle = Windows.Forms.FormBorderStyle.None
MyBase.ShowInTaskbar = False
End Sub
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
MyBase.Dispose(disposing)
GC.Collect()
GC.WaitForPendingFinalizers()
End Sub
Public Sub SetBitmap(ByVal bitmap As Bitmap)
Me.SetBitmap(bitmap, &HFF)
GC.Collect()
GC.WaitForPendingFinalizers()
End Sub
Public Sub SetBitmap(ByVal bitmap As Bitmap, ByVal opacity As Byte)
If (bitmap.PixelFormat <> Imaging.PixelFormat.Format32bppArgb) Then
Throw New ApplicationException("The bitmap must be 32ppp with alpha-channel.")
End If
Dim screenDc As IntPtr = Win32.GetDC(IntPtr.Zero)
Dim memDc As IntPtr = Win32.CreateCompatibleDC(screenDc)
Dim hBitmap As IntPtr = IntPtr.Zero
Dim oldBitmap As IntPtr = IntPtr.Zero
Try
hBitmap = bitmap.GetHbitmap(Color.FromArgb(0))
oldBitmap = Win32.SelectObject(memDc, hBitmap)
Dim size As New Size(bitmap.Width, bitmap.Height)
Dim pointSource As New Point(0, 0)
Dim topPos As New Point(MyBase.Left, MyBase.Top)
Dim blend As New BLENDFUNCTION
blend.BlendOp = 0
blend.BlendFlags = 0
blend.SourceConstantAlpha = opacity
blend.AlphaFormat = 1
Win32.UpdateLayeredWindow(MyBase.Handle, screenDc, (topPos), _
(size), memDc, (pointSource), 0, (blend), 2)
Finally
Win32.ReleaseDC(IntPtr.Zero, screenDc)
If (hBitmap <> IntPtr.Zero) Then
Win32.SelectObject(memDc, oldBitmap)
Win32.DeleteObject(hBitmap)
End If
Win32.DeleteDC(memDc)
Win32.DeleteDC(screenDc)
Win32.DeleteObject(oldBitmap)
Win32.DeleteObject(screenDc)
Win32.DeleteObject(memDc)
GC.Collect()
GC.WaitForPendingFinalizers()
End Try
End Sub
' Properties
Protected Overrides ReadOnly Property CreateParams() As CreateParams
Get
Dim cp As CreateParams = MyBase.CreateParams
cp.ExStyle = (cp.ExStyle Or &H80000)
cp.ExStyle = (cp.ExStyle Or &H80)
Return cp
End Get
End Property
End Class
对于任何窗体,我们可以使用这段代码使其透明
Dim frm As New PerPixelAlphaForm
frm.SetBitmap(My.Resources.Blue)
frm.Show()
这段代码使 frm
(Form
) 像蓝色的气泡图像一样透明(如上图所示)。
现在我们将讨论如何显示不同颜色的气泡。 我使用了不同的图像来显示不同颜色的气泡。
首先,我定义了一个随机数。 然后根据它,我们可以为气泡设置不同的图像。 当 Timer1
触发时,会生成一个随机数,并且会冒出一个气泡。 我将它们结合起来,在 timer1_tick
代码中关闭光标移动时的屏保。
Timer1_tick
Private Sub Timer1_Tick(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Timer1.Tick
If MposL <> System.Windows.Forms.Cursor.Position.X Or _
MposT <> System.Windows.Forms.Cursor.Position.Y Then
Timer1.Enabled = False
Me.Close()
Exit Sub
End If
k = New PerPixelAlphaForm
Dim a As New System.Random
Select Case a.NextDouble
Case Is < 0.1
k.SetBitmap(My.Resources.Blue)
Case Is < 0.2
k.SetBitmap(My.Resources.Green)
Case Is < 0.3
k.SetBitmap(My.Resources.Orange)
Case Is < 0.4
k.SetBitmap(My.Resources.Other1)
Case Is < 0.5
k.SetBitmap(My.Resources.Other2)
Case Is < 0.6
k.SetBitmap(My.Resources.Pink)
Case Is < 0.7
k.SetBitmap(My.Resources.Red)
Case Is < 0.8
k.SetBitmap(My.Resources.Violate)
Case Else
k.SetBitmap(My.Resources.Yellow)
End Select
If TotalBub < txtBubbles.Text Then
k.Ang = 1.57 * a.NextDouble
k.Show()
TotalBub += 1
End If
k = Nothing
End Sub
现在难点是如何将气泡发送到不同的方向,并在它们与屏幕边缘碰撞时让它们返回。 再次,我使用了一个随机数和一些数学函数将它们发送到不同的角度,并且当位置超出屏幕宽度时,它们会朝其他方向移动。 我在 PerPixelAlphaForm.vb 中添加了一个 Timer
来获取位置和角度。
在 PerPixelAlphaForm.vb 中编辑
Private Sub Timer1_Tick(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles tim.Tick
If Me.Left < 0 Or Me.Top < 0 Or Me.Left > _
Screen.PrimaryScreen.WorkingArea.Width - _
185 Or Me.Top > Screen.PrimaryScreen.WorkingArea.Height - 185 Then
Ang += 1.57 * Date.Now.Millisecond / 1000
If Me.Left < 0 Then Me.Left = 0
If Me.Top < 0 Then Me.Top = 0
If Me.Right > Screen.PrimaryScreen.WorkingArea.Width Then Me.Left = _
Screen.PrimaryScreen.WorkingArea.Width - 185
If Me.Bottom > Screen.PrimaryScreen.WorkingArea.Height Then Me.Top = _
Screen.PrimaryScreen.WorkingArea.Height - 185
Else
Me.Left += Math.Cos(Ang) * 10
Me.Top -= Math.Sin(Ang) * 10
End If
End Sub
我将 timer1.interval
设置为 2
,以便在气泡加载时提供速度和真实感。
Private Sub PerPixelAlphaForm_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
tim.Enabled = True
tim.Interval = 2
Me.Top = Screen.PrimaryScreen.WorkingArea.Height - 200
Me.Left = 0
End Sub
历史
- 2011 年 5 月 22 日:首次发布