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

气泡屏保

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.46/5 (10投票s)

2011 年 5 月 22 日

CPOL

2分钟阅读

viewsIcon

69445

downloadIcon

5713

这个项目展示了如何在 VB.NET 中创建类似于 Windows 7 气泡屏保。

BubbleScreenSaver/Preview.jpg

引言

很多用户都有关于为他们的项目创建屏保的问题。 许多用户希望创建与透明 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 日:首次发布
© . All rights reserved.