C#开发案例精粹
上QQ阅读APP看书,第一时间看更新

bt2-L 实例005 隐藏式窗体

实例说明

一般情况下,当一个窗体被打开后会处于一个默认位置,如果此时进行其他操作,就必须关闭、移动或者最小化当前窗体。当该窗体再次被应用时,又要对其进行上述的一系列操作,这样就显得有些麻烦。本实例可以解决这个问题。实例运行结果如图1.5和图1.6所示。

图1.5 隐藏式窗体之登录结果

图1.6 隐藏式窗体之登录成功结果

技术要点

本实例主要用到Windows的API函数,它们是 WindowFromPoint函数、GetParent函数和GetSystemMetrics函数。

(1)WindowFromPoint函数。该函数用来获取当前鼠标指针下的控件。其语法如下:

[DllImport("user32.dll")]
public static extern int WindowFromPoint(int xPoint,int yPoint);

参数说明如下。

xPoint:表示当前状态下鼠标指针的x坐标。

yPoint:表示当前状态下鼠标指针的y坐标。

返回值:当前鼠标指针下控件的句柄。

(2)GetParent函数。该函数用来获取指定窗体的父窗体。其语法如下:

[DllImport("user32.dll",ExactSpelling = true,CharSet = CharSet.Auto)]
public static extern IntPtr GetParent(IntPtr hWnd);

参数说明如下。

hWnd:表示当前窗体的句柄。

返回值:当前窗体的父级句柄。

(3)GetSystemMetrics函数。该函数用来获取当前工作区的大小。其语法如下:

[DllImport("user32.dll",EntryPoint = "GetSystemMetrics")]
private static extern int GetSystemMetrics(int mVal);

参数说明如下。

mVal:表示将进行的操作类型。

返回值:取决于参数值。

注意:在调用Windows的API函数时必须引用命名空间System.Runtime.InteropServices,后文遇到这种情况将不再提示。

实现过程

01 新建一个项目,将其命名为HideToolBar,默认窗体为HideToolBar。

02 在HideToolBar窗体上添加1个ProgressBar控件、2个Label控件和3个Timer组件。设置ProgressBar控件的Style属性为Marquee,设置3个Timer组件的Interval属性分别为3000、1、1。

03 主要代码。

运行本实例,需要进行的变量定义及声明如下:

01   #region 声明本实例中用到的API函数
02   //获取当前鼠标指针下可视化控件的函数
03   [DllImport("user32.dll")]
04   public static extern int WindowFromPoint(int xPoint,int yPoint);
05   //获取指定句柄的父级函数
06   [DllImport("user32.dll",ExactSpelling = true,CharSet = CharSet.Auto)]
07   public static extern IntPtr GetParent(IntPtr hWnd);
08   //获取屏幕的大小
09   [DllImport("user32.dll",EntryPoint = "GetSystemMetrics")]
10   private static extern int GetSystemMetrics(int mVal);
11   #endregion

本实例在加载窗体时,窗体默认位于屏幕的右上侧。代码如下:

01   private void HideToolBar_Load(object sender,EventArgs e)
02   {
03       this.DesktopLocation = new Point(794,0);//为当前窗体定位
04       Tip.Visible = false;                   //设置Label控件为不可见状态
05       progressBar1.Minimum = 0;              //设置ProgressBar控件的最小值为0
06       progressBar1.Maximum = 10;             //设置ProgressBar控件的最大值为10
07       Counter.Start();                       //计时器Counter开始工作
08       //设置ProgressBar控件的滚动块在进度条内滚动所用的时间段
09       progressBar1.MarqueeAnimationSpeed = 100; 
10       this.MaximizeBox = false;              //设置最大化窗体为不可用状态
11   }

当窗体与屏幕边缘的距离小于3px时,如果此时鼠标指针在窗体外,那么窗体自动隐藏。代码如下:

