2011-02-03 10 views
9


Tengo un programa que permite al usuario abrir varios formularios. Una vez que se produce un evento dado (por ejemplo, 30 segundos), necesito llamar la atención del usuario sobre el Formulario que desencadenó el evento, sin robar el foco. ya obtener el formulario en la parte superior conObtenga la atención del usuario sin robar el foco

f.TopMost = true; 

pero me gustaría poner en práctica alguna alternativa a eso. Como cambiar el color del borde del marco parece una tarea casi imposible (esta solución hubiera sido la mejor), ¿alguien tiene alguna idea sobre cómo llamar la atención sin robar el foco?

Respuesta

19

Opción A: Necesita usar FlashWindowEx desde la API de Windows. Esto no está disponible en .NET, por lo que debe usar PInvoke.

Opción B: utilice una punta de globo desde la bandeja del sistema. Esto está integrado en .NET, pero requiere que su aplicación use un ícono de notificación, que es posible que no desee. Más detalles aquí: http://msdn.microsoft.com/en-us/library/system.windows.forms.notifyicon.showballoontip.aspx

Aquí está el ejemplo de cómo utilizar la opción A:

pInvoke.net tiene el mejor ejemplo: http://pinvoke.net/default.aspx/user32.FlashWindowEx

[DllImport("user32.dll")] 
[return: MarshalAs(UnmanagedType.Bool)] 
static extern bool FlashWindowEx(ref FLASHWINFO pwfi); 

tipos definidos por el usuario:

[StructLayout(LayoutKind.Sequential)] 
public struct FLASHWINFO 
{ 
    public UInt32 cbSize; 
    public IntPtr hwnd; 
    public UInt32 dwFlags; 
    public UInt32 uCount; 
    public UInt32 dwTimeout; 
} 

Notas:

//Stop flashing. The system restores the window to its original state. 
public const UInt32 FLASHW_STOP = 0; 
//Flash the window caption. 
public const UInt32 FLASHW_CAPTION = 1; 
//Flash the taskbar button. 
public const UInt32 FLASHW_TRAY = 2; 
//Flash both the window caption and taskbar button. 
//This is equivalent to setting the FLASHW_CAPTION | FLASHW_TRAY flags. 
public const UInt32 FLASHW_ALL = 3; 
//Flash continuously, until the FLASHW_STOP flag is set. 
public const UInt32 FLASHW_TIMER = 4; 
//Flash continuously until the window comes to the foreground. 
public const UInt32 FLASHW_TIMERNOFG = 12; 

Consejos & Trucos:

¡Añada algunos!

Código de ejemplo:

/// <summary> 
/// Flashes a window 
/// </summary> 
/// <param name="hWnd">The handle to the window to flash</param> 
/// <returns>whether or not the window needed flashing</returns> 
public static bool FlashWindowEx(IntPtr hWnd) 
{ 
    FLASHWINFO fInfo = new FLASHWINFO(); 

    fInfo.cbSize = Convert.ToUInt32(Marshal.SizeOf(fInfo)); 
    fInfo.hwnd = hWnd; 
    fInfo.dwFlags = FLASHW_ALL; 
    fInfo.uCount = UInt32.MaxValue; 
    fInfo.dwTimeout = 0; 

    return FlashWindowEx(ref fInfo); 
} 

...

/// Minor adjust to the code above 
/// <summary> 
/// Flashes a window until the window comes to the foreground 
/// Receives the form that will flash 
/// </summary> 
/// <param name="hWnd">The handle to the window to flash</param> 
/// <returns>whether or not the window needed flashing</returns> 
public static bool FlashWindowEx(Form frm) 
{ 
     IntPtr hWnd = frm.Handle; 
     FLASHWINFO fInfo = new FLASHWINFO(); 

     fInfo.cbSize = Convert.ToUInt32(Marshal.SizeOf(fInfo)); 
     fInfo.hwnd = hWnd; 
     fInfo.dwFlags = FLASHW_ALL | FLASHW_TIMERNOFG; 
     fInfo.uCount = UInt32.MaxValue; 
     fInfo.dwTimeout = 0; 

     return FlashWindowEx(ref fInfo); 
} 

Aquí está el ejemplo Microsoft oficial: http://msdn.microsoft.com/en-us/library/ms679347(v=vs.85).aspx

