Я хочу знать, как получить прямоугольник (нижний, верхний, левый и правый), который занимает панель задач. Как мне сделать это на С#?
Как получить положение и размер панели задач?
Ответ 1
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;
}
Ответ 2
Это на самом деле намного сложнее, чем показано выше. Во-первых, панель задач не обязательно должна быть на основном экране, ее можно перетащить на любой экран. С другой стороны, в теории может быть что-то закрепленное на каждом краю каждого данного экрана. Приведенный выше код неверно предполагает, что нахождение чего-либо пристыкованного к одному ребру исключает все остальные ребра.
Единственный способ, которым местоположение панели задач могло быть окончательно получено из границ по сравнению с рабочей областью, было бы, если бы только один край из всех экранов был прикреплен к нему.
Следующая функция возвращает массив прямоугольников, каждый из которых представляет закрепленную панель задач, и записывает счетчик в свой параметр 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
Или для тех из вас, кто предпочитает С#... (Примечание: этот портированный код не проверен)
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;
}
Ответ 3
Основываясь на ответе Дэвида, вот лучшая реализация, которая использует P/Invoke для правильного определения размещения и размера панели задач. Единственное ограничение, которое я знаю до сих пор, это то, что он не возвращает правильные границы, когда несколько мониторов настроены для отображения в расширенном режиме.
Код со всеми последующими обновлениями доступен по адресу https://git.io/v9bCx.
/******************************************************************************
* Name: Taskbar.cs
* Description: Class to get the taskbar 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 window handle.</summary>
public static IntPtr Handle
{
get { return _appBarData.hWnd; }
}
/// <summary>Gets the taskbar 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;
}
}
}
Ответ 4
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;
}
Ответ 5
Это ответ от Mark McGinty
в С#.
Этот код возвращает все панели задач в список переходов:
- 0 прямоугольников означает, что панель задач скрыта;
- 1 прямоугольник - это позиция панели задач;
- 2+ очень редко, это означает, что у нас есть несколько мониторов, и мы не используем
Extend these displays
для создания единого виртуального рабочего стола.
Работает в любой ситуации
Он хорошо работает с:
- Windows 7 (почти наверняка будет работать на Windows 8.1 и Windows 10).
- Все комбинации настроек.
Код С#
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;
}
Ответ 6
Это простой пример использования winforms с поддержкой wpf и multi screen:
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
}
Ответ 7
Это как получить высоту панели задач (используя WPF)
int PSBH = System.Windows.Forms.Screen.PrimaryScreen.Bounds
int TaskBarHeight = PSBH - System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Height;
Если вы хотите, чтобы учитывать dpi
int PSH = SystemParameters.PrimaryScreenHeight;
int PSBH = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height;
double ratio = PSH / PSBH;
int TaskBarHeight = PSBH - System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Height;
TaskBarHeight *= ratio;