實例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的登錄。
- 觸·心:DT時代的大數據精準營銷
- HoloLens Beginner's Guide
- Mastering Ember.js
- PostgreSQL 11從入門到精通(視頻教學版)
- 名師講壇:Java微服務架構實戰(SpringBoot+SpringCloud+Docker+RabbitMQ)
- 微信公眾平臺開發:從零基礎到ThinkPHP5高性能框架實踐
- Mastering Python Networking
- FPGA Verilog開發實戰指南:基于Intel Cyclone IV(進階篇)
- 實戰Java高并發程序設計(第2版)
- 大學計算機基礎實驗指導
- Continuous Delivery and DevOps:A Quickstart Guide Second Edition
- 金融商業數據分析:基于Python和SAS
- Sitecore Cookbook for Developers
- 用Python動手學統計學
- Swift 2 Design Patterns