2010-05-15 8 views
5

Tengo una aplicación C# winforms que se ejecuta en segundo plano, esperando que se presionen las teclas rápidas. Cuando se presiona una tecla rápida, mi forma hace una breve aparición. El formulario siempre se está ejecutando, pero se establece en oculto hasta que reciba un evento de tecla de acceso rápido, en ese momento establecí la propiedad visible en verdadero. El código se ve así:¿Cómo evitar que mi aplicación C# winforms robe el foco cuando establezco el visible correctamente en verdadero?

void hook_volumeDown(object sender, KeyPressedEventArgs e) 
{ 
    this.Visible = true; 
} 

Cabe señalar que la propiedad superior de este formulario se establece en verdadero.

La parte realmente extraña es que, después de que mi aplicación C# ha robado el foco de otra aplicación, nunca volverá a hacerlo. Por ejemplo: inicio mi aplicación, luego lanzo una aplicación fullscreep como Team Fortress 2. Luego presiono mi tecla de acceso directo. Team Fortress 2 se minimiza, y veo mi forma. Entonces, sin embargo, puedo restaurar TF2, y presionar mi tecla de acceso de nuevo todo lo que quiero (con el efecto deseado), y TF2 permanecerá enfocado.

En cualquier caso, estoy buscando una manera de arreglar esto. He encontrado muchas preguntas aquí que cubren problemas similares, pero todas están relacionadas con la creación/lanzamiento de un nuevo formulario, sin hacer que uno existente sea visible (a menos que me haya perdido algo). Podría volver a trabajar la aplicación para crear un nuevo formulario cada vez que lo necesite, pero eso implicaría crear otra forma de ser invisible todo el tiempo solo para esperar los eventos de teclas de acceso rápido, así que preferiría dejarlo como está.

¿Alguna idea?

+0

No estoy seguro de seguir ... ¿estás diciendo que funciona como debería * excepto * por primera vez? –

Respuesta

6

Creo que su problema está relacionado con el hecho de que Visible = true se comporta de manera diferente entre la primera y las siguientes llamadas. La primera vez que se llama a visible y no se ha creado el identificador de ventana, la ventana se crea llamando a CreateWindowEx que tiene algunos parámetros de estilo que controlan cómo debe comportarse la ventana. Creo que debe asegurarse de que la ventana se crea con el estilo WS_EX_NOACTIVATE, lo que puede hacer sobrescribiendo CreateParams.

Otras cosas para probar:

1) La función ShowWindow (utilizado por Visible = true) ignora el parámetro enfoque la primera vez que se llama (http://msdn.microsoft.com/en-us/library/ms633548%28VS.85%29.aspx) si el programa ofrece una estructura STARTUPINFO. Indague en el reflector y descubra si la clase Form proporciona una estructura STARTUPINFO y, si es así, cómo manipularla.

2) El formulario tiene una propiedad ShowWithoutActivation que puede anularse y establecerse en verdadero, ¿ha anulado esto?

Disculpa las "no hay respuesta exacta", pero espero que al menos te brinde algunos puntos de partida para una mayor investigación. Buena suerte.

+1

Gracias, anulando ShowWithoutActivation resultó ser la solución perfecta. Una línea de código y todo está arreglado. – Fopedush

+0

Reemplazar ShowWithoutActivation turned IS es la solución perfecta para mí también. – beppe9000

1

Ver KeyPressedEventArgs en su función se ve realmente extraño. Las teclas de acceso rápido pueden implementarse mediante P/Invocando la función API RegisterHotKey(). Envía un mensaje a su ventana cuando se presiona la tecla directa. Aquí hay un ejemplo de una forma que es invisible al inicio, se activa cuando se presiona la tecla rápida. Ctrl + Alt + T en este caso:

using System; 
using System.Windows.Forms; 
using System.Runtime.InteropServices; 

namespace WindowsFormsApplication1 { 
    public partial class Form1 : Form { 
     private const int MYKEYID = 0; // In case you want to register more than one... 
     public Form1() { 
      InitializeComponent(); 
      this.FormClosing += (s, args) => UnregisterHotKey(this.Handle, MYKEYID); 
     } 
     protected override void SetVisibleCore(bool value) { 
      if (value && !this.IsHandleCreated) { 
       this.CreateHandle(); 
       RegisterHotKey(this.Handle, MYKEYID, MOD_CONTROL + MOD_SHIFT, Keys.U); 
       value = false; 
      } 
      base.SetVisibleCore(value); 
     } 
     protected override void WndProc(ref Message m) { 
      if (m.Msg == WM_HOTKEY && m.WParam.ToInt32() == MYKEYID) { 
       this.Visible = true; 
       if (this.WindowState == FormWindowState.Minimized) 
        this.WindowState = FormWindowState.Normal; 
       SetForegroundWindow(this.Handle); 
      } 
      base.WndProc(ref m); 
     } 
     // P/Invoke declarations 
     private const int WM_HOTKEY = 0x312; 
     private const int MOD_ALT = 1; 
     private const int MOD_CONTROL = 2; 
     private const int MOD_SHIFT = 4; 
     [DllImport("user32.dll")] 
     private static extern int RegisterHotKey(IntPtr hWnd, int id, int modifier, Keys vk); 
     [DllImport("user32.dll")] 
     private static extern bool UnregisterHotKey(IntPtr hWnd, int id); 
     [DllImport("user32.dll")] 
     private static extern bool SetForegroundWindow(IntPtr hWnd); 
    } 
} 

Tenga en cuenta que la función SetForegroundWindow() es el problema, posiblemente, también la fuente del problema que usted describe en su pregunta. Windows no permite que una aplicación introduzca una ventana en la cara del usuario cuando el usuario está utilizando activamente otra ventana. Al menos varios segundos de inactividad deben expirar antes de que permita que la ventana se robe el foco. Con el código dado, que es bastante fácil de ver, el botón de la barra de tareas de su formulario parpadeará. Evite establecer la propiedad ShowInTaskbar en falso. No es necesario hacerlo con este código, el botón de la barra de tareas no se mostrará hasta que se presione la tecla de acceso directo.

+0

Voto a favor por la minuciosidad de su respuesta, aunque no lo intenté. Estoy usando una clase contenedora para teclas rápidas que básicamente hace lo mismo que mostraste y luego activa un evento. A los efectos de esta aplicación, es importante que no se muestre la entrada de la barra de tareas, incluso cuando se presiona la tecla de acceso directo. – Fopedush

+0

No veo cómo tiene sentido que su ventana emergente se pierda detrás de una ventana frontal más grande sin que el usuario pueda activarla. Oh bien. –

+0

topmost se establece en verdadero, por lo que a menos que haya circunstancias inusuales (aplicación de pantalla completa), estará visible. La ventana actúa como una OSD para el volumen del sistema, mis teclas de acceso rápido lo suben/bajan/lo silencian. La forma literalmente es una cosita sin bordes con una barra de progreso y una etiqueta que muestra el volumen%. – Fopedush

Cuestiones relacionadas