.NET2.0 如何使用透明PNG作为窗体背景

a913844287 2013-11-10 09:32:02
如图,我是想要是想这样的效果

但是VB.NET里面如果直接设置背景图像就会这样

TransparencyKey的方法我试过,没有效果
目前找到一个,但是有严重的BUG,就是不管窗体上面放置什么控件,运行时都完全看不见
下面是代码:AlphaForm.vb
Imports System
Imports System.Drawing
Imports System.Drawing.Imaging
Imports System.Windows.Forms
Imports System.Runtime.InteropServices

#Region "Win32 Class"
Friend Class Win32

#Region "常量"
Public Const ULW_COLORKEY As Int32 = &H1
Public Const ULW_ALPHA As Int32 = &H2
Public Const ULW_OPAQUE As Int32 = &H4
Public Const WS_EX_LAYERED As Int32 = &H80000
Public Const AC_SRC_OVER As Byte = &H0
Public Const AC_SRC_ALPHA As Byte = &H1
#End Region

#Region "枚举"
Public Enum Bool
[False] = 0
[True]
End Enum
#End Region

#Region "结构"
<StructLayout(LayoutKind.Sequential, Pack:=1)> _
Private Structure ARGB
Public Blue As Byte
Public Green As Byte
Public Red As Byte
Public Alpha As Byte
End Structure

<StructLayout(LayoutKind.Sequential)> _
Public Structure Size
Public cx As Int32
Public cy As Int32

Public Sub New(ByVal cx As Int32, ByVal cy As Int32)
Me.cx = cx
Me.cy = cy
End Sub
End Structure

<StructLayout(LayoutKind.Sequential)> _
Public Structure Point
Public x As Int32
Public y As Int32

Public Sub New(ByVal x As Int32, ByVal y As Int32)
Me.x = x
Me.y = y
End Sub
End Structure

<StructLayout(LayoutKind.Sequential, Pack:=1)> _
Public Structure BLENDFUNCTION
Public BlendOp As Byte
Public BlendFlags As Byte
Public SourceConstantAlpha As Byte
Public AlphaFormat As Byte
End Structure
#End Region

#Region "API"
'该函数检索一指定窗口的客户区域或整个屏幕的显示设备上下文环境的句柄,以后可以在GDI函数中使用该句柄来在设备上下文环境中绘图。
Public Declare Auto Function GetDC Lib "user32.dll" (ByVal hWnd As IntPtr) As IntPtr

'该函数创建一个与指定设备兼容的内存设备上下文环境(DC)。通过GetDc()获取的HDC直接与相关设备沟通,而本函数创建的DC,则是与内存中的一个表面相关联。
Public Declare Auto Function CreateCompatibleDC Lib "gdi32.dll" (ByVal hDC As IntPtr) As IntPtr

'该函数选择一对象到指定的设备上下文环境中,该新对象替换先前的相同类型的对象。
Public Declare Auto Function SelectObject Lib "gdi32.dll" (ByVal hDC As IntPtr, ByVal hObject As IntPtr) As IntPtr

'该函数更新一个分层的窗口的位置,大小,形状,内容和半透明度。
Public Declare Auto Function UpdateLayeredWindow Lib "user32.dll" (ByVal hwnd As IntPtr, ByVal hdcDst As IntPtr, ByRef pptDst As Point, ByRef psize As Size, ByVal hdcSrc As IntPtr, ByRef pprSrc As Point, ByVal crKey As Int32, ByRef pblend As BLENDFUNCTION, ByVal dwFlags As Int32) As Bool

'该函数释放设备上下文环境(DC)供其他应用程序使用。函数的效果与设备上下文环境类型有关。它只释放公用的和设备上下文环境,对于类或私有的则无效。
Public Declare Auto Function ReleaseDC Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal hDC As IntPtr) As Integer

'该函数删除一个逻辑笔、画笔、字体、位图、区域或者调色板,释放所有与该对象有关的系统资源,在对象被删除之后,指定的句柄也就失效了。
Public Declare Auto Function DeleteObject Lib "gdi32.dll" (ByVal hObject As IntPtr) As Bool

