2010-03-11 28 views
10

Estoy queriendo escribir un teclado virtual, como el teclado de Windows en pantalla para PC con pantalla táctil. Pero estoy teniendo problemas con mi teclado virtual robando el foco de la aplicación que se está utilizando. El teclado de Windows en pantalla mantiene el enfoque en la aplicación actual incluso cuando el usuario hace clic en ella. ¿Hay alguna manera de hacer lo mismo con los formularios de Windows en C#?Haz un formulario no enfocable en C#

Lo único que puedo hacer por ahora es enviar un evento de teclado a una aplicación específica, como un bloc de notas en el siguiente código. Si pudiera hacer que el formulario no se pueda enfocar, podría obtener la ventana enfocada actual con GetForegroundWindow.

[DllImport("USER32.DLL", CharSet = CharSet.Unicode)] 
public static extern IntPtr FindWindow(string lpClassName,string lpWindowName); 


[DllImport("USER32.DLL")] 
public static extern bool SetForegroundWindow(IntPtr hWnd); 

private void button1_Click(object sender, EventArgs e) 
{ 
    IntPtr calculatorHandle = FindWindow("notepad", null); 
    SetForegroundWindow(calculatorHandle); 
    SendKeys.SendWait("111"); 
} 

¿Hay alguna manera de hacerlo? ¿Alguna sugerencia de una mejor manera de tener el formulario de envío de eventos de teclado a la aplicación que se utiliza?

Gracias!

Respuesta

8

En lugar de intentar restablecer la ventana activa después de haber hecho clic en la suya, prefiero evitar que la ventana reciba el foco/se active.

Eche un vistazo a this article. Al final, el autor explica brevemente cómo se puede hacer esto:

¿Cómo puedo evitar que mi ventana de conseguir la activación y el foco cuando se muestra?

En Windows Forms 2.0 hay una nueva propiedad llamada ShowWithoutActivation, que deberá sobrescribir en el formulario. En aplicaciones nativas, puede usar SetWindowPos con el indicador SWP_NOACTIVATE o el ShowWindow con el indicador SW_SHOWNA.

Además, en this article se proporciona un ejemplo de código para Windows Forms:

Si quieres un completo en forma, ahora se puede sustituir una propiedad llamada ShowWithoutActivation:

public class NoActivateForm : Form { 
    protected override bool ShowWithoutActivation { 
     get { 
      return true; 
     } 
    } 
}

Tenga en cuenta que esto no "evita" la activación todo el tiempo; puede activar llamando al Activate(), Focus() ... etc métodos. Si desea evitar que los clics en el área del cliente activen la ventana , puede manejar el mensaje WM_MOUSEACTIVATE.

private const int WM_MOUSEACTIVATE = 0x0021, MA_NOACTIVATE = 0x0003; 

protected override void WndProc(ref Message m) { 
    if (m.Msg == WM_MOUSEACTIVATE) { 
     m.Result = (IntPtr)MA_NOACTIVATE; 
     return; 
    } 
    base.WndProc(ref m); 
}
+0

+1 buena idea/punteros. –

+0

Gracias! Está a mitad de camino! Esa solución de artículo evita que mi formulario se centre, pero no impide que la otra aplicación pierda el foco. Es decir, cuando hago clic en mi aplicación, llego a la situación en la que ninguna aplicación tiene el foco. – Jandex

+0

En caso de que los enlaces se vuelvan inválidos, su respuesta básicamente no contiene información.Resuma los recursos externos, para que su respuesta continúe siendo valiosa, incluso si los recursos fuera del sitio fallan. – IInspectable

9

Su resuelto!

He intentado la solución de gehho, pero también necesitaba reemplazar el método CreateParams:

private const int WS_EX_NOACTIVATE = 0x08000000; 
protected override CreateParams CreateParams 
    { 
     get 
     { 
      CreateParams createParams = base.CreateParams; 
      createParams.ExStyle |= WS_EX_NOACTIVATE; 
      return createParams; 
     } 
    } 
+3

¿No debería técnicamente * agregar * a 'createParams.ExStyle', en lugar de reemplazarlo por completo? (por ejemplo, 'createParams.ExStyle | = WS_EX_NOA [...];') – Jesse

+0

He editado el código en la respuesta para efectuar ese cambio –

+0

@DavidHeffernan ok, así que lo editó para efectuar el cambio sugerido por Jesse? – barlop

Cuestiones relacionadas