做过.NET Winform窗体美化的人应该都很熟悉UpdateLayeredWindow吧,UpdateLayeredWindow可以实现窗体的任意透明,效果很好,不会有毛边。不过使用这个API之后,会有一个问题就是无法使用普通控件,而且没有Paint消息。为了解决这个问题,有两种方法。

一、使用双层窗体,底层窗体使用UpdateLayeredWindow作为背景,上层窗体用普通窗体,并且可以使用TransparencyKey或者Region来实现去除不需要的窗体内容,让上层窗体能看到底层的窗体。

二、直接单层窗体,使用控件的DrawToBitmap把控件图像绘制到UpdateLayeredWindow的窗体上,这样就可以看到普通控件了。不过这个也有问题:1.控件内容不能自动更新  2.效率低,很多控件使用DrawToBitmap绘制出的图像不完整,甚至绘制不出图像。比如TextBox无法显示光标,WebBrowser无法显示内容。

三、采用DirectUI技术,重写所有基础控件。效果最好,不过工作量巨大。

使用UpdateLayeredWindow时,一般是需要对Bitmap缓存起来,通过设置剪辑区域,局部重绘来提高效率。另外还可以异步重绘,模拟Winform的失效到重绘。

有些人会说为什么不直接用WPF啊,Wpf和Winform各有优缺点,适应不同的场合。Winform相对于使用更简单一些,系统要求更低。当然需要看人的习惯了和擅长的。

UpdateLayeredWindow 基本使用方法:

重写窗体的 CreateParams 属性

protected   override  CreateParams CreateParams
{
get
{
CreateParams cp = base .CreateParams;
cp.ExStyle |= 0x00080000 ; // WS_EX_LAYERED 扩展样式
return cp;
}
}

  

API调用:

          public   void  SetBitmap(Bitmap bitmap,  byte  opacity)
{
if (bitmap.PixelFormat != PixelFormat.Format32bppArgb)
throw new ApplicationException( "位图必须是32位包含alpha 通道" ); IntPtr screenDc = Win32.GetDC(IntPtr.Zero);
IntPtr memDc = Win32.CreateCompatibleDC(screenDc);
IntPtr hBitmap = IntPtr.Zero;
IntPtr oldBitmap = IntPtr.Zero; try
{
hBitmap = bitmap.GetHbitmap(Color.FromArgb( 0 )); // 创建GDI位图句柄,效率较低
oldBitmap = Win32.SelectObject(memDc, hBitmap); Win32.Size size = new Win32.Size(bitmap.Width, bitmap.Height);
Win32.Point pointSource = new Win32.Point( 0 , 0 );
Win32.Point topPos = new Win32.Point(Left, Top);
Win32.BLENDFUNCTION blend = new Win32.BLENDFUNCTION();
blend.BlendOp = Win32.AC_SRC_OVER;
blend.BlendFlags = 0 ;
blend.SourceConstantAlpha = opacity;
blend.AlphaFormat = Win32.AC_SRC_ALPHA; Win32.UpdateLayeredWindow(Handle, screenDc, ref topPos, ref size, memDc, ref pointSource, 0 , ref blend, Win32.ULW_ALPHA);
}
finally
{
Win32.ReleaseDC(IntPtr.Zero, screenDc);
if (hBitmap != IntPtr.Zero)
{
Win32.SelectObject(memDc, oldBitmap); Win32.DeleteObject(hBitmap);
}
Win32.DeleteDC(memDc);
}
}

  

