.NET:如何将我的窗口放置在通知区域(系统托盘)附近?

发布于 2024-08-30 02:56:04 字数 202 浏览 4 评论 0原文

我想在通知区域旁边显示一个小弹出窗口。与 Outlook/Skype/Live 类似! Messenger/etc 在显示有关新消息的通知时会执行此操作。就我而言,它将有一些输入控件(文本框、日期时间选择器、按钮...),因此简单的气泡不起作用。

诀窍是当用户有多个显示器和/或任务栏不在屏幕底部时正确执行此操作。我找不到任何可以让我确定任务栏/通知区域的位置和方向的功能。

I'd like to display a little popup window next to the notification area. It's similar to what Outlook/Skype/Live! Messenger/etc does when it displays the notification about a new message. In my case it will have some input controls (textbox, datetimepicker, buttons...) so a simple bubble won't do.

The trick is doing this correctly when the user has multiple monitors and/or the taskbar is not located at the bottom of the screen. I could not find any functions that would let me determine the position and orientation of the taskbar/notification area.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

皇甫轩 2024-09-06 02:56:04

使用 WinAPI 调用查找任务栏位置,并根据它定位窗口

C# 示例

class Program
{
    static void Main(string[] args)
    {
        Taskbar taskbar = new Taskbar();
        Console.WriteLine("Position: {0}, AlwaysOnTop: {1}; AutoHide: {2}; Bounds: {3}", taskbar.Position, taskbar.AlwaysOnTop, taskbar.AutoHide, taskbar.Bounds);

        Console.ReadLine();
    }
}

public enum TaskbarPosition
{
    Unknown = -1,
    Left,
    Top,
    Right,
    Bottom,
}

public sealed class Taskbar
{
    private const string ClassName = "Shell_TrayWnd";

    public Rectangle Bounds
    {
        get;
        private set;
    }
    public TaskbarPosition Position
    {
        get;
        private set;
    }
    public Point Location
    {
        get
        {
            return this.Bounds.Location;
        }
    }
    public Size Size
    {
        get
        {
            return this.Bounds.Size;
        }
    }
    //Always returns false under Windows 7
    public bool AlwaysOnTop
    {
        get;
        private set;
    }
    public bool AutoHide
    {
        get;
        private set;
    }

    public Taskbar()
    {
        IntPtr taskbarHandle = User32.FindWindow(Taskbar.ClassName, null);

        APPBARDATA data = new APPBARDATA();
        data.cbSize = (uint) Marshal.SizeOf(typeof(APPBARDATA));
        data.hWnd = taskbarHandle;
        IntPtr result = Shell32.SHAppBarMessage(ABM.GetTaskbarPos, ref data);
        if (result == IntPtr.Zero)
            throw new InvalidOperationException();

        this.Position = (TaskbarPosition) data.uEdge;
        this.Bounds = Rectangle.FromLTRB(data.rc.left, data.rc.top, data.rc.right, data.rc.bottom);

        data.cbSize = (uint) Marshal.SizeOf(typeof(APPBARDATA));
        result = Shell32.SHAppBarMessage(ABM.GetState, ref data);
        int state = result.ToInt32();
        this.AlwaysOnTop = (state & ABS.AlwaysOnTop) == ABS.AlwaysOnTop;
        this.AutoHide = (state & ABS.Autohide) == ABS.Autohide;
    }
}

public enum ABM : uint
{
    New = 0x00000000,
    Remove = 0x00000001,
    QueryPos = 0x00000002,
    SetPos = 0x00000003,
    GetState = 0x00000004,
    GetTaskbarPos = 0x00000005,
    Activate = 0x00000006,
    GetAutoHideBar = 0x00000007,
    SetAutoHideBar = 0x00000008,
    WindowPosChanged = 0x00000009,
    SetState = 0x0000000A,
}

public enum ABE : uint
{
    Left = 0,
    Top = 1,
    Right = 2,
    Bottom = 3
}

public static class ABS
{
    public const int Autohide = 0x0000001;
    public const int AlwaysOnTop = 0x0000002;
}

public static class Shell32
{
    [DllImport("shell32.dll", SetLastError = true)]
    public static extern IntPtr SHAppBarMessage(ABM dwMessage, [In] ref APPBARDATA pData);
}

public static class User32
{
    [DllImport("user32.dll", SetLastError = true)]
    public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
}

[StructLayout(LayoutKind.Sequential)]
public struct APPBARDATA
{
    public uint cbSize;
    public IntPtr hWnd;
    public uint uCallbackMessage;
    public ABE uEdge;
    public RECT rc;
    public int lParam;
}

