感谢原作者:
'************************VB版本云效果***********************
'**作者: laviewpbt
'**QQ: 33184777
'**********************************************************
直接先上图:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
移植难点总结如下:
原代码
'iRet = GetDIBits(hmemDC,xxx,m_Height,pOldPixel,BmpInfo,DIB_RGB_COLORS) 'iRet = GetDIBits(hmemDC,pPixel,DIB_RGB_COLORS)工作不正常. 找不到原因. 用如下代替:
myBitmap = New Bitmap(Me.Image.Image) ... For i As Integer = 0 To m_Height - 1 For j As Integer = 0 To m_Width - 1 OldPixel(i * m_Width + j) = myBitmap.GetPixel(j,i).ToArgb And &HFFFFFFFF dispPixel(i * m_Width + j) = myBitmap.GetPixel(j,i).ToArgb And &HFFFFFFFF Next Next
2,内存数据复制部分
原代码
CopyMemory(Pixel(0),OldPixel(0),m_Width * m_Height * 4)改为
pPixel = System.Runtime.InteropServices.Marshal.UnsafeAddrOfPinnedArrayElement(dispPixel,0) ... Dim r As New Rectangle(0,m_Width,m_Height) Dim bmpData As Drawing.Imaging.BitmapData bmpData = myBitmap.LockBits(r,Drawing.Imaging.ImageLockMode.ReadOnly,Drawing.Imaging.PixelFormat.Format32bppArgb) myBitmap.UnlockBits(bmpData) CopyMemory(pPixel,bmpData.Scan0(),m_Width * m_Height * 4)
3,PictureBox绘图
原代码不工作.
<pre name="code" class="vb"> SetDIBitsToDevice(Me.hdc,DIB_RGB_COLORS)改为单像素填充
<pre name="code" class="vb"> pos = Y * m_Width + X<pre name="code" class="vb"> wR = (dispPixel(pos) And &HFF0000) >> 16wG = (dispPixel(pos) And &HFF00) >> 8
wB = dispPixel(pos) And &HFF
...
<pre name="code" class="vb"> myBitmap.SetPixel(X,Y,pixelColor)Me.Image.Image = myBitmap
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
代码:
' ' Form1.vb ' ' divilis # qq . com ' Imports System.Math Public Class Form1 Private hdc As Long Private myOldBitmap As Bitmap Private myBitmap As Bitmap Private Sub Form1_Click(ByVal sender As Object,ByVal e As System.EventArgs) Handles Me.Click If Timer1.Enabled Or Timer2.Enabled Then Timer1.Enabled = False Timer2.Enabled = False Else Timer1.Enabled = True Timer2.Enabled = True End If End Sub Private Sub Form_DblClick() Handles Me.DoubleClick Me.Close() End Sub Private Sub Form_Load() Handles Me.Load myBitmap = New Bitmap(Me.Image.Image) m_Width = myBitmap.Width m_Height = myBitmap.Height DoubleHeight = m_Height * 2 With BmpInfo.bmiHeader .biSize = Len(BmpInfo.bmiHeader) .biWidth = m_Width .biHeight = m_Height .biPlanes = 1 .biBitCount = 32 .biCompression = BI_RGB End With ReDim OldPixel(3 * m_Width * m_Height - 1) ReDim dispPixel(3 * m_Width * m_Height - 1) ReDim WaveHeight(3 * m_Width * m_Height * 2 - 1) myOldBitmap = myBitmap.Clone() End Sub Private Sub DropWater(ByVal X As Long,ByVal Y As Long,ByVal Radius As Long,ByVal Height As Long) Dim Distance As Long Dim XX As Long Dim YY As Long Dim I As Long Dim J As Long Dim Ratio As Double Ratio = PI / Radius For I = -Radius To Radius For J = -Radius To Radius XX = X + I YY = Y + J If XX >= 0 And XX < m_Width And YY >= 0 And YY < m_Height Then Distance = Sqrt(I * I + J * J) If Distance <= Radius Then WaveHeight(XX * m_Height * 2 + YY * 2 + CurrentHeightBuffer) = Height * Cos(Distance * Ratio) End If End If Next Next End Sub Private Sub PaintWater() Dim TimeUse As Long Dim OffsetX As Long Dim OffsetY As Long Dim X As Long Dim Y As Long Dim Speed As Long Dim Fast As Long TimeUse = GetTickCount NewHeightBuffer = (CurrentHeightBuffer + 1) Mod 2 Dim pPixel As System.IntPtr Dim pOldPixel As System.IntPtr Dim wB,wR,wG As Short Dim pixelColor As Color 'Dim pixelColorInteger As Integer Dim pos As Integer pPixel = System.Runtime.InteropServices.Marshal.UnsafeAddrOfPinnedArrayElement(dispPixel,0) pOldPixel = System.Runtime.InteropServices.Marshal.UnsafeAddrOfPinnedArrayElement(OldPixel,0) myBitmap = myOldBitmap.Clone() 'For i As Integer = 0 To m_Height - 1 ' For j As Integer = 0 To m_Width - 1 ' OldPixel(i * m_Width + j) = myBitmap.GetPixel(j,i).ToArgb And &HFFFFFFFF ' dispPixel(i * m_Width + j) = myBitmap.GetPixel(j,i).ToArgb And &HFFFFFFFF ' Next 'Next Dim r As New Rectangle(0,m_Width * m_Height * 4) For X = 1 To m_Width - 2 For Y = 1 To m_Height - 2 Speed = X * DoubleHeight + Y * 2 + NewHeightBuffer Fast = X * DoubleHeight + Y * 2 + CurrentHeightBuffer WaveHeight(Speed) = _ (WaveHeight(Fast - DoubleHeight) + _ WaveHeight(Fast - DoubleHeight - 2) + _ WaveHeight(Fast - 2) + _ WaveHeight(Fast + DoubleHeight - 2) + _ WaveHeight(Fast + DoubleHeight) + _ WaveHeight(Fast + DoubleHeight + 2) + _ WaveHeight(Fast + 2) + _ WaveHeight(Fast - DoubleHeight + 2)) \ 4 - _ WaveHeight(Speed) WaveHeight(Speed) = WaveHeight(Speed) - WaveHeight(Speed) \ 32 OffsetX = (WaveHeight(Speed - DoubleHeight) - WaveHeight(Speed + DoubleHeight)) \ 16 OffsetY = (WaveHeight(Speed - 2) - WaveHeight(Speed + 2)) \ 16 If OffsetX <> 0 And OffsetY <> 0 Then If X + OffsetX <= 0 Then OffsetX = -X ElseIf X + OffsetX >= m_Width - 1 Then OffsetX = m_Width - X - 1 End If If Y + OffsetY <= 0 Then OffsetY = -Y ElseIf Y + OffsetY >= m_Height - 1 Then OffsetY = m_Height - Y - 1 End If dispPixel(X + Y * m_Width) = OldPixel(X + OffsetX + (Y + OffsetY) * m_Width) pos = Y * m_Width + X wR = (dispPixel(pos) And &HFF0000) >> 16 wG = (dispPixel(pos) And &HFF00) >> 8 wB = dispPixel(pos) And &HFF 'pixelColorInteger = dispPixel(Y * m_Width + X) 'pixelColor = Color.FromArgb(pixelColorInteger) pixelColor = Color.FromArgb(wR,wG,wB) myBitmap.SetPixel(X,pixelColor) End If Next Next CurrentHeightBuffer = NewHeightBuffer 'For i As Integer = 0 To m_Height - 1 ' For j As Integer = 0 To m_Width - 1 ' Next 'Next 'SetDIBitsToDevice(Me.hdc,DIB_RGB_COLORS) Me.Image.Image = myBitmap Me.Text = "water drop,frame delay: " + CStr((GetTickCount - TimeUse)) End Sub Private Sub CreateWaterDrops() Dim I As Long Dim DropX As Long Dim DropY As Long Dim DropRadius As Long Dim Height As Long Dim Percent As Long Percent = 0.0015 * (m_Width + m_Height) For I = 0 To 99 DropX = Rnd() * m_Width DropY = Rnd() * m_Height Height = Rnd() * 400 DropRadius = Rnd() * 4 * Percent If DropRadius < 4 Then DropRadius = 4 Drops(I).X = DropX Drops(I).Y = DropY Drops(I).Height = Height Drops(I).Radius = DropRadius Next End Sub Private Sub Timer1_Timer() Handles Timer1.Tick Dim I As Long Dim Percent As Long Dim DropsNumber As Long Dim Index As Long Percent = 0.005 * (m_Width + m_Height) DropsNumber = Rnd() * Percent For I = 0 To DropsNumber - 1 Index = Rnd() * 99 DropWater(Drops(Index).X,Drops(Index).Y,Drops(Index).Radius,Drops(Index).Height) Next End Sub Private Sub Timer2_Timer() Handles Timer2.Tick PaintWater() End Sub Private Sub Form1_Shown(ByVal sender As Object,ByVal e As System.EventArgs) Handles Me.Shown 'Me.Text = "water drop:" 'hdc = GetDC(FindWindow(Nothing,"water drop")) hdc = Me.Image.CreateGraphics().GetHdc() Dim pHbitmap As Long Dim pOldHbitmap As Long Dim pOldPixel As Long Dim pPixel As Long Dim hmemDC As Long Dim iRet As Long = -1 pOldPixel = System.Runtime.InteropServices.Marshal.UnsafeAddrOfPinnedArrayElement(OldPixel,0) pPixel = System.Runtime.InteropServices.Marshal.UnsafeAddrOfPinnedArrayElement(dispPixel,0) hmemDC = CreateCompatibleDC(hdc) pHbitmap = CreateCompatibleBitmap(hdc,m_Height) pOldHbitmap = SelectObject(hmemDC,pHbitmap) pHbitmap = SelectObject(hdc,pOldHbitmap) BitBlt(hmemDC,hdc,&HCC0020) For i As Integer = 0 To m_Height - 1 For j As Integer = 0 To m_Width - 1 OldPixel(i * m_Width + j) = myBitmap.GetPixel(j,i).ToArgb And &HFFFFFFFF Next Next 'Dim xxx As Long 'xxx = myBitmap.GetHbitmap 'iRet = GetDIBits(hmemDC,DIB_RGB_COLORS) Randomize() CreateWaterDrops() End Sub End Class
' ' Module1.vb ' ' divilis # qq . com ' Module Module1 Structure POINTAPI Public X As Long Public Y As Long End Structure Public Declare Function GetTickCount Lib "kernel32" () As Long Structure RGBQUAD '只有bibitcount为1,2,4时才有调色板 Public Blue As Byte '蓝色分量 Public Green As Byte '绿色分量 Public Red As Byte '红色分量 Public Reserved As Byte '保留值 End Structure Structure BITMAPINFOHEADER '40 bytes Public biSize As Long 'BITMAPINFOHEADER结构的大小 Public biWidth As Long Public biHeight As Long Public biPlanes As Integer '设备的为平面数,现在都是1 Public biBitCount As Integer '图像的颜色位图 Public biCompression As Long '压缩方式 Public biSizeImage As Long '实际的位图数据所占字节 Public biXPelsPerMeter As Long '目标设备的水平分辨率 Public biYPelsPerMeter As Long '目标设备的垂直分辨率 Public biClrUsed As Long '使用的颜色数 Public biClrImportant As Long '重要的颜色数。如果该项为0,表示所有颜色都是重要的 End Structure Structure BITMAPINFO Public bmiHeader As BITMAPINFOHEADER Public bmiColors As RGBQUAD End Structure Structure RECT Public Left As Long Public Top As Long Public Right As Long Public Bottom As Long End Structure ' Structure DropData Public X As Long Public Y As Long Public Radius As Long Public Height As Long End Structure Public Declare Function GetDIBits Lib "gdi32" (ByVal aHDC As Long,ByVal hBitmap As Long,ByVal nStartScan As Long,ByVal nNumScans As Long,ByVal lpBits As Long,ByVal lpBI As BITMAPINFO,ByVal wUsage As Long) As Long Public Declare Function SetDIBitsToDevice Lib "gdi32" (ByVal hdc As Long,ByVal X As Long,ByVal dx As Long,ByVal dy As Long,ByVal SrcX As Long,ByVal SrcY As Long,ByVal Scan As Long,ByVal NumScans As Long,ByVal Bits As Long,ByVal BitsInfo As BITMAPINFO,ByVal wUsage As Long) As Long Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) Public Declare Function SetDIBits Lib "gdi32" (ByVal hdc As Long,ByVal wUsage As Long) As Long Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByVal Destination As System.IntPtr,ByVal Source As System.IntPtr,ByVal Length As Long) Declare Function GetLastError Lib "kernel32" Alias "GetLastError" () As Long Public Const DIB_RGB_COLORS = 0& Public Const BI_RGB = 0& Public Const PI As Double = 3.1415926 Public m_Width As Long Public m_Height As Long Public OldPixel() As Long Public dispPixel() As Long Public WaveHeight() As Long Public CurrentHeightBuffer As Long Public NewHeightBuffer As Long Public Drops(99) As DropData Public DoubleHeight As Long Public BmpInfo As BITMAPINFO Declare Function GetDC Lib "user32" Alias "GetDC" (ByVal hwnd As Long) As Long Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String,ByVal lpWindowName As String) As Long Declare Function MoveToEx Lib "gdi32" Alias "MoveToEx" (ByVal hdc As Long,ByVal x As Long,ByVal y As Long,ByVal lpPoint As POINTAPI) As Long Declare Function LineTo Lib "gdi32" Alias "LineTo" (ByVal hdc As Long,ByVal y As Long) As Long Declare Function SelectObject Lib "gdi32" Alias "SelectObject" (ByVal hdc As Long,ByVal hObject As Long) As Long Declare Function CreateCompatibleBitmap Lib "gdi32" Alias "CreateCompatibleBitmap" (ByVal hdc As Long,ByVal nWidth As Long,ByVal nHeight As Long) As Long Declare Function CreateCompatibleDC Lib "gdi32" Alias "CreateCompatibleDC" (ByVal hdc As Long) As Long Declare Function BitBlt Lib "gdi32" Alias "BitBlt" (ByVal hDestDC As Long,ByVal nHeight As Long,ByVal hSrcDC As Long,ByVal xSrc As Long,ByVal ySrc As Long,ByVal dwRop As Long) As Long 'Declare Function WNetConnectionDialog Lib "mpr.dll" Alias "WNetConnectionDialog" (ByVal hwnd As Long,ByVal dwType As Long) As Long End Module
附上原代码:
VERSION 5.00 Begin VB.Form FrmWater BackColor = &H00C0FFC0& BorderStyle = 3 'Fixed Dialog Caption = "水波" ClientHeight = 6030 ClientLeft = 45 ClientTop = 435 ClientWidth = 8070 FillColor = &H00FFFFFF& BeginProperty Font Name = "宋体" Size = 12 Charset = 134 Weight = 400 Underline = 0 'False Italic = 0 'False Strikethrough = 0 'False EndProperty Icon = "FrmWater.frx":0000 LinkTopic = "Form1" MaxButton = 0 'False MinButton = 0 'False Picture = "FrmWater.frx":08CA ScaleHeight = 402 ScaleMode = 3 'Pixel ScaleWidth = 538 ShowInTaskbar = 0 'False StartUpPosition = 2 '屏幕中心 Begin VB.Timer Timer2 Interval = 50 Left = 2760 Top = 3000 End Begin VB.Timer Timer1 Interval = 45 Left = 2160 Top = 3000 End End Attribute VB_Name = "FrmWater" Attribute VB_GlobalNameSpace = False Attribute VB_Creatable = False Attribute VB_PredeclaredId = True Attribute VB_Exposed = False Option Explicit Private Type POINTAPI X As Long Y As Long End Type Private Declare Function GetTickCount Lib "kernel32" () As Long Private Type RGBQUAD '只有bibitcount为1,2,4时才有调色板 Blue As Byte '蓝色分量 Green As Byte '绿色分量 Red As Byte '红色分量 Reserved As Byte '保留值 End Type Private Type BITMAPINFOHEADER '40 bytes biSize As Long 'BITMAPINFOHEADER结构的大小 biWidth As Long biHeight As Long biPlanes As Integer '设备的为平面数,现在都是1 biBitCount As Integer '图像的颜色位图 biCompression As Long '压缩方式 biSizeImage As Long '实际的位图数据所占字节 biXPelsPerMeter As Long '目标设备的水平分辨率 biYPelsPerMeter As Long '目标设备的垂直分辨率 biClrUsed As Long '使用的颜色数 biClrImportant As Long '重要的颜色数。如果该项为0,表示所有颜色都是重要的 End Type Private Type BITMAPINFO bmiHeader As BITMAPINFOHEADER bmiColors As RGBQUAD End Type Private Type RECT Left As Long Top As Long Right As Long Bottom As Long End Type ' Private Type DropData X As Long Y As Long Radius As Long Height As Long End Type Private Declare Function GetDIBits Lib "gdi32" (ByVal aHDC As Long,lpBits As Any,lpBI As BITMAPINFO,ByVal wUsage As Long) As Long Private Declare Function SetDIBitsToDevice Lib "gdi32" (ByVal hdc As Long,Bits As Any,BitsInfo As BITMAPINFO,ByVal wUsage As Long) As Long Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) Private Declare Function SetDIBits Lib "gdi32" (ByVal hdc As Long,ByVal wUsage As Long) As Long Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any,Source As Any,ByVal Length As Long) Private Const DIB_RGB_COLORS = 0& Private Const BI_RGB = 0& Private Const PI As Double = 3.1415926 Private m_Width As Long Private m_Height As Long Private OldPixel() As Long Private Pixel() As Long Private WaveHeight() As Long Private CurrentHeightBuffer As Long Private NewHeightBuffer As Long Private Drops(99) As DropData Private DoubleHeight As Long Private BmpInfo As BITMAPINFO '************************VB版本云效果*********************** '**作者: laviewpbt '**QQ: 33184777 '*********************************************************** Private Sub Form_DblClick() Unload Me End Sub Private Sub Form_Load() m_Width = Me.ScaleWidth m_Height = Me.ScaleHeight DoubleHeight = m_Height * 2 With BmpInfo.bmiHeader .biSize = Len(BmpInfo.bmiHeader) .biWidth = m_Width .biHeight = m_Height .biPlanes = 1 .biBitCount = 32 .biCompression = BI_RGB End With ReDim OldPixel(m_Width * m_Height - 1) As Long ReDim Pixel(m_Width * m_Height - 1) As Long ReDim WaveHeight(m_Width * m_Height * 2 - 1) As Long GetDIBits Me.hdc,Me.Image.Handle,DIB_RGB_COLORS GetDIBits Me.hdc,Pixel(0),DIB_RGB_COLORS Randomize CreateWaterDrops End Sub Private Sub DropWater(X As Long,Y As Long,Radius As Long,Height As Long) Dim Distance As Long Dim XX As Long Dim YY As Long Dim I As Long Dim J As Long Dim Ratio As Double Ratio = PI / Radius For I = -Radius To Radius For J = -Radius To Radius XX = X + I YY = Y + J If XX >= 0 And XX < m_Width And YY >= 0 And YY < m_Height Then Distance = Sqr(I * I + J * J) If Distance <= Radius Then WaveHeight(XX * m_Height * 2 + YY * 2 + CurrentHeightBuffer) = Height * Cos(Distance * Ratio) End If End If Next Next End Sub '************************VB版本水波效果*********************** '**作者: laviewpbt '**QQ: 33184777 '*********************************************************** Private Sub PaintWater() Dim TimeUse As Long Dim OffsetX As Long Dim OffsetY As Long Dim X As Long Dim Y As Long Dim Speed As Long Dim Fast As Long TimeUse = GetTickCount NewHeightBuffer = (CurrentHeightBuffer + 1) Mod 2 CopyMemory Pixel(0),m_Width * m_Height * 4 For X = 1 To m_Width - 2 For Y = 1 To m_Height - 2 Speed = X * DoubleHeight + Y * 2 + NewHeightBuffer Fast = X * DoubleHeight + Y * 2 + CurrentHeightBuffer WaveHeight(Speed) = _ (WaveHeight(Fast - DoubleHeight) + _ WaveHeight(Fast - DoubleHeight - 2) + _ WaveHeight(Fast - 2) + _ WaveHeight(Fast + DoubleHeight - 2) + _ WaveHeight(Fast + DoubleHeight) + _ WaveHeight(Fast + DoubleHeight + 2) + _ WaveHeight(Fast + 2) + _ WaveHeight(Fast - DoubleHeight + 2)) \ 4 - _ WaveHeight(Speed) WaveHeight(Speed) = WaveHeight(Speed) - WaveHeight(Speed) \ 32 OffsetX = (WaveHeight(Speed - DoubleHeight) - WaveHeight(Speed + DoubleHeight)) \ 16 OffsetY = (WaveHeight(Speed - 2) - WaveHeight(Speed + 2)) \ 16 If OffsetX <> 0 And OffsetY <> 0 Then If X + OffsetX <= 0 Then OffsetX = -X ElseIf X + OffsetX >= m_Width - 1 Then OffsetX = m_Width - X - 1 End If If Y + OffsetY <= 0 Then OffsetY = -Y ElseIf Y + OffsetY >= m_Height - 1 Then OffsetY = m_Height - Y - 1 End If Pixel(X + Y * m_Width) = OldPixel(X + OffsetX + (Y + OffsetY) * m_Width) End If Next Next CurrentHeightBuffer = NewHeightBuffer SetDIBitsToDevice Me.hdc,DIB_RGB_COLORS Me.Caption = GetTickCount - TimeUse End Sub Private Sub CreateWaterDrops() Dim I As Long Dim DropX As Long Dim DropY As Long Dim DropRadius As Long Dim Height As Long Dim Percent As Long Percent = 0.0015 * (m_Width + m_Height) For I = 0 To 99 DropX = Rnd * m_Width DropY = Rnd * m_Height Height = Rnd * 400 DropRadius = Rnd * 4 * Percent If DropRadius < 4 Then DropRadius = 4 Drops(I).X = DropX Drops(I).Y = DropY Drops(I).Height = Height Drops(I).Radius = DropRadius Next End Sub Private Sub Timer1_Timer() Dim I As Long Dim Percent As Long Dim DropsNumber As Long Dim Index As Long Percent = 0.005 * (m_Width + m_Height) DropsNumber = Rnd * Percent For I = 0 To DropsNumber - 1 Index = Rnd * 99 DropWater Drops(Index).X,Drops(Index).Height Next End Sub Private Sub Timer2_Timer() PaintWater End Sub