API声明:

      class  Win32
{
public enum Bool
{
False = 0 ,
True
} ; [StructLayout(LayoutKind.Sequential)]
public struct Point
{
public Int32 x;
public Int32 y; public Point(Int32 x, Int32 y)
{ this .x = x; this .y = y; }
} [StructLayout(LayoutKind.Sequential)]
public struct Size
{
public Int32 cx;
public Int32 cy; public Size(Int32 cx, Int32 cy)
{ this .cx = cx; this .cy = cy; }
} [StructLayout(LayoutKind.Sequential, Pack = 1 )]
struct ARGB
{
public byte Blue;
public byte Green;
public byte Red;
public byte Alpha;
} [StructLayout(LayoutKind.Sequential, Pack = 1 )]
public struct BLENDFUNCTION
{
public byte BlendOp;
public byte BlendFlags;
public byte SourceConstantAlpha;
public byte AlphaFormat;
} public const Int32 ULW_COLORKEY = 0x00000001 ;
public const Int32 ULW_ALPHA = 0x00000002 ;
public const Int32 ULW_OPAQUE = 0x00000004 ; public const byte AC_SRC_OVER = 0x00 ;
public const byte AC_SRC_ALPHA = 0x01 ; [DllImport( " user32.dll " , ExactSpelling = true , SetLastError = true )]
public static extern Bool UpdateLayeredWindow(IntPtr hwnd, IntPtr hdcDst, ref Point pptDst, ref Size psize, IntPtr hdcSrc, ref Point pprSrc, Int32 crKey, ref BLENDFUNCTION pblend, Int32 dwFlags); [DllImport( " user32.dll " , ExactSpelling = true , SetLastError = true )]
public static extern IntPtr GetDC(IntPtr hWnd); [DllImport( " user32.dll " , ExactSpelling = true )]
public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC); [DllImport( " gdi32.dll " , ExactSpelling = true , SetLastError = true )]
public static extern IntPtr CreateCompatibleDC(IntPtr hDC); [DllImport( " gdi32.dll " , ExactSpelling = true , SetLastError = true )]
public static extern Bool DeleteDC(IntPtr hdc); [DllImport( " gdi32.dll " , ExactSpelling = true )]
public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject); [DllImport( " gdi32.dll " , ExactSpelling = true , SetLastError = true )]
public static extern Bool DeleteObject(IntPtr hObject); [DllImport( " user32.dll " , EntryPoint = " SendMessage " )]
public static extern int SendMessage( int hWnd, int wMsg, int wParam, int lParam);
[DllImport( " user32.dll " , EntryPoint = " ReleaseCapture " )] public static extern int ReleaseCapture();
public const int WM_SysCommand = 0x0112 ;
public const int SC_MOVE = 0xF012 ; public const int SC_MAXIMIZE = 61488 ;
public const int SC_MINIMIZE = 61472 ;
}

  

需要呈现图像的时候调用 SetBitmap 方法。只要优化好,呈现效率比普通的Paint重绘方式高很多,并且不卡不闪烁,支持任意透明。

下面是自己开发出来的效果:

这个是用OpenGL绘制的

推荐一款C#界面库:DSkin界面库(Winform平台首个DirectUI界面库)  http://d.cskin.net

还有一个也是我开发的免费界面库LayeredSkin http://bbs.cskin.net/forum-56-1.html 也可以实现很多效果
 
Winform也可以很炫丽的!