01   private void JudgeWinMouPosition_Tick(object sender,EventArgs e)
02   {
03       if(this.Top < 3)                       //当窗体与屏幕的上边缘的距离小于3px时
04       {
05       //当鼠标指针在该窗体上时
06           if(this.Handle == MouseNowPosition(Cursor.Position.X,Cursor.Position.Y))
07           {
08               WindowFlag = 1;                //设定当前的窗体状态
09               HideWindow.Enabled = false;    //设定计时器HideWindow为不可用状态
10               this.Top = 0;                  //设定窗体上边缘与容器工作区上边缘之间的距离
11           }
12           else                               //当鼠标指针未在窗体上时
13           {
14               WindowFlag = 1;                //设定当前的窗体状态
15               HideWindow.Enabled = true;     //启动计时器HideWindow
16           }
17       }  
18       else                                   //当窗体与屏幕的上边缘的距离大于3px时
19       {
20           //当窗体处于屏幕的最左端、最右端或者最下端时
21           if(this.Left < 3 || (this.Left + this.Width) > (GetSystemMetrics(0) - 3) ||
                (this.Top + this.Height) > (Screen.AllScreens[0].Bounds.Height - 3))
22           {
23               if(this.Left < 3)  //当窗体左边缘与容器工作区左边缘的距离小于3px时
24               {
25                   if(this.Handle == MouseNowPosition(Cursor.Position.X,Cursor.
                                       Position.Y)) //当鼠标指针在该窗体上时
26                   {
27                       WindowFlag = 2;            //设定当前的窗体状态
28                       HideWindow.Enabled = false;//设定计时器HideWindow为不可用状态
29                       this.Left = 0;  //设定窗体左边缘与容器工作区左边缘之间的距离
30                   }
31                   else                          //当鼠标指针未在该窗体上时
32                   {
33                       WindowFlag = 2;           //设定当前的窗体状态
34                       HideWindow.Enabled = true;//设定计时器HideWindow为可用状态
35                   }
36               }
37               //当窗体处于屏幕的最右端时
38               if((this.Left + this.Width) > (GetSystemMetrics(0) - 3)) 
39               {
40                   if(this.Handle == MouseNowPosition(Cursor.Position.X,Cursor.
                                       Position.Y))//当鼠标指针处于该窗体上时
41                   {
42                       WindowFlag = 3;              //设定当前的窗体状态
43                       HideWindow.Enabled = false;  //设定计时器HideWindow为不可用状态
44                       //设定该窗体与容器工作区左边缘之间的距离
45                       this.Left = GetSystemMetrics(0) - this.Width; 
46                   }
47                   else                            //当鼠标指针离开该窗体时
48                   {
49                       WindowFlag = 3;             //设定当前的窗体状态
50                       HideWindow.Enabled = true;  //设定计时器HideWindow为可用状态
51                   }
52               }
53               //当窗体与屏幕的下边缘的距离小于3px时
54               if((this.Top + this.Height) > (Screen.AllScreens[0].Bounds.
                                               Height - 3))
55               {
56                   if(this.Handle == MouseNowPosition(Cursor.Position.X,Cursor.
                                       Position.Y)) //当鼠标指针在该窗体上时
57                   {
58                       WindowFlag = 4;            //设定当前的窗体状态
59                       HideWindow.Enabled = false;//设定计时器HideWindow为不可用状态
60                       //设定该窗体与容器工作区上边缘之间的距离
61                       this.Top = Screen.AllScreens[0].Bounds.Height - this.Height; 
62                   }
63                   else                          //当鼠标指针未在该窗体上时
64                   {
65                       WindowFlag = 4;           //设定当前的窗体状态
66                       HideWindow.Enabled = true;//设定计时器HideWindow为可用状态
67                   }
68               }
69           }
70       }
71   }

当窗体处于应该隐藏的区域时,窗体自动消失,在消失的地方露出窗体的一部分;当与鼠标指针接触时,窗体自动显示。代码如下:

01   private void HideWindow_Tick(object sender,EventArgs e)
02   {
03       switch(Convert.ToInt32(WindowFlag.ToString())) //判断当前窗体处于哪个状态
04       {
05           case 1:             //当窗体处于最上端时   
06               if(this.Top < 5)   //当窗体与容器工作区上边缘的距离小于5px时
07                   this.Top = -(this.Height - 2);//设定当前窗体距容器工作区上边缘的值
08               break;
09           case 2:              //当窗体处于最左端时
10               if(this.Left < 5)//当窗体与容器工作区左边缘的距离小于5px时
11                   this.Left = -(this.Width - 2); //设定当前窗体距容器工作区左边缘的值
12               break;
13           case 3:             //当窗体处于最右端时
14               //当窗体与容器工作区右边缘的距离小于5px时
15               if((this.Right + this.Width) > (GetSystemMetrics(0) - 5))  
16                   //设定当前窗体距容器工作区右边缘的值
17                   this.Right = GetSystemMetrics(0) - 2; 
18               break;
19           case 4:             //当窗体处于最下端时
20               if((this.Bottom + this.Height) > (Screen.AllScreens[0].Bounds.
                     Height - 5)) //当窗体与容器工作区下边缘的距离小于5px时
21                   //设定当前窗体距容器工作区下边缘的值
22                   this.Bottom = Screen.AllScreens[0].Bounds.Height - 2;   
23               break;
24       }
25   }

当鼠标指针在窗体上移动时,需要判断鼠标指针当前所处的窗体是否是隐藏的窗体。代码如下:

01   public IntPtr MouseNowPosition(int x,int y)
02   {
03       IntPtr OriginalHandle;//声明保存原始句柄的变量
04       OriginalHandle = ((IntPtr)WindowFromPoint(x,y));//获取原始的句柄
05       CurrentHandle = OriginalHandle;//保存原始的句柄
06       while(OriginalHandle != ((IntPtr)0))//循环判断鼠标指针是否移动
07       {
08           CurrentHandle = OriginalHandle;//记录当前的句柄
09           OriginalHandle = GetParent(CurrentHandle);//更新原始的句柄
10       }
11       return CurrentHandle;  //返回当前的句柄
12   }

举一反三

根据本实例,读者可以实现以下功能。

在屏幕的任何位置隐藏新建的窗体。

模拟腾讯QQ的登录。