2010-04-26 15 views
9

Me gustaría mostrar una pequeña ventana emergente al lado del área de notificación. Es similar a lo que Outlook/Skype/Live! Messenger/etc lo hace cuando muestra la notificación sobre un nuevo mensaje. En mi caso, tendrá algunos controles de entrada (cuadro de texto, selector de fecha y hora, botones ...) para que una burbuja simple no funcione..NET: ¿Cómo colocar mi ventana cerca del área de notificación (systray)?

El truco está en hacer esto correctamente cuando el usuario tiene múltiples monitores y/o la barra de tareas no se encuentra en la parte inferior de la pantalla. No pude encontrar ninguna función que me permitiera determinar la posición y la orientación de la barra de tareas/área de notificación.

+0

cualquier todo completo ejemplo de código fuente? – Kiquenet

+0

@alhambraeidos - Creo que la respuesta aceptada contiene toda la información que necesita. No tengo el código fuente en línea, pero no es muy difícil hacer algo así. ¿Tienes algún problema específico? –

Respuesta

8

Uso WinAPI llama para encontrar la posición de barra de tareas, y la posición de la ventana de acuerdo con ella

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

¡Agradable! ¡Gracias! :) –

+0

Sin embargo, codifica el nombre de la clase de la barra de tareas, que no es un contrato sino un detalle de implementación. ¿Y qué hay de las personas que usan otro caparazón? – Joey

+0

http://www.codeproject.com/KB/shell/trayposition.aspx Otro enfoque conservó el comentario de johannes rössel, sencillo de portar a C# imo –

0

Es necesario para obtener la ubicación real de su icono de notificación, y coloque su emergente ventana cerca de eso (o donde quieras).

Necesita traducir sus ubicaciones XY en relación con el escritorio (s). AFAIK, no hay una función directa, incluso en Win32 API, que puede darle la respuesta directamente.

Estos sitios ayudar a You-
1. http://forum.codecall.net/managed-c/262-dual-monitors-window-position.html
2. http://msdn.microsoft.com/en-us/magazine/cc188759.aspx

Cuestiones relacionadas