'该函数删除指定的设备上下文环境(DC)。
Public Declare Auto Function DeleteDC Lib "gdi32.dll" (ByVal hdc As IntPtr) As Bool
#End Region
End Class

#End Region

Public Class AlphaForm
Inherits Form

Public Sub SetBitmap(ByVal opacity As Byte)
Dim bmp As Bitmap = Me.BackgroundImage
If bmp.PixelFormat <> PixelFormat.Format32bppArgb Then
Throw New ApplicationException("窗体背景必须使用带Alpha通道的32位图片。")
End If

'根据图片大小设置窗体大小 www.2cto.com
Me.Size = bmp.Size

'在内存中创建与当前屏幕兼容的DC
Dim hDC1 As IntPtr = Win32.GetDC(IntPtr.Zero)
Dim hDC2 As IntPtr = Win32.CreateCompatibleDC(hDC1)
Dim hBitmap1 As IntPtr = IntPtr.Zero
Dim hBitmap2 As IntPtr = IntPtr.Zero

Try
hBitmap1 = bmp.GetHbitmap(Color.FromArgb(0))
hBitmap2 = Win32.SelectObject(hDC2, hBitmap1)

Dim blend As New Win32.BLENDFUNCTION()
With blend
.BlendOp = Win32.AC_SRC_OVER
.BlendFlags = 0
.AlphaFormat = Win32.AC_SRC_ALPHA
.SourceConstantAlpha = opacity
End With

Call Win32.UpdateLayeredWindow(Me.Handle, hDC1, New Win32.Point(Left, Top),
New Win32.Size(bmp.Width, bmp.Height), hDC2,
New Win32.Point(0, 0), 0, blend, Win32.ULW_ALPHA)

Finally
Call Win32.ReleaseDC(IntPtr.Zero, hDC1)
If hBitmap1 <> IntPtr.Zero Then
Call Win32.SelectObject(hDC2, hBitmap2)
Call Win32.DeleteObject(hBitmap1)
End If
Call Win32.DeleteDC(hDC2)
End Try
End Sub

Protected Overloads Overrides ReadOnly Property CreateParams() As CreateParams
Get
If Not DesignMode Then
Dim cp As CreateParams = MyBase.CreateParams
cp.ExStyle = cp.ExStyle Or Win32.WS_EX_LAYERED
Return cp
Else
Return MyBase.CreateParams
End If
End Get
End Property

End Class

MainForm.vb
Public Class MainForm
Inherits AlphaForm
'让窗体继承Alplaform类
Private Sub MainForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.BackgroundImage = My.Resources.alphabg
'把窗体背景设置成32位真彩色BMP或PNG
SetBitmap(255)
'传入你想设置的窗体整体透明度值(0~255)
End Sub

End Class


希望各位大大如果能解决这个BUG,或者有其他的方法实现透明窗体背景能告诉,我将感激不尽

补充:我是刚刚开始搞VB.NET的小白,那上面的AlphaForm.vb里面的代码我基本上是一句都看不懂,是网上找来的。
...全文
333 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
a913844287 2013-11-28
  • 打赏
  • 举报
回复
引用 9 楼 dylike 的回复:
关于透明PNG窗体(层窗体),系统在这种样式的窗体下不再绘制上面任何控件,甚至连窗体本身也不绘制,而DrawBP是将指定的一张图片显示出来,只能是一张图,所以有两种方法可以解决: 1 PNG做窗体底层,叠加一个使用透明色抠空只剩下控件的窗体叠加上去,显示时显示在PNG窗体的前一层(两个窗体),该方法比较落伍,不怎么推荐。 2 将所有需要显示的东西,包括控件,都绘制到PNG图片上,然后再DrapBP出这个画好的PNG图片,效果最佳,但至于控件对鼠标消息的外观改变颜色改变什么的,都要求重新绘制出大图再DrawBP。该方法视觉效果最佳,但界面响应效率会下降(当你上面的图像频繁改变重绘时)。我个人一直使用此法。
假如把控件都直接绘制到图片上,工作量很大,占用内存也很大。 另外刚才回复之前手抖了下,不小心点了“扔个板砖”,抱歉啊、。。。。
capricciosoft 2013-11-14
  • 打赏
  • 举报