[DllImport("user32.dll")] 
    [return: MarshalAs(UnmanagedType.Bool)] 
    public static extern bool FlashWindowEx(ref FLASHWINFO pwfi); 

    [StructLayout(LayoutKind.Sequential)] 
    public struct FLASHWINFO 
    { 
     /// <summary> 
     /// The size of the structure in bytes. 
     /// </summary> 
     public uint cbSize; 
     /// <summary> 
     /// A Handle to the Window to be Flashed. The window can be either opened or minimized. 
     /// </summary> 
     public IntPtr hwnd; 
     /// <summary> 
     /// The Flash Status. 
     /// </summary> 
     public FlashWindowFlags dwFlags; //uint 
     /// <summary> 
     /// The number of times to Flash the window. 
     /// </summary> 
     public uint uCount; 
     /// <summary> 
     /// The rate at which the Window is to be flashed, in milliseconds. If Zero, the function uses the default cursor blink rate. 
     /// </summary> 
     public uint dwTimeout; 
    } 


    public enum FlashWindowFlags : uint 
    { 
     /// <summary> 
     /// Stop flashing. The system restores the window to its original state. 
     /// </summary> 
     FLASHW_STOP = 0, 

     /// <summary> 
     /// Flash the window caption. 
     /// </summary> 
     FLASHW_CAPTION = 1, 

     /// <summary> 
     /// Flash the taskbar button. 
     /// </summary> 
     FLASHW_TRAY = 2, 

     /// <summary> 
     /// Flash both the window caption and taskbar button. 
     /// This is equivalent to setting the FLASHW_CAPTION | FLASHW_TRAY flags. 
     /// </summary> 
     FLASHW_ALL = 3, 

     /// <summary> 
     /// Flash continuously, until the FLASHW_STOP flag is set. 
     /// </summary> 
     FLASHW_TIMER = 4, 

     /// <summary> 
     /// Flash continuously until the window comes to the foreground. 
     /// </summary> 
     FLASHW_TIMERNOFG = 12 
    } 


    public static bool FlashWindow(IntPtr hWnd, 
            FlashWindowFlags fOptions, 
            uint FlashCount, 
            uint FlashRate) 
    { 
     if(IntPtr.Zero != hWnd) 
     { 
      FLASHWINFO fi = new FLASHWINFO(); 
      fi.cbSize = (uint)Marshal.SizeOf(typeof(FLASHWINFO)); 
      fi.dwFlags = fOptions; 
      fi.uCount = FlashCount; 
      fi.dwTimeout = FlashRate; 
      fi.hwnd = hWnd; 

      return FlashWindowEx(ref fi); 
     } 
     return false; 
    } 

    public static bool StopFlashingWindow(IntPtr hWnd) 
    { 
     if(IntPtr.Zero != hWnd) 
     { 
      FLASHWINFO fi = new FLASHWINFO(); 
      fi.cbSize = (uint)Marshal.SizeOf(typeof(FLASHWINFO)); 
      fi.dwFlags = (uint)FlashWindowFlags.FLASHW_STOP; 
      fi.hwnd = hWnd; 

      return FlashWindowEx(ref fi); 
     } 
     return false; 
    } 
+0

¡Buena llamada sobre el uso de 'NotifyIcon'! –

+0

Importante: en Windows 7 algunos usuarios informaron esto como No funciona. Después de algunas investigaciones, descubrí que el motivo es que si su aplicación tiene varias ventanas y si alguna de esas ventanas está activa mientras llama a esta API para mostrar otra ventana, no funcionará. Solo funcionará si todas las ventanas de su programa están inactivas. Si está atascado en el primer escenario, entonces use api FlashWindow anterior: http://pinvoke.net/default.aspx/user32/FlashWindow.html – tunafish24

7

En Windows 7, una barra de progreso en una forma está representada en su tarea botón r; podrías aprovechar eso. También debe haber una manera de simplemente resaltar el botón de la barra de tareas, como lo hacen los programas de MI cuando recibes un mensaje nuevo.

+0

Me encantaría ver cómo simplemente resaltar el botón de la barra de tareas en lugar de mostrarlo ... teniendo problemas para encontrar buenas muestras de código que lo hagan. –

Cuestiones relacionadas