巧用内置函数+句柄实现:动态显示窗体效果
今天再给大家带来一个小程序:使用系统内置函数+句柄控制、实现动态显示窗体的效果。先简单的来介绍一下功能可以实现的效果:
1、酷狗音乐用过吧?当我们关闭窗体时、窗体动态关闭:高度先变扁、然后再变窄、最后缩小成为一个光点、 2、QQ2013、登录成功后、窗体以卷帘的方式向上收缩、 3、等等。。。
当然、在此之前、你也可以自己实现这个效果:例如在窗体上放置几个Timer控件、 在窗体加载时,动态改变窗体的宽高、达到动态显示窗体的效果、然后在窗体关闭时事件中再动态改变窗体的宽高、达到动态关闭窗体的效果、
但是、这样的写法只会让你的程序变卡、用户体验度大打折扣、
也许你还会问?提供的函数有多少效果呢?会不会没有我自己用Timer写的效果多呢? 可以实现的效果有:自上向下、自下向上、自左向右、自由向左、滑入滑出、渐变等。详细的下面有介绍。
既然微软内置了这种效果的对外接口、我们为什么不用呢?因此、下面我来介绍一些这个程序的制作过程:
——————————————————————————————————————
首先、新建一个WinForm程序、默认会给你一个窗体吧(没有就添加一个)?命名这个窗体名为frmMain.cs、
然后打开这个窗体的设计器、按下F7、进入这个窗体的代码编辑界面、引入以下命名空间:
1 using System; 2 using System.Windows.Forms; 3 using System.Runtime.InteropServices;
然后、我们引用功能实现的接口函数:
1 [DllImportAttribute("user32.dll")] 2 //第一个参数表示我们要动态控制的窗体控件的句柄、 3 //第二个参数表示指定效果运行的时间、也就是效果运行的速度、单位是毫秒、 4 //第三个参数就是我们要实现的效果数值,所有可实现的效果数值及效果注释下面会提供。 5 private static extern bool AnimateWindow(IntPtr hwnd, int dwTime, int dwFlags);
其次、我们设置常量、用来在我们使用上面声明的接口函数时、动态控制效果实现的。
为什么要设置为常量、因为数值是固定的、设置为常量是怕某些人在操作过程中对参数值大小的更改。
下面是所有效果的常量数值:
1 public const Int32 GUYING_HOR_POSITIVE = 0x00000001; //自左向右显示窗口。该标志可以在滚动动画和滑动动画中使用。当使用GUYING_CENTER标志时,该标志将被忽略 2 public const Int32 GUYING_HOR_NEGATIVE = 0x00000002; //自右向左显示窗口。当使用了GUYING_CENTER 标志时该标志被忽略 3 public const Int32 GUYING_VER_POSITIVE = 0x00000004; //自顶向下显示窗口。该标志可以在滚动动画和滑动动画中使用。当使用GUYING_CENTER标志时,该标志将被忽略 4 public const Int32 GUYING_VER_NEGATIVE = 0x00000008; //自下向上显示窗口。该标志可以在滚动动画和滑动动画中使用。当使用GUYING_CENTER标志时,该标志将被忽略 5 public const Int32 GUYING_CENTER = 0x00000010; //若使用了GUYING_HIDE标志,则使窗口向内重叠;若未使用GUYING_HIDE标志,则使窗口向外扩展 6 public const Int32 GUYING_ACTIVATE = 0x00020000; //激活窗口。在使用了GUYING_HIDE标志后不要使用这个标志 7 public const Int32 GUYING_SLIDE = 0x00040000; //使用滑动类型。缺省则为滚动动画类型。当使用AW_CENTER标志时,这个标志就被忽略 8 public const Int32 GUYING_BLEND = 0x00080000; //使用淡入效果。只有当hWnd为顶层窗口的时候才可以使用此标志 9 public const Int32 GUYING_HIDE = 0x00010000; //隐藏窗口,缺省则显示窗口,这个必须注意下面的【特别注意】!!!
然后、我们想要什么效果直接按照我给你们的效果注释、自己改参数就可以了、
【特别注意:】 常量“GUYING_HIDE”、这个常量表示关闭的效果、 例如、我们要在窗体关闭的时候、实现某个效果、那么就加上这个常量值、 如果不加、那么就表示、该效果实在窗体加载显示时要实现的效果、 简单的说:加上这个常量、就表示加载时;不加、就表示关闭时。
例如:我现在要做的效果是:窗体加载显示时、窗体以卷帘的方式自上向下动态显示;关闭的时候、渐变至透明、最后关闭、
那么我们首先按照我提供的效果注释、找到自上向下的常量“GUYING_VER_POSITIVE”和渐变的常量“GUYING_BLEND”、
窗体加载显示效果、所以我们可以把函数写在Load事件中、也可以直接写到窗体默认的构造函数里、 【注意:】如果写在构造函数里、最好写在“InitializeComponent();”的下面。 而关闭显示效果、则可以写在Form_Closing的事件中。
由于上面注意的地方说了、关闭的效果需要加GUYING_HIDE常量、因此、代码如下:
1 //窗体Load加载时、显示效果 2 //当然、你也可以写在窗体的Load事件中 3 public frmMain() 4 { 5 InitializeComponent(); 6 7 //窗体加载完控件之后、开始执行窗体动画常量值:“GUYING_VER_POSITIVE”的效果。 8 //第一个参数:要控制的句柄、在这里是当前窗体的句柄 9 //第二个参数:效果执行的速度,在这里是300毫秒 10 //第三个参数:效果数值、也就是上面的常量值。由于要求是自上而下、所以选用常量“GUYING_VER_POSITIVE”、由于是加载显示的动画效果、因此不用加“GUYING_HIDE”常量。 11 AnimateWindow(this.Handle, 300, GUYING_VER_POSITIVE); 12 } 13 14 //窗体关闭时、执行的效果 15 private void frmMain_FormClosed(object sender, FormClosedEventArgs e) 16 { 17 //窗体关闭时、开始执行窗体动画:常量值“GUYING_BLEND”的效果。 18 //第一个参数:要控制的句柄、在这里是当前窗体的句柄 19 //第二个参数:效果执行的速度,在这里是300毫秒 20 //第三个参数:效果数值、也就是上面的常量值。由于我们要求的是做一个渐变效果的程序、所以选择的是常量“GUYING_BLEND”、又因为这是关闭效果、因此、需要加常量“GUYING_HIDE”表示关闭效果。 21 AnimateWindow(this.Handle, 300, GUYING_BLEND + GUYING_HIDE); 22 }
完整的窗体后置代码frmMain.cs如下:
1 using System; 2 using System.Windows.Forms; 3 using System.Runtime.InteropServices; 4 5 namespace ShowFormWithAPI 6 { 7 public partial class frmMain : Form 8 { 9 [DllImportAttribute("user32.dll")] 10 //第一个参数表示我们要动态控制的窗体控件的句柄、 11 //第二个参数表示指定效果运行的时间、也就是效果运行的速度、单位是毫秒、 12 //第三个参数就是我们要实现的效果数值,所有可实现的效果数值及效果注释下面会提供。 13 private static extern bool AnimateWindow(IntPtr hwnd, int dwTime, int dwFlags); 14 15 public const Int32 GUYING_HOR_POSITIVE = 0x00000001; //自左向右显示窗口。该标志可以在滚动动画和滑动动画中使用。当使用GUYING_CENTER标志时,该标志将被忽略 16 public const Int32 GUYING_HOR_NEGATIVE = 0x00000002; //自右向左显示窗口。当使用了GUYING_CENTER 标志时该标志被忽略 17 public const Int32 GUYING_VER_POSITIVE = 0x00000004; //自顶向下显示窗口。该标志可以在滚动动画和滑动动画中使用。当使用GUYING_CENTER标志时,该标志将被忽略 18 public const Int32 GUYING_VER_NEGATIVE = 0x00000008; //自下向上显示窗口。该标志可以在滚动动画和滑动动画中使用。当使用GUYING_CENTER标志时,该标志将被忽略 19 public const Int32 GUYING_CENTER = 0x00000010; //若使用了GUYING_HIDE标志,则使窗口向内重叠;若未使用GUYING_HIDE标志,则使窗口向外扩展 20 public const Int32 GUYING_HIDE = 0x00010000; //隐藏窗口,缺省则显示窗口 21 public const Int32 GUYING_ACTIVATE = 0x00020000; //激活窗口。在使用了GUYING_HIDE标志后不要使用这个标志 22 public const Int32 GUYING_SLIDE = 0x00040000; //使用滑动类型。缺省则为滚动动画类型。当使用AW_CENTER标志时,这个标志就被忽略 23 public const Int32 GUYING_BLEND = 0x00080000; //使用淡入效果。只有当hWnd为顶层窗口的时候才可以使用此标志 24 25 //默认构造、可以吧加载效果下载这里 26 public frmMain() 27 { 28 InitializeComponent(); 29 } 30 31 //窗体Load加载事件、里面的是加载时显示的效果 32 private void frmMain_Load(object sender, EventArgs e) 33 { 34 //窗体加载完控件之后、开始执行窗体动画常量值:“GUYING_VER_POSITIVE”的效果。 35 //第一个参数:要控制的句柄、在这里是当前窗体的句柄 36 //第二个参数:效果执行的速度,在这里是300毫秒 37 //第三个参数:效果数值、也就是上面的常量值。由于要求是自上而下、所以选用常量“GUYING_VER_POSITIVE”、由于是加载显示的动画效果、因此不用加“GUYING_HIDE”常量。 38 AnimateWindow(this.Handle, 300, GUYING_VER_POSITIVE); 39 } 40 41 //窗体关闭时执行关闭的动态效果 42 private void frmMain_FormClosed(object sender, FormClosedEventArgs e) 43 { 44 //窗体关闭时、开始执行窗体动画:常量值“GUYING_BLEND”的效果。 45 //第一个参数:要控制的句柄、在这里是当前窗体的句柄 46 //第二个参数:效果执行的速度,在这里是300毫秒 47 //第三个参数:效果数值、也就是上面的常量值。由于我们要求的是做一个渐变效果的程序、所以选择的是常量“GUYING_BLEND”、又因为这是关闭效果、因此、需要加常量“GUYING_HIDE”表示关闭效果。 48 AnimateWindow(this.Handle, 300, GUYING_BLEND + GUYING_HIDE); 49 } 50 } 51 }
最后、执行一下看看效果吧、
最后、我在啰嗦一下“GUYING_HIDE”这个常量、如果我们的要求是:加载显示时渐变出现(即由透明慢慢显示)、关闭时渐变隐藏(即由显示慢慢透明)、怎么做?
首先找到渐变的常量“GUYING_BLEND”、如果加载关闭都写这一个、出现的情况会是:加载正常(慢慢显示)、但是关闭时、直接关闭了、 因为、没有加常量“GUYING_HIDE”、在关闭效果中、程序一看没有“GUYING_HIDE”以为是加载效果的慢慢显示、因此、已经是显示状态了、所以直接关闭了、
解决办法的实现代码如下:
1 //窗体加载完控件之后、开始执行窗体动画 2 private void frmMain_Load(object sender, EventArgs e) 3 { 4 AnimateWindow(this.Handle, 300, GUYING_BLEND); //由于渐变显示、所以不加“GUYING_HIDE” 5 } 6 7 //窗体关闭时、开始执行窗体动画 8 private void frmMain_FormClosed(object sender, FormClosedEventArgs e) 9 { 10 AnimateWindow(this.Handle, 300, GUYING_BLEND + GUYING_HIDE); //由于渐变隐藏、所以需要加“GUYING_HIDE” 11 }
也许你在运行的时候会发现、慢慢显示的时候、窗体部分是动态慢慢显示的、但是、窗体的边缘、也就是窗体的边框、提前显示出来了、什么情况?怎么办? 这是因为我们的函数控制的是当前窗体的句柄、窗体的边框并不包括在内、怎么办? 善意的提醒你一下、窗体有个“FormBorderStyle”属性、
如果你非要加载显示动画时、不提前显示边框、动画显示后在显示边框、下面是办法: 在构造加载出控件之后 窗体Load显示之前、可以将边框设置为none、动画执行后、再将边框样式设置回去、 下面的就不用我教你了吧、
因为我主要讲的是这个效果的制作、因此别的我没有考虑进去、 例如、效果常量和效果实现的函数接口引入、我们可以单独写一个公共类、最后、我们用的时候、引用这个公共类中的数据、
好了、不罗嗦了、如果程序还是没有看懂、可以私下联系我、联系方式在个人资料里。
【原文来自:http://www.cnblogs.com/HackerGuying,尊重原创、转载请注明出处!】