C# Winform实现炫酷的透明动画界面的更多相关文章

  1. 8个超炫酷仿HTML5动画源码

    1.jQuery万年历插件 带农历老皇历功能 这是一款基于jQuery的日历插件,这款日历插件和之前分享的日历控件有很大差异,它是一本万年历,包含了农历已经老皇历的功能,是一个挑好日子的工具.同时日历 ...

  2. 手把手带你做一个超炫酷loading成功动画view Android自定义view

    写在前面: 本篇可能是手把手自定义view系列最后一篇了,实际上我也是一周前才开始真正接触自定义view,通过这一周的练习,基本上已经熟练自定义view,能够应对一般的view需要,那么就以本篇来结尾 ...

  3. HTML5 Canvas 超炫酷烟花绽放动画教程

    这是一个很酷的HTML5 Canvas动画,它将模拟的是我们现实生活中烟花绽放的动画特效,效果非常逼真,但是毕竟是电脑模拟,带女朋友看就算了,效果还是差了点,呵呵.这个HTML5 Canvas动画有一 ...

  4. WPF炫酷UI及动画

    偶然看见了一张图,感觉挺好看的,花了点时间将他转化成了我代码仓库的一部分.虽然不难但也费时间.其中除了背景是百度的一张底图,其他所有内容均通过WPF的Path.Line.TextBlock.Borde ...

  5. 如何在你的blog中添加炫酷的飘雪动画效果

    将下面的代码复制到你的设置栏下页眉html代码框中即可 <script> (function($){$.fn.snow=function(options){,maxSize:,newOn: ...

  6. 8个经典炫酷的HTML5 Canvas动画欣赏

    HTML5非常强大,尤其是Canvas技术的应用,让HTML5几乎可以完成所有Flash能完成的效果.本文精选了8个经典炫酷的HTML5 Canvas动画欣赏,每一个都提供全部的源代码,希望对你有所帮 ...

  7. iOS任何界面全屏炫酷倒计时,一句代码就够了

    概述 iOS全屏炫酷倒计时,任何界面只需要调用一句代码就能实现,支持定制倒计时数字.倒计时结束时显示的文本.支持倒计时播放图片.开始倒计时和结束倒计时的block和delegate回调.支持定制文本颜 ...

  8. 使用Three.js实现炫酷的赛博朋克风格3D数字地球大屏 🌐

    声明:本文涉及图文和模型素材仅用于个人学习.研究和欣赏,请勿二次修改.非法传播.转载.出版.商用.及进行其他获利行为. 背景 近期工作有涉及到数字大屏的需求,于是利用业余时间,结合 Three.js ...

  9. html5跟随鼠标炫酷网站引导页动画特效

    html5跟随鼠标炫酷网站引导页动画特效一款非常不错的引导页,文字效果渐变,鼠标跟随出绚丽的条纹.html5炫酷网站引导页,鼠标跟随出特效. 体验效果:http://hovertree.com/tex ...

随机推荐

  1. Bootstrap 类解析

    Bootstrap 类解析 元素 Bootstrap 类 定义 <div> container 内容容器 <table> table 表格 <table> tabl ...

  2. ehcache入门

    一.简介 ehcache是一个开源的,纯java进程内的缓存框架.它具有快速,简单,具有多种缓存策略等特点. Hibernate中默认就是用了ehcache.在我们的应用中使用ehcache可以快速地 ...

  3. 烂泥:KVM安装Windows Server 2008 R2使用virtio硬盘

    本文首发于烂泥行天下. 在上一篇文章中,我们介绍了使用IDE硬盘来安装Windows Server 2008 R2,这篇文章我们来介绍使用virtio硬盘来安装Windows Server 2008 ...

  4. Heartbeat+LVS构建高可用负载均衡集群

    1.heartbeat简介: Heartbeat 项目是 Linux-HA 工程的一个组成部分,它实现了一个高可用集群系统.心跳服务和集群通信是高可用集群的两个关键组件,在 Heartbeat 项目里 ...

  5. [译]OpenStack Object Storage Monitoring

    注:翻译的不完整,主要是有些地方翻译后反而妨碍理解,有些不知道怎么翻,anyway,需要时拿来用用也是可行的,顺便共享啦.欢迎提意见. 一个OpenStack Object Storage(OSOS) ...

  6. 自动化测试selenium+java 第一章

    selenium元素的定位以及操作 1. 元素的定位 Selenium 自动化,我们需要做的最基本的事情就是在页面找到元素并通过脚本程 序去操作这个元素,实现模拟人工操作.我们有多种定位元素的方式可以 ...

  7. 译文:Nesting Your BEM?

    原文链接:http://csswizardry.com/2016/11/nesting-your-bem/ 在我开始这篇文章之前,我得说这不是一个建议或者是新的"练习指南".这只是 ...

  8. 【问题&解决】解决 Android SDK下载和更新失败“Connection to https://dl-ssl.google.com refused”的问题

    缘由: 更新sdk,遇到了更新下载失败问题: Fetching https://dl-ssl.google.com/android/repository/addons_list-2.xmlFetche ...

  9. 矩阵乘法快速幂 codevs 1250 Fibonacci数列

    codevs 1250 Fibonacci数列  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond   题目描述 Description 定义:f0=f1=1 ...

  10. UVALive 6663 Count the Regions --离散化+DFS染色

    题意:给你n(n<=50)个矩形(左上角坐标和右下角坐标),问这些矩形总共将平面分成多少个部分.坐标值可能有1e9. 分析:看到n和坐标的范围,容易想到离散化,当时就没想到离散化以后怎么判断区域 ...