我如何获得任务栏的位置和大小?
我想知道如何获得任务栏占据的矩形(底部,顶部,左侧和右侧)。 我如何去做这个在C#中?
你必须调用一些Windows API:
http://winsharp93.wordpress.com/2009/06/29/find-out-size-and-position-of-the-taskbar/
private enum TaskBarLocation { TOP, BOTTOM, LEFT, RIGHT} private TaskBarLocation GetTaskBarLocation() { TaskBarLocation taskBarLocation = TaskBarLocation.BOTTOM; bool taskBarOnTopOrBottom = (Screen.PrimaryScreen.WorkingArea.Width == Screen.PrimaryScreen.Bounds.Width); if (taskBarOnTopOrBottom) { if (Screen.PrimaryScreen.WorkingArea.Top > 0) taskBarLocation = TaskBarLocation.TOP; } else { if (Screen.PrimaryScreen.WorkingArea.Left > 0) { taskBarLocation = TaskBarLocation.LEFT; } else { taskBarLocation = TaskBarLocation.RIGHT; } } return taskBarLocation; }
这实际上比上面显示的更复杂。 首先,任务栏不必在主屏幕上,可以拖动到任何屏幕。 另一方面,从理论上讲,每个给定屏幕的每个边缘上可能会有东西停靠。 上面的代码不正确地假定find停靠到一个边的东西排除了所有其他边。
任务栏的位置唯一的方法可能是从边界vs工作区域确定派生,如果只有一个边缘在所有的屏幕上都有对接的东西。
下面的函数返回一个矩形数组,每个矩形代表一个停靠的任务栏,并将计数写入它的byref参数。 如果该计数为1,则返回数组的元素0是任务栏占用的矩形。 如果大于1,有时间猜测?
Public Function FindDockedTaskBars(ByRef DockedRectCounter As Integer) As Rectangle() Dim TmpScrn As Screen = Nothing Dim LeftDockedWidth As Integer = 0 Dim TopDockedHeight As Integer = 0 Dim RightDockedWidth As Integer = 0 Dim BottomDockedHeight As Integer = 0 Dim DockedRects(Screen.AllScreens.Count * 4) As Rectangle DockedRectCounter = 0 For Each TmpScrn In Screen.AllScreens If Not TmpScrn.Bounds.Equals(TmpScrn.WorkingArea) Then LeftDockedWidth = Math.Abs(Math.Abs(TmpScrn.Bounds.Left) - Math.Abs(TmpScrn.WorkingArea.Left)) TopDockedHeight = Math.Abs(Math.Abs(TmpScrn.Bounds.Top) - Math.Abs(TmpScrn.WorkingArea.Top)) RightDockedWidth = (TmpScrn.Bounds.Width - LeftDockedWidth) - TmpScrn.WorkingArea.Width BottomDockedHeight = (TmpScrn.Bounds.Height - TopDockedHeight) - TmpScrn.WorkingArea.Height If LeftDockedWidth > 0 Then DockedRects(DockedRectCounter).X = TmpScrn.Bounds.Left DockedRects(DockedRectCounter).Y = TmpScrn.Bounds.Top DockedRects(DockedRectCounter).Width = LeftDockedWidth DockedRects(DockedRectCounter).Height = TmpScrn.Bounds.Height DockedRectCounter += 1 End If If RightDockedWidth > 0 Then DockedRects(DockedRectCounter).X = TmpScrn.WorkingArea.Right DockedRects(DockedRectCounter).Y = TmpScrn.Bounds.Top DockedRects(DockedRectCounter).Width = RightDockedWidth DockedRects(DockedRectCounter).Height = TmpScrn.Bounds.Height DockedRectCounter += 1 End If If TopDockedHeight > 0 Then DockedRects(DockedRectCounter).X = TmpScrn.WorkingArea.Left DockedRects(DockedRectCounter).Y = TmpScrn.Bounds.Top DockedRects(DockedRectCounter).Width = TmpScrn.WorkingArea.Width DockedRects(DockedRectCounter).Height = TopDockedHeight DockedRectCounter += 1 End If If BottomDockedHeight > 0 Then DockedRects(DockedRectCounter).X = TmpScrn.WorkingArea.Left DockedRects(DockedRectCounter).Y = TmpScrn.WorkingArea.Bottom DockedRects(DockedRectCounter).Width = TmpScrn.WorkingArea.Width DockedRects(DockedRectCounter).Height = BottomDockedHeight DockedRectCounter += 1 End If End If Next Return DockedRects End Function
或者对于那些喜欢C#的人…(注意:这个移植的代码是未经testing的)
using System.Drawing; using System.Windows.Forms; public Rectangle[] FindDockedTaskBars(ref int DockedRectCounter) { int LeftDockedWidth = 0; int TopDockedHeight = 0; int RightDockedWidth = 0; int BottomDockedHeight = 0; Rectangle[] DockedRects = new Rectangle[Screen.AllScreens.Count() * 4]; DockedRectCounter = 0; foreach (Screen TmpScrn in Screen.AllScreens) { if (!TmpScrn.Bounds.Equals(TmpScrn.WorkingArea)) { LeftDockedWidth = Math.Abs(Math.Abs(TmpScrn.Bounds.Left) - Math.Abs(TmpScrn.WorkingArea.Left)); TopDockedHeight = Math.Abs(Math.Abs(TmpScrn.Bounds.Top) - Math.Abs(TmpScrn.WorkingArea.Top)); RightDockedWidth = (TmpScrn.Bounds.Width - LeftDockedWidth) - TmpScrn.WorkingArea.Width; BottomDockedHeight = (TmpScrn.Bounds.Height - TopDockedHeight) - TmpScrn.WorkingArea.Height; if (LeftDockedWidth > 0) { DockedRects[DockedRectCounter].X = TmpScrn.Bounds.Left; DockedRects[DockedRectCounter].Y = TmpScrn.Bounds.Top; DockedRects[DockedRectCounter].Width = LeftDockedWidth; DockedRects[DockedRectCounter].Height = TmpScrn.Bounds.Height; DockedRectCounter += 1; } if (RightDockedWidth > 0) { DockedRects[DockedRectCounter].X = TmpScrn.WorkingArea.Right; DockedRects[DockedRectCounter].Y = TmpScrn.Bounds.Top; DockedRects[DockedRectCounter].Width = RightDockedWidth; DockedRects[DockedRectCounter].Height = TmpScrn.Bounds.Height; DockedRectCounter += 1; } if (TopDockedHeight > 0) { DockedRects[DockedRectCounter].X = TmpScrn.WorkingArea.Left; DockedRects[DockedRectCounter].Y = TmpScrn.Bounds.Top; DockedRects[DockedRectCounter].Width = TmpScrn.WorkingArea.Width; DockedRects[DockedRectCounter].Height = TopDockedHeight; DockedRectCounter += 1; } if (BottomDockedHeight > 0) { DockedRects[DockedRectCounter].X = TmpScrn.WorkingArea.Left; DockedRects[DockedRectCounter].Y = TmpScrn.WorkingArea.Bottom; DockedRects[DockedRectCounter].Width = TmpScrn.WorkingArea.Width; DockedRects[DockedRectCounter].Height = BottomDockedHeight; DockedRectCounter += 1; } } } return DockedRects; }
private enum TaskBarLocation { TOP, BOTTOM, LEFT, RIGHT } private TaskBarLocation GetTaskBarLocation() { //System.Windows.SystemParameters.... if (SystemParameters.WorkArea.Left > 0) return TaskBarLocation.LEFT; if (SystemParameters.WorkArea.Top > 0) return TaskBarLocation.TOP; if (SystemParameters.WorkArea.Left == 0 && SystemParameters.WorkArea.Width < SystemParameters.PrimaryScreenWidth) return TaskBarLocation.RIGHT; return TaskBarLocation.BOTTOM; }
这是Mark McGinty
在C#中的答案。
此代码将所有任务栏作为rectanges列表回来:
- 0矩形意味着任务栏被隐藏;
- 1矩形是任务栏的位置;
- 2+是非常罕见的,这意味着我们有多个显示器,而且我们没有使用
Extend these displays
来创build单个虚拟桌面。
适用于任何情况
它适用于:
- Windows 7(几乎肯定会在Windows 8.1和Windows 10上运行)。
- 所有设置的组合。
C#代码
public static List<Rectangle> FindDockedTaskBars() { List<Rectangle> dockedRects = new List<Rectangle>(); foreach (var tmpScrn in Screen.AllScreens) { if (!tmpScrn.Bounds.Equals(tmpScrn.WorkingArea)) { Rectangle rect = new Rectangle(); var leftDockedWidth = Math.Abs((Math.Abs(tmpScrn.Bounds.Left) - Math.Abs(tmpScrn.WorkingArea.Left))); var topDockedHeight = Math.Abs((Math.Abs(tmpScrn.Bounds.Top) - Math.Abs(tmpScrn.WorkingArea.Top))); var rightDockedWidth = ((tmpScrn.Bounds.Width - leftDockedWidth) - tmpScrn.WorkingArea.Width); var bottomDockedHeight = ((tmpScrn.Bounds.Height - topDockedHeight) - tmpScrn.WorkingArea.Height); if ((leftDockedWidth > 0)) { rect.X = tmpScrn.Bounds.Left; rect.Y = tmpScrn.Bounds.Top; rect.Width = leftDockedWidth; rect.Height = tmpScrn.Bounds.Height; } else if ((rightDockedWidth > 0)) { rect.X = tmpScrn.WorkingArea.Right; rect.Y = tmpScrn.Bounds.Top; rect.Width = rightDockedWidth; rect.Height = tmpScrn.Bounds.Height; } else if ((topDockedHeight > 0)) { rect.X = tmpScrn.WorkingArea.Left; rect.Y = tmpScrn.Bounds.Top; rect.Width = tmpScrn.WorkingArea.Width; rect.Height = topDockedHeight; } else if ((bottomDockedHeight > 0)) { rect.X = tmpScrn.WorkingArea.Left; rect.Y = tmpScrn.WorkingArea.Bottom; rect.Width = tmpScrn.WorkingArea.Width; rect.Height = bottomDockedHeight; } else { // Nothing found! } dockedRects.Add(rect); } } if (dockedRects.Count == 0) { // Taskbar is set to "Auto-Hide". } return dockedRects; }
这是一个简单的例子,使用wpf和多屏幕支持winforms:
Screen sc = Screen.FromHandle(new WindowInteropHelper(this).Handle); if (sc.WorkingArea.Top > 0) { // TASKBAR TOP } else if (sc.WorkingArea.Left != sc.Bounds.X) { // TASKBAR LEFT } else if ((sc.Bounds.Height - sc.WorkingArea.Height) > 0) { // TASKBAR BOTTOM } else if (sc.WorkingArea.Right != 0) { // TASKBAR RIGHT } else { // TASKBAR NOT FOUND }
基于David的回答 ,这是一个更好的实现,它使用P / Invoke来正确确定任务栏的位置和大小。 到目前为止,我所知道的唯一限制是当多个监视器设置为以扩展模式显示时,它不会返回正确的界限。
所有后续更新的代码都可以在https://git.io/v9bCx上find 。
/****************************************************************************** * Name: Taskbar.cs * Description: Class to get the taskbar's position, size and other properties. * Author: Franz Alex Gaisie-Essilfie * based on code from https://winsharp93.wordpress.com/2009/06/29/find-out-size-and-position-of-the-taskbar/ * * Change Log: * Date | Description * -------------|-------------------------------------------------------------- * 2017-05-16 | Initial design */ using System; using System.Drawing; using System.Runtime.InteropServices; namespace System.Windows.Forms { public enum TaskbarPosition { Unknown = -1, Left, Top, Right, Bottom, } public static class Taskbar { private enum ABS { AutoHide = 0x01, AlwaysOnTop = 0x02, } ////private enum ABE : uint private enum AppBarEdge : uint { Left = 0, Top = 1, Right = 2, Bottom = 3 } ////private enum ABM : uint private enum AppBarMessage : uint { New = 0x00000000, Remove = 0x00000001, QueryPos = 0x00000002, SetPos = 0x00000003, GetState = 0x00000004, GetTaskbarPos = 0x00000005, Activate = 0x00000006, GetAutoHideBar = 0x00000007, SetAutoHideBar = 0x00000008, WindowPosChanged = 0x00000009, SetState = 0x0000000A, } private const string ClassName = "Shell_TrayWnd"; private static APPBARDATA _appBarData; /// <summary>Static initializer of the <see cref="Taskbar" /> class.</summary> static Taskbar() { _appBarData = new APPBARDATA { cbSize = (uint)Marshal.SizeOf(typeof(APPBARDATA)), hWnd = FindWindow(Taskbar.ClassName, null) }; } /// <summary> /// Gets a value indicating whether the taskbar is always on top of other windows. /// </summary> /// <value><c>true</c> if the taskbar is always on top of other windows; otherwise, <c>false</c>.</value> /// <remarks>This property always returns <c>false</c> on Windows 7 and newer.</remarks> public static bool AlwaysOnTop { get { int state = SHAppBarMessage(AppBarMessage.GetState, ref _appBarData).ToInt32(); return ((ABS)state).HasFlag(ABS.AlwaysOnTop); } } /// <summary> /// Gets a value indicating whether the taskbar is automatically hidden when inactive. /// </summary> /// <value><c>true</c> if the taskbar is set to auto-hide is enabled; otherwise, <c>false</c>.</value> public static bool AutoHide { get { int state = SHAppBarMessage(AppBarMessage.GetState, ref _appBarData).ToInt32(); return ((ABS)state).HasFlag(ABS.AutoHide); } } /// <summary>Gets the current display bounds of the taskbar.</summary> public static Rectangle CurrentBounds { get { var rect = new RECT(); if (GetWindowRect(Handle, ref rect)) return Rectangle.FromLTRB(rect.Left, rect.Top, rect.Right, rect.Bottom); return Rectangle.Empty; } } /// <summary>Gets the display bounds when the taskbar is fully visible.</summary> public static Rectangle DisplayBounds { get { if (RefreshBoundsAndPosition()) return Rectangle.FromLTRB(_appBarData.rect.Left, _appBarData.rect.Top, _appBarData.rect.Right, _appBarData.rect.Bottom); return CurrentBounds; } } /// <summary>Gets the taskbar's window handle.</summary> public static IntPtr Handle { get { return _appBarData.hWnd; } } /// <summary>Gets the taskbar's position on the screen.</summary> public static TaskbarPosition Position { get { if (RefreshBoundsAndPosition()) return (TaskbarPosition)_appBarData.uEdge; return TaskbarPosition.Unknown; } } /// <summary>Hides the taskbar.</summary> public static void Hide() { const int SW_HIDE = 0; ShowWindow(Handle, SW_HIDE); } /// <summary>Shows the taskbar.</summary> public static void Show() { const int SW_SHOW = 1; ShowWindow(Handle, SW_SHOW); } private static bool RefreshBoundsAndPosition() { //! SHAppBarMessage returns IntPtr.Zero **if it fails** return SHAppBarMessage(AppBarMessage.GetTaskbarPos, ref _appBarData) != IntPtr.Zero; } #region DllImports [DllImport("user32.dll", SetLastError = true)] private static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect); [DllImport("shell32.dll", SetLastError = true)] private static extern IntPtr SHAppBarMessage(AppBarMessage dwMessage, [In] ref APPBARDATA pData); [DllImport("user32.dll")] private static extern int ShowWindow(IntPtr hwnd, int command); #endregion DllImports [StructLayout(LayoutKind.Sequential)] private struct APPBARDATA { public uint cbSize; public IntPtr hWnd; public uint uCallbackMessage; public AppBarEdge uEdge; public RECT rect; public int lParam; } [StructLayout(LayoutKind.Sequential)] private struct RECT { public int Left; public int Top; public int Right; public int Bottom; } } }