C# 顯示、隱藏視窗對應的工作列

唐宋元明清2188發表於2021-10-01

WPF中全屏視窗,會自動隱藏工作列。

那非全屏視窗如何隱藏工作列?甚至有沒有一種場景,隱藏任務後自定義一套系統工作列來顯示?

以下會分階段講述一些概念,工作列、查詢視窗、控制視窗顯示。

1. 主屏工作列

工作列,其實也是一個視窗,主屏的工作列名稱是"Shell_TrayWnd"。

所以可以通過名稱查詢視窗,然後對視窗進行顯示、隱藏操作。

以下是主螢幕工作列的控制操作:

 1     public static class ScreenTaskBar
 2     {
 3         private const int SwHide = 0; //隱藏視窗
 4         private const int SwRestore = 9;//還原視窗
 5 
 6         [DllImport("user32.dll")]
 7         private static extern int ShowWindow(int hwnd, int nCmdShow);
 8         [DllImport("user32.dll")]
 9         private static extern int FindWindow(string lpClassName, string lpWindowName);
10         /// <summary>
11         /// 顯示工作列
12         /// </summary>
13         public static void Show()
14         {
15             ShowWindow(FindWindow("Shell_TrayWnd", null), SwRestore);
16         }
17         /// <summary>
18         /// 隱藏工作列
19         /// </summary>
20         public static void Hide()
21         {
22             ShowWindow(FindWindow("Shell_TrayWnd", null), SwHide);
23         }
24     }

2. 多屏工作列

如果是多屏,對工作列進行處理的場景,一般是對視窗所對應的工作列操作。

如何獲取任意視窗所在的工作列呢?既然工作列也是視窗,那麼我們的關注點就是如何找到工作列視窗了。

User32有EnumWindows函式,可以遍歷當前電腦的所有視窗。

1     private delegate bool EnumWindowProc(IntPtr hWnd, int lParam);
2     [DllImport("user32")]
3     private static extern bool EnumWindows(EnumWindowProc lpEnumFunc, int lParam);

EnumWindowProc定義了委託的處理。新增回撥方法,返回的引數是控制程式碼資訊:

1     bool OnEnumWindow(IntPtr hWnd, int lparam)
2     {
3         //新增程式碼XXX
4         return true;
5     }

然後可以在回撥內部新增程式碼,根據視窗的控制程式碼資訊,我們去拿視窗的一些資訊,類名、視窗標題、視窗的Bounds(位置、大小)

1     [DllImport("user32")]
2     private static extern int GetClassName(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
3     [DllImport("user32")]
4     private static extern int GetWindowText(IntPtr hWnd, StringBuilder lptrString, int nMaxCount);
5     [DllImport("user32")]
6     private static extern bool GetWindowRect(IntPtr hWnd, ref LPRECT rect);

以下是部分遍歷出來的視窗類資訊:

所以,可以篩選出那些以TrayWnd字串結尾的,這些都是工作列視窗。

之後就是如何篩選出我們想要的工作列,即視窗對應的工作列。

視窗與工作列,是通過螢幕關聯在一起的。通過視窗獲取當前螢幕資訊,工作列的Bounds如果與螢幕Bounds相交,則說明此工作列在此螢幕內。

1     var intPtr = new WindowInteropHelper(window).Handle;//獲取當前視窗的控制程式碼
2     var screen = Screen.FromHandle(intPtr);//獲取當前螢幕
3     var currentScreenBounds = screen.Bounds;
4     var taskBars = windows.Where(i => i.ClassName.Contains("TrayWnd"));
5     var currentTaskBar = taskBars.FirstOrDefault(i => i.Bounds.IntersectsWith(currentScreenBounds));

獲取工作列,也可以通過工作列的控制程式碼獲取螢幕,與主視窗所在螢幕判斷是否同一個。

獲取了指定的工作列資訊後,我們就可以控制工作列顯示、隱藏了。呼叫下user32下函式ShowWindow即可:

 1     private const int SwHide = 0; //隱藏視窗
 2     private const int SwRestore = 9;//還原視窗
 3     /// <summary>
 4     /// 通過控制程式碼,窗體顯示函式
 5     /// </summary>
 6     /// <param name="hWnd">窗體控制程式碼</param>
 7     /// <param name="cmdShow">顯示方式</param>
 8     /// <returns>返回成功與否</returns>
 9     [DllImport("user32.dll", EntryPoint = "ShowWindowAsync", SetLastError = true)]
10     public static extern bool ShowWindow(IntPtr hWnd, int cmdShow);

 這裡的ShowWindow,與上面預設工作列操作所呼叫的ShowWindow不一樣,控制程式碼引數是IntPtr 

相關文章