¿Cómo obtengo la posición y el tamaño de la barra de tareas?

Quiero saber cómo obtener el rectángulo (abajo, arriba, izquierda y derecha) que ocupa la barra de tareas. ¿Cómo hago esto en C #?

  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; } 

De hecho, es mucho más complicado de lo que se muestra arriba. Por un lado, la barra de tareas no tiene que estar en la pantalla principal, se puede arrastrar a cualquier pantalla. Por otro lado, en teoría podría haber algo atracado en cada borde de cada pantalla. El código anterior asume incorrectamente que encontrar algo atracado en un borde excluye todos los otros bordes.

La única forma en que la ubicación de la barra de tareas podría derivarse definitivamente de los límites en comparación con el área de trabajo sería si solo un borde de todas las pantallas tuviera algo acoplado.

La siguiente función devuelve una matriz de rectangularjs, cada uno representa una barra de tareas acoplada, y escribe el recuento en su parámetro byref. Si ese recuento es 1, el elemento 0 de la matriz devuelta es el rectángulo ocupado por la barra de tareas. Si es mayor que 1, ¿es tiempo de adivinar?

 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 

O para aquellos de ustedes que prefieren C # … (Nota: este código portado no se ha probado)

 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; } 

Según la respuesta de David , aquí hay una mejor implementación que usa P / Invoke para determinar correctamente la ubicación y el tamaño de la barra de tareas. La única limitación que conozco hasta ahora es que no devuelve los límites correctos cuando varios monitores están configurados para mostrarse en modo extendido.

El código con todas las actualizaciones posteriores está disponible como una esencia en https://git.io/v9bCx .

 /****************************************************************************** * 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; /// Static initializer of the  class. static Taskbar() { _appBarData = new APPBARDATA { cbSize = (uint)Marshal.SizeOf(typeof(APPBARDATA)), hWnd = FindWindow(Taskbar.ClassName, null) }; } ///  /// Gets a value indicating whether the taskbar is always on top of other windows. ///  /// true if the taskbar is always on top of other windows; otherwise, false. /// This property always returns false on Windows 7 and newer. public static bool AlwaysOnTop { get { int state = SHAppBarMessage(AppBarMessage.GetState, ref _appBarData).ToInt32(); return ((ABS)state).HasFlag(ABS.AlwaysOnTop); } } ///  /// Gets a value indicating whether the taskbar is automatically hidden when inactive. ///  /// true if the taskbar is set to auto-hide is enabled; otherwise, false. public static bool AutoHide { get { int state = SHAppBarMessage(AppBarMessage.GetState, ref _appBarData).ToInt32(); return ((ABS)state).HasFlag(ABS.AutoHide); } } /// Gets the current display bounds of the taskbar. 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; } } /// Gets the display bounds when the taskbar is fully visible. public static Rectangle DisplayBounds { get { if (RefreshBoundsAndPosition()) return Rectangle.FromLTRB(_appBarData.rect.Left, _appBarData.rect.Top, _appBarData.rect.Right, _appBarData.rect.Bottom); return CurrentBounds; } } /// Gets the taskbar's window handle. public static IntPtr Handle { get { return _appBarData.hWnd; } } /// Gets the taskbar's position on the screen. public static TaskbarPosition Position { get { if (RefreshBoundsAndPosition()) return (TaskbarPosition)_appBarData.uEdge; return TaskbarPosition.Unknown; } } /// Hides the taskbar. public static void Hide() { const int SW_HIDE = 0; ShowWindow(Handle, SW_HIDE); } /// Shows the taskbar. 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; } } } 
 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; } 

Esta es la respuesta de Mark McGinty en C #.

Este código recupera todas las barras de tareas como una lista de rectangularjs:

  • 0 rectangularjs significa que la barra de tareas está oculta;
  • 1 rectángulo es la posición de la barra de tareas;
  • 2+ es muy raro, significa que tenemos múltiples monitores, y no estamos usando Extend these displays para crear un solo escritorio virtual.

Funciona en cada situación

Funciona bien con:

  • Windows 7 (seguramente funcionará en Windows 8.1 y Windows 10).
  • Todas las combinaciones de configuraciones

enter image description here

C # Code

 public static List FindDockedTaskBars() { List dockedRects = new List(); 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; } 

Este es un ejemplo simple que usa winforms con wpf y soporte multi pantalla:

 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 }