巧用内置函数+句柄实现:动态显示窗体效果

  今天再给大家带来一个小程序:使用系统内置函数+句柄控制、实现动态显示窗体的效果。先简单的来介绍一下功能可以实现的效果:

  1、酷狗音乐用过吧?当我们关闭窗体时、窗体动态关闭:高度先变扁、然后再变窄、最后缩小成为一个光点、   2、QQ2013、登录成功后、窗体以卷帘的方式向上收缩、   3、等等。。。

  当然、在此之前、你也可以自己实现这个效果:例如在窗体上放置几个Timer控件、   在窗体加载时,动态改变窗体的宽高、达到动态显示窗体的效果、然后在窗体关闭时事件中再动态改变窗体的宽高、达到动态关闭窗体的效果、

  但是、这样的写法只会让你的程序变卡、用户体验度大打折扣、

  也许你还会问?提供的函数有多少效果呢?会不会没有我自己用Timer写的效果多呢?   可以实现的效果有:自上向下、自下向上、自左向右、自由向左、滑入滑出、渐变等。详细的下面有介绍。

  既然微软内置了这种效果的对外接口、我们为什么不用呢?因此、下面我来介绍一些这个程序的制作过程:

——————————————————————————————————————

  首先、新建一个WinForm程序、默认会给你一个窗体吧(没有就添加一个)?命名这个窗体名为frmMain.cs、

  然后打开这个窗体的设计器、按下F7、进入这个窗体的代码编辑界面、引入以下命名空间:

需要引用的命名空间
1 using System;
2 using System.Windows.Forms;
3 using System.Runtime.InteropServices;


  然后、我们引用功能实现的接口函数:

调用系统的API接口
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如下:

窗体完整的后置代码(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”以为是加载效果的慢慢显示、因此、已经是显示状态了、所以直接关闭了、

  解决办法的实现代码如下:

缺少“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,尊重原创、转载请注明出处!】

 

 

posted @ 2013-04-16 18:31  单曲循环ㄋ  阅读(461)  评论(0编辑  收藏  举报