[原创][VB.NET] 用LayeredWindow制作PNG透明窗体心得

[原创][VB.NET] 关于用GDI32.dll采用UpdateLayeredWindow制作PNG透明窗体的心得(HAVENT81/夜雨流星℡  From Www.Ai169.Com)

------------------------------------------------------------------------

前几天突然想制作一个窗体基类,所以去网上看了一下,发现了PNG透明窗体的源代码,代码的核心就是采用UpdateLayeredWindow的方法绘制窗体,测试了一下,界面非常爽,窗体的半透明效果感觉跟VistaGlass效果几乎一样。 但是随之而来的是遇到了一个非常棘手的问题,这个方法存在一个超级大BUG,就是无法可视化所有的控件,无论放什么控件,都无法显示(但是控件确实存在,只是没有绘制而已,我用TEXTBOX测试能够获取内容文本,也有区域感知,就是屏幕上看没有任何东西)。 基于这原因,本人上网找了资料,发现很多人也出现同样问题,后来研究一下System.Drawing.Graphics的功能,总算有了一点思路。 由于原来的设计就是利用单幅图片进行窗体绘制,所以在这个思路上,即最终用已经实现的SetBitmap()方法来实现窗体绘制,但是在图片输出之前用Graphics类进行图片叠加处理,来实现窗体内控件内容的叠加操作(也许这就是窗体绘制的最原始的方法,只是微软已经将绘制封装到了控件中而已),下面是简单的在原来窗体图片上加绘了一些字符串和一张图片的方法:

Dim _Image As Bitmap = My.Resources.Vista                   '最终要呈现的图片 Dim _Graphics As Graphics = Graphics.FromImage(_Image)      '建立一个图片绘制对象 Dim _Brush As New SolidBrush(Color.Black)                   '用来处理文字的画笔

Dim _Format As New StringFormat                             '文本布局信息封装对象 _Format.Alignment = StringAlignment.Center                  '垂直文本对齐方式 _Format.LineAlignment = StringAlignment.Center              '水平文本对齐方式

_Graphics.TextRenderingHint = TextRenderingHint.AntiAlias   '设置高质量模式

'在原始图层上绘制字符串 _Graphics.DrawString("HAVENT81/夜雨流星℡", New System.Drawing.Font(SystemFonts.CaptionFont.FontFamily, 120.0F, FontStyle.Bold), _Brush, CSng(((Me.Width / 2))), CSng((Me.Height / 2)), _Format)

'继续在图层之上绘制一张图片,图片来源为资源文件中的 VistaItem _Graphics.DrawImage(My.Resources.VistaItem, 10.0F, 20.0F) _Graphics.Dispose()

Me.SetBitmap(_Image, &HFF)                                  '利用前人总结的技术进行图片填充 _Image.Dispose() _Format.Dispose() 下面提供的是前人提供的SetBitmap的方法(这个方法要依托一个Win32的类,类代码在后面给出):

Public Sub SetBitmap(ByVal bitmap As Bitmap, ByVal opacity As Byte)             If (bitmap.PixelFormat <> PixelFormat.Format32bppArgb) Then                 Throw New ApplicationException("The bitmap must be 32ppp with alpha-channel.")             End If             Dim dC As IntPtr = Win32.GetDC(IntPtr.Zero)             Dim hDC As IntPtr = Win32.CreateCompatibleDC(dC)             Dim zero As IntPtr = IntPtr.Zero             Dim hObject As IntPtr = IntPtr.Zero             Try                 zero = bitmap.GetHbitmap(Color.FromArgb(0))                 hObject = Win32.SelectObject(hDC, zero)                 Dim psize As New Win32.Size(bitmap.Width, bitmap.Height)                 Dim pprSrc As New Win32.Point(0, 0)                 Dim pptDst As New Win32.Point(MyBase.Left, MyBase.Top)                 Dim pblend As New Win32.BLENDFUNCTION                 pblend.BlendOp = 0                 pblend.BlendFlags = 0                 pblend.SourceConstantAlpha = opacity                 pblend.AlphaFormat = 1                 Win32.UpdateLayeredWindow(MyBase.Handle, dC, (pptDst), (psize), hDC, (pprSrc), 0, (pblend), 2)             Finally                 Win32.ReleaseDC(IntPtr.Zero, dC)                 If (zero <> IntPtr.Zero) Then                     Win32.SelectObject(hDC, hObject)                     Win32.DeleteObject(zero)                 End If                 Win32.DeleteDC(hDC)             End Try         End Sub

接下来就是用于API交互的WIN32类:

 Friend Class Win32         ' Methods         <DllImport("gdi32.dll", SetLastError:=True, ExactSpelling:=True)> _         Public Shared Function CreateCompatibleDC(ByVal hDC As IntPtr) As IntPtr         End Function

        <DllImport("gdi32.dll", SetLastError:=True, ExactSpelling:=True)> _         Public Shared Function DeleteDC(ByVal hdc As IntPtr) As Bool         End Function

        <DllImport("gdi32.dll", SetLastError:=True, ExactSpelling:=True)> _         Public Shared Function DeleteObject(ByVal hObject As IntPtr) As Bool         End Function

        <DllImport("user32.dll", SetLastError:=True, ExactSpelling:=True)> _         Public Shared Function GetDC(ByVal hWnd As IntPtr) As IntPtr         End Function

        <DllImport("user32.dll", ExactSpelling:=True)> _         Public Shared Function ReleaseDC(ByVal hWnd As IntPtr, ByVal hDC As IntPtr) As Integer         End Function

        <DllImport("gdi32.dll", ExactSpelling:=True)> _         Public Shared Function SelectObject(ByVal hDC As IntPtr, ByVal hObject As IntPtr) As IntPtr         End Function

        <DllImport("user32.dll", SetLastError:=True, ExactSpelling:=True)> _         Public Shared Function UpdateLayeredWindow(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 Integer, ByRef pblend As BLENDFUNCTION, ByVal dwFlags As Integer) As Bool         End Function

        ' Fields         Public Const AC_SRC_ALPHA As Byte = 1         Public Const AC_SRC_OVER As Byte = 0         Public Const ULW_ALPHA As Integer = 2         Public Const ULW_COLORKEY As Integer = 1         Public Const ULW_OPAQUE As Integer = 4

        ' Nested Types         <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, Pack:=1)> _         Public Structure BLENDFUNCTION             Public BlendOp As Byte             Public BlendFlags As Byte             Public SourceConstantAlpha As Byte             Public AlphaFormat As Byte         End Structure

        Public Enum Bool             ' Fields             [False] = 0             [True] = 1         End Enum

        <StructLayout(LayoutKind.Sequential)> _         Public Structure Point             Public x As Integer             Public y As Integer             Public Sub New(ByVal x As Integer, ByVal y As Integer)                 Me.x = x                 Me.y = y             End Sub         End Structure

        <StructLayout(LayoutKind.Sequential)> _         Public Structure Size             Public cx As Integer             Public cy As Integer             Public Sub New(ByVal cx As Integer, ByVal cy As Integer)                 Me.cx = cx                 Me.cy = cy             End Sub         End Structure     End Class

以上只是提供了一个思路,有功夫的朋友可以修改这个方法,然后修改一些WINDOWS窗体控件,将它们转化成图像,统一用SetBitmap方法来进行输出,这样就等于完全自己处理控件的显示效果了,不过貌似工程量太庞大了点……  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值