10

通知領域の横に小さなポップアップ ウィンドウを表示したいと思います。Outlook/Skype/Live! に似ています。Messenger/etc は、新しいメッセージに関する通知を表示するときに行います。私の場合、いくつかの入力コントロール (テキストボックス、datetimepicker、ボタンなど) があるため、単純なバブルではうまくいきません。

ユーザーが複数のモニターを使用している場合、および/またはタスクバーが画面の下部にない場合、これを正しく行うのが秘訣です。タスクバー/通知領域の位置と向きを決定できる機能が見つかりませんでした。

4

2 に答える 2

9

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;
}
于 2010-04-26T09:22:16.377 に答える
0

通知アイコンの実際の位置を取得し、ポップアップ ウィンドウをその近く (または好きな場所) に配置する必要があります。

デスクトップを基準にして XY 位置を変換する必要があります。私の知る限り、答えを直接与えることができる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

于 2010-04-26T09:26:03.363 に答える