回复
引用 9 楼 dylike 的回复:
关于透明PNG窗体(层窗体),系统在这种样式的窗体下不再绘制上面任何控件,甚至连窗体本身也不绘制,而DrawBP是将指定的一张图片显示出来,只能是一张图,所以有两种方法可以解决: 1 PNG做窗体底层,叠加一个使用透明色抠空只剩下控件的窗体叠加上去,显示时显示在PNG窗体的前一层(两个窗体),该方法比较落伍,不怎么推荐。 2 将所有需要显示的东西,包括控件,都绘制到PNG图片上,然后再DrapBP出这个画好的PNG图片,效果最佳,但至于控件对鼠标消息的外观改变颜色改变什么的,都要求重新绘制出大图再DrawBP。该方法视觉效果最佳,但界面响应效率会下降(当你上面的图像频繁改变重绘时)。我个人一直使用此法。
学习了.
水猿兵团五哥 2013-11-14
  • 打赏
  • 举报
回复
DY在此,我就不敢造次了
dylike 2013-11-14
  • 打赏
  • 举报
回复
关于透明PNG窗体(层窗体),系统在这种样式的窗体下不再绘制上面任何控件,甚至连窗体本身也不绘制,而DrawBP是将指定的一张图片显示出来,只能是一张图,所以有两种方法可以解决: 1 PNG做窗体底层,叠加一个使用透明色抠空只剩下控件的窗体叠加上去,显示时显示在PNG窗体的前一层(两个窗体),该方法比较落伍,不怎么推荐。 2 将所有需要显示的东西,包括控件,都绘制到PNG图片上,然后再DrapBP出这个画好的PNG图片,效果最佳,但至于控件对鼠标消息的外观改变颜色改变什么的,都要求重新绘制出大图再DrawBP。该方法视觉效果最佳,但界面响应效率会下降(当你上面的图像频繁改变重绘时)。我个人一直使用此法。
dylike 2013-11-14
  • 打赏
  • 举报
回复
要合并的话我可以帮你,QQ20353841
xxxuan 2013-11-12
  • 打赏
  • 举报
回复

这是可以的
xxxuan 2013-11-12
  • 打赏
  • 举报
回复
Opacity属性设置0.2,你试下肯定可以
capricciosoft 2013-11-12
  • 打赏
  • 举报
回复
UpdateLayeredWindow的方法得到的窗口本身是不支持显示子控件的。解决的办法通常是自绘组件,或者在上面加上子窗口(层窗口作为背景)。 用一个窗口实现的代码不知道是什么原理。你确信这个窗口还带有alpha通道的效果么?看你的图有锯齿哦。
a913844287 2013-11-12
  • 打赏
  • 举报
回复
引用 4 楼 xxxuan 的回复:
这是可以的
PNG背景是可以支持,问题是无法设置窗体整体的透明度
a913844287 2013-11-11
  • 打赏
  • 举报
回复
引用 1 楼 dylike 的回复:
http://download.csdn.net/detail/dylike/4028682
好像还是有一些问题,Me.Opacity无法设置窗体的透明度,如果用DYD.DrawBP(Me, Me.BackgroundImage, 255)来设置还是一样会导致所有控件都消失掉
a913844287 2013-11-11
  • 打赏
  • 举报
回复
引用 1 楼 dylike 的回复:
http://download.csdn.net/detail/dylike/4028682
谢谢,我试了下可以用,不过再问一个问题,我想让做出的程序是单文件的,又没有什么办法能让DYD.DLL合并进去呢?

16,555

社区成员

发帖
与我相关
我的任务
社区描述
VB技术相关讨论,主要为经典vb,即VB6.0
社区管理员
  • VB.NET
  • 水哥阿乐
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