我的wpf应用程序应该打开一个靠近通知区域的窗口。 当用户点击托盘图标打开一个窗口。 所以我需要在通知区域相同的屏幕上的窗口。 现在我只是得到任务栏位置: https ://stackoverflow.com/a/8581546/1502011和屏幕上的任务栏rectlange https://stackoverflow.com/a/3677319/1502011然后我用它来find我的窗口像:
//xaml.cs var taskBarLocation = GetTaskBarLocation(); var taskBarPosition = GetTaskbarPosition(); this.Left = taskBarLocation == Location.Left ? taskBarPosition.Width : SystemParameters.WorkArea.Width - Width; this.Top = taskBarLocation == Location.Top ? taskBarPosition.Height : SystemParameters.WorkArea.Height - Height;
它只有在通知区域被放置在主屏幕上时才起作用。 据我了解,我应该使用WinApi将我的窗口放在其他显示器上,但我甚至不知道如何find通知区域的屏幕。 任何帮助将不胜感激。
好的,因为
1)Wpf窗口位置不关心监视器(它是“控制面板\所有控制面板项目\显示\屏幕分辨率”的坐标,而不是在当前的屏幕坐标)
2)WinApi方法SHAppBarMessage(5,参考数据)也适用于全局坐标
3)每个屏幕对象都有Bounds属性,代表全局坐标下屏幕的位置
解决办法很简单:
public static class TaskBarLocationProvider { // P/Invoke goo: private const int ABM_GETTASKBARPOS = 5; [DllImport("shell32.dll")] private static extern IntPtr SHAppBarMessage(int msg, ref AppBarData data); /// <summary> /// Where is task bar located (at top of the screen, at bottom (default), or at the one of sides) /// </summary> private enum Dock { Left = 0, Top = 1, Right = 2, Bottom = 3 } private struct Rect { public int Left, Top, Right, Bottom; } private struct AppBarData { public int cbSize; public IntPtr hWnd; public int uCallbackMessage; public Dock Dock; public Rect rc; public IntPtr lParam; } private static Rectangle GetTaskBarCoordinates(Rect rc) { return new Rectangle(rc.Left, rc.Top, rc.Right - rc.Left, rc.Bottom - rc.Top); } private static AppBarData GetTaskBarLocation() { var data = new AppBarData(); data.cbSize = Marshal.SizeOf(data); IntPtr retval = SHAppBarMessage(ABM_GETTASKBARPOS, ref data); if (retval == IntPtr.Zero) { throw new Win32Exception("WinAPi Error: does'nt work api method SHAppBarMessage"); } return data; } private static Screen FindScreenWithTaskBar(Rectangle taskBarCoordinates) { foreach (var screen in Screen.AllScreens) { if (screen.Bounds.Contains(taskBarCoordinates)) { return screen; } } return Screen.PrimaryScreen; } /// <summary> /// Calculate wpf window position for place it near to taskbar area /// </summary> /// <param name="windowWidth">target window height</param> /// <param name="windowHeight">target window width</param> /// <param name="left">Result left coordinate <see cref="System.Windows.Window.Left"/></param> /// <param name="top">Result top coordinate <see cref="System.Windows.Window.Top"/></param> public static void CalculateWindowPositionByTaskbar(double windowWidth, double windowHeight, out double left, out double top) { var taskBarLocation = GetTaskBarLocation(); var taskBarRectangle = GetTaskBarCoordinates(taskBarLocation.rc); var screen = FindScreenWithTaskBar(taskBarRectangle); left = taskBarLocation.Dock == Dock.Left ? screen.Bounds.X + taskBarRectangle.Width : screen.Bounds.X + screen.WorkingArea.Width - windowWidth; top = taskBarLocation.Dock == Dock.Top ? screen.Bounds.Y + taskBarRectangle.Height : screen.Bounds.Y + screen.WorkingArea.Height - windowHeight; }
和xaml.cs中的用法
private void SetWindowPosition() { double left, right; TaskBarLocationProvider.CalculateWindowPositionByTaskbar(this.Width, this.Height, out left, out right); Left = left; Top = right; }