[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
    public int left;
    public int top;
    public int right;
    public int bottom;
}

Use WinAPI calls to find the TaskBar position, and position your window according to it

C# Example

class Program
{
    static void Main(string[] args)
    {
        Taskbar taskbar = new Taskbar();
        Console.WriteLine("Position: {0}, AlwaysOnTop: {1}; AutoHide: {2}; Bounds: {3}", taskbar.Position, taskbar.AlwaysOnTop, taskbar.AutoHide, taskbar.Bounds);

        Console.ReadLine();
    }
}

public enum TaskbarPosition
{
    Unknown = -1,
    Left,
    Top,
    Right,
    Bottom,
}

public sealed class Taskbar
{
    private const string ClassName = "Shell_TrayWnd";

    public Rectangle Bounds
    {
        get;
        private set;
    }
    public TaskbarPosition Position
    {
        get;
        private set;
    }
    public Point Location
    {
        get
        {
            return this.Bounds.Location;
        }
    }
    public Size Size
    {
        get
        {
            return this.Bounds.Size;
        }
    }
    //Always returns false under Windows 7
    public bool AlwaysOnTop
    {
        get;
        private set;
    }
    public bool AutoHide
    {
        get;
        private set;
    }

    public Taskbar()
    {
        IntPtr taskbarHandle = User32.FindWindow(Taskbar.ClassName, null);

        APPBARDATA data = new APPBARDATA();
        data.cbSize = (uint) Marshal.SizeOf(typeof(APPBARDATA));
        data.hWnd = taskbarHandle;
        IntPtr result = Shell32.SHAppBarMessage(ABM.GetTaskbarPos, ref data);
        if (result == IntPtr.Zero)
            throw new InvalidOperationException();

        this.Position = (TaskbarPosition) data.uEdge;
        this.Bounds = Rectangle.FromLTRB(data.rc.left, data.rc.top, data.rc.right, data.rc.bottom);

        data.cbSize = (uint) Marshal.SizeOf(typeof(APPBARDATA));
        result = Shell32.SHAppBarMessage(ABM.GetState, ref data);
        int state = result.ToInt32();
        this.AlwaysOnTop = (state & ABS.AlwaysOnTop) == ABS.AlwaysOnTop;
        this.AutoHide = (state & ABS.Autohide) == ABS.Autohide;
    }
}

public enum ABM : uint
{
    New = 0x00000000,
    Remove = 0x00000001,
    QueryPos = 0x00000002,
    SetPos = 0x00000003,
    GetState = 0x00000004,
    GetTaskbarPos = 0x00000005,
    Activate = 0x00000006,
    GetAutoHideBar = 0x00000007,
    SetAutoHideBar = 0x00000008,
    WindowPosChanged = 0x00000009,
    SetState = 0x0000000A,
}

public enum ABE : uint
{
    Left = 0,
    Top = 1,
    Right = 2,
    Bottom = 3
}

public static class ABS
{
    public const int Autohide = 0x0000001;
    public const int AlwaysOnTop = 0x0000002;
}

public static class Shell32
{
    [DllImport("shell32.dll", SetLastError = true)]
    public static extern IntPtr SHAppBarMessage(ABM dwMessage, [In] ref APPBARDATA pData);
}

public static class User32
{
    [DllImport("user32.dll", SetLastError = true)]
    public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
}

[StructLayout(LayoutKind.Sequential)]
public struct APPBARDATA
{
    public uint cbSize;
    public IntPtr hWnd;
    public uint uCallbackMessage;
    public ABE uEdge;
    public RECT rc;
    public int lParam;
}

[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
    public int left;
    public int top;
    public int right;
    public int bottom;
}
尤怨 2024-09-06 02:56:04

您需要获取通知图标的实际位置,并将弹出窗口放置在该图标附近(或您喜欢的任何位置)。

您需要相对于桌面平移 XY 位置。 AFAIK,即使在Win32 API中也没有直接的函数可以直接给你答案。

这些网站将为您提供帮助-
1. http://forum.codecall.net/ Managed-c/262-dual-monitors-window-position.html
2. http://msdn.microsoft.com/en-us/magazine/ cc188759.aspx

You need to get the actual location of your notification icon, and place your pop-up window near that (or wherever you like).

You need to translate your XY locations relative to desktop(s). AFAIK, there are no direct function, even in Win32 API which can directly give you the answer.

These sites will help you-
1. http://forum.codecall.net/managed-c/262-dual-monitors-window-position.html
2. http://msdn.microsoft.com/en-us/magazine/cc188759.aspx

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文