La idea es la siguiente: enviar por medio de una aplicación las pulsaciones de teclado a una aplicación externa.
Cuál es el problema? Cuando se trabaja con aplicaciones que reciben texto no hay problema, pero supongamos que la aplicación tiene varias ventanas, una ventana donde se muestra una imagen, otra ventana con accesos directos de teclado, otra con iconos, etc..., estas ventanas no reciben texto sino pulsaciones de teclado. Estas pulsaciones son lo que se denomina "hotKey".
Bien, he problado con:
- SendKeys.Send() pero no funciona salvo para la ventana que recibe texto, si ésta ventana está activa.
- API Keybd_event pero hace exactamente lo mismo que el anterior.
- He usado los eventos KeyDown, KeyUp, etc, de los controles que van a enviar el hotkey y tampoco funciona.
- Probé también pasar el caracter a byte con la función ASC pero me hace lo mismo.
- Probé al enviar el hotket con keys.[El caracter o tecla de función que necesite], como por ejemplo "Keys.LControlKey" o "Keys.Enter" pero obtengo los mismos resultados.
Con la curiosidad probé la aplicación que trae el windows 7 "Teclado en Pantalla" y "voila" ahi si sirve todo sobre la aplicación externa.
Entonces lo que necesito es saber como rayos trabaja el teclado en pantalla del windows, supongo que estará programado en C++ o C#, pero aun así, usará un link a una DLL de una API para trabajar el teclado a bajo nivel para conseguir lo que quiero.
Una cosa más, cuando uso "SendKeys.Send("{ENTER}") si funciona en la aplicación externa, pero si hago esto "SendKeys.Send("T")" no funciona como hotkey excepto si la ventana para recibir el texto está activa.
En otras palabras los caracteres los recibe como texto cuando los envio por SendKeys.Send o cuando lo envio usando Keybd_event, pero no como pulsación del teclado. Esto no pasa con el "teclado en pantalla" del windows, que cuando le doy a T del teclado en pantalla éste si funciona como hotKey.
Cualquier información que puedan pasarme sobre el trabajo a bajo nivel de teclado por medio de VB.NET se los agradeceré.
Les adjunto el código de lo que tengo hecho en VB.NET para que vean.
Código VB.NET:
Ver original
Imports System.Runtime.InteropServices Public Class Form1 Const KEYEVENTF_KEYUP = &H2 Const KEYEVENTF_EXTENDEDKEY = &H1 <DllImport("user32.dll", EntryPoint:="keybd_event", CharSet:=CharSet.Auto, ExactSpelling:=True)> _ Public Shared Sub Keybd_event(ByVal vk As Byte, ByVal scan As Byte, ByVal flags As Integer, ByVal extrainfo As Integer) End Sub Declare Function VkKeyScan Lib "user32" Alias "VkKeyScanA" (ByVal cChar_Renamed As Byte) As Short Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick sTimer(TextBox2, TextBox1) End Sub Private Sub Timer2_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer2.Tick sTimer(TextBox4, TextBox3) End Sub Private Sub Timer3_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer3.Tick sTimer(TextBox6, TextBox5) End Sub Private Sub Timer4_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer4.Tick sTimer(TextBox8, TextBox7) End Sub Private Sub Timer5_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer5.Tick sTimer(TextBox10, TextBox9) End Sub Private Sub Timer6_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer6.Tick sTimer(TextBox12, TextBox11) End Sub Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click Timer1.Enabled = True Timer2.Enabled = True Timer3.Enabled = True Timer4.Enabled = True Timer5.Enabled = True Timer6.Enabled = True End Sub Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click Timer1.Enabled = False Timer2.Enabled = False Timer3.Enabled = False Timer4.Enabled = False Timer5.Enabled = False Timer6.Enabled = False End Sub Private Sub sTimer(ByVal txt As TextBox, ByVal txtEnvio As TextBox) 'Se comprueba que exista texto en la caja correspondiente y que su valor sea mayor que 0... If CLng(txt.Text) > 0 Then txt.Text = CStr(CLng(txt.Text) - 1) End If Else Exit Sub End If Dim time_t As Integer time_t = CInt(txt.Text) 'Se transforma el valor de la caja de texto al tipo integer... If CInt(txt.Text) = 0 Then txt.Text = time_t.ToString() 'El valor del time_t se pasa a string y se le asigna a la caja de texto... End If Dim tiempomuerto As Integer tiempomuerto = 1 If CInt(txt.Text) = tiempomuerto Then 'Si el valor es igual a 1 entonces... 'MsgBox(Asc(txtEnvio.Text), MsgBoxStyle.OkOnly, "Prueba") SendKeys.Send(Keys.Enter) 'Pulsar(CByte(Asc(txtEnvio.Text))) 'se envía lo que exista en la caja de texto... End If End Sub Private Sub Pulsar(ByVal tecla As Byte) Keybd_event(tecla, 0, 0, 0) Keybd_event(tecla, 0, KEYEVENTF_KEYUP, 0) End Sub End Class
Es un formulario con 12 cajas de texto y 6 timer, pero con 2 cajas y un timer bastará para probar.
La caja de texto par, (textbox2, textbox4, textbox6, etc), es donde se coloca el tiempo antes de que se envíe el hotkey, (va en cuenta regresiva).
La caja de texto impar, (textbox1, textbox3, textbox5, etc), es donde se coloca el caracter que será el hotkey a enviar a la aplicación externa.
Button3, empieza la cuenta regresiva, Button4 detiene los timers.
Saludos y muchas gracias de antemano.