实例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的登录。