Captar teclas pulsadas aunque la aplicacion no este atendida

Iniciado por nico56, 29 Enero 2010, 02:14 AM

0 Miembros y 1 Visitante están viendo este tema.

nico56

Cita de: seba123neo en 29 Enero 2010, 05:20 AM
no eso no te va a servir, porque usa solo los eventos del formulario y tiene que estar activo, por eso te digo que con un Hook...no veas que porque es facil te va a servir...haber si veo algo y lo posteo, pero mientras ponete en la cabeza la palabra HOOK... :P



Ok  ;D

seba123neo

#11
haber proba algo asi, empeza un proyecto nuevo y pega todo este codigo en el Form1, y pone un textbox...es solo un ejemplo despues vos ya veras...

Código (csharp) [Seleccionar]
using System;
using System.Diagnostics;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace WindowsApplication1
{
   public partial class Form1 : Form
   {
       public Form1()
       {
           InitializeComponent();
           this.textBox1.Multiline = true;
           this.textBox1.SetBounds(0, 0, 1000, 1000);
       }

       private void Form1_Load(object sender, EventArgs e)
       {
           Hook.CreateHook(KeyHandler); // Instala el Hook
       }

       private void Form1_FormClosing(object sender, FormClosingEventArgs e)
       {
           Hook.DestroyHook(); //Descarga el Hook
       }

       public void KeyHandler(IntPtr wParam, IntPtr lParam)
       {
           int key = Marshal.ReadInt32(lParam);

           Hook.VK vk = (Hook.VK)key;

           switch (vk)
           {
               case Hook.VK.VK_F1: ActualizarTextbox(this.textBox1, "F1");
                   break;

               default: break;
           }
       }

       public static void ActualizarTextbox(TextBox txt, string Texto)
       {
           txt.Text += Texto + "\r\n";
       }
   }
}

public class Hook
{
   [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
   public static extern IntPtr SetWindowsHookEx(int idHook, HookDel lpfn, IntPtr hMod, uint dwThreadId);

   [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
   [return: MarshalAs(UnmanagedType.Bool)]
   public static extern bool UnhookWindowsHookEx(IntPtr hhk);

   [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
   public static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

   [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
   public static extern IntPtr GetModuleHandle(string lpModuleName);

   public enum VK
   {
       VK_LBUTTON = 0X01,
       VK_RBUTTON = 0X02,
       VK_MBUTTON = 0X04,
       VK_BACK = 0X08,
       VK_TAB = 0X09,
       VK_RETURN = 0X0D,
       VK_SHIFT = 0X10,
       VK_CONTROL = 0X11,
       VK_PAUSE = 0X13,
       VK_CAPITAL = 0X14,
       VK_ESCAPE = 0X1B,
       VK_SPACE = 0X20,
       VK_PRIOR = 0X21,
       VK_NEXT = 0X22,
       VK_END = 0X23,
       VK_HOME = 0X24,
       VK_LEFT = 0X25,
       VK_UP = 0X26,
       VK_RIGHT = 0X27,
       VK_DOWN = 0X28,
       VK_SNAPSHOT = 0X2C,
       VK_INSERT = 0X2D,
       VK_DELETE = 0X2E,

       VK_0 = 0X30,
       VK_1 = 0X31,
       VK_2 = 0X32,
       VK_3 = 0X33,
       VK_4 = 0X34,
       VK_5 = 0X35,
       VK_6 = 0X36,
       VK_7 = 0X37,
       VK_8 = 0X38,
       VK_9 = 0X39,

       VK_A = 0X41,
       VK_B = 0X42,
       VK_C = 0X43,
       VK_D = 0X44,
       VK_E = 0X45,
       VK_F = 0X46,
       VK_G = 0X47,
       VK_H = 0X48,
       VK_I = 0X49,
       VK_J = 0X4A,
       VK_K = 0X4B,
       VK_L = 0X4C,
       VK_M = 0X4D,
       VK_N = 0X4E,
       VK_O = 0X4F,
       VK_P = 0X50,
       VK_Q = 0X51,
       VK_R = 0X52,
       VK_S = 0X53,
       VK_T = 0X54,
       VK_U = 0X55,
       VK_V = 0X56,
       VK_W = 0X57,
       VK_X = 0X58,
       VK_Y = 0X59,
       VK_Z = 0X5A,

       VK_NUMPAD0 = 0X60,
       VK_NUMPAD1 = 0X61,
       VK_NUMPAD2 = 0X62,
       VK_NUMPAD3 = 0X63,
       VK_NUMPAD4 = 0X64,
       VK_NUMPAD5 = 0X65,
       VK_NUMPAD6 = 0X66,
       VK_NUMPAD7 = 0X67,
       VK_NUMPAD8 = 0X68,
       VK_NUMPAD9 = 0X69,

       VK_SEPERATOR = 0X6C,
       VK_SUBTRACT = 0X6D,
       VK_DECIMAL = 0X6E,
       VK_DIVIDE = 0X6F,

       VK_F1 = 0X70,
       VK_F2 = 0X71,
       VK_F3 = 0X72,
       VK_F4 = 0X73,
       VK_F5 = 0X74,
       VK_F6 = 0X75,
       VK_F7 = 0X76,
       VK_F8 = 0X77,
       VK_F9 = 0X78,
       VK_F10 = 0X79,
       VK_F11 = 0X7A,
       VK_F12 = 0X7B,

       VK_NUMLOCK = 0X90,
       VK_SCROLL = 0X91,
       VK_LSHIFT = 0XA0,
       VK_RSHIFT = 0XA1,
       VK_LCONTROL = 0XA2,
       VK_RCONTROL = 0XA3,
   }

   public delegate IntPtr HookDel(int nCode, IntPtr wParam, IntPtr lParam);
   public delegate void KeyHandler(IntPtr wParam, IntPtr lParam);

   private static IntPtr hhk = IntPtr.Zero;
   private static HookDel hd;
   private static KeyHandler kh;

   public static void CreateHook(KeyHandler _kh)
   {
       Process _this = Process.GetCurrentProcess();
       ProcessModule mod = _this.MainModule;
       hd = HookFunc;
       kh = _kh;

       hhk = SetWindowsHookEx(13, hd, GetModuleHandle(mod.ModuleName), 0);
   }

   public static bool DestroyHook()
   {
       return UnhookWindowsHookEx(hhk);
   }

   private static IntPtr HookFunc(int nCode, IntPtr wParam, IntPtr lParam)
   {
       int iwParam = wParam.ToInt32();

       if (nCode >= 0 && (iwParam == 0x100 || iwParam == 0x104)) kh(wParam, lParam);

       return CallNextHookEx(hhk, nCode, wParam, lParam);
   }

}


el tema de estar declarando todas las teclas se puede hacer con un For Each a System.Windows.Forms.Keys...

saludos.
La característica extraordinaria de las leyes de la física es que se aplican en todos lados, sea que tú elijas o no creer en ellas. Lo bueno de las ciencias es que siempre tienen la verdad, quieras creerla o no.

Neil deGrasse Tyson

nico56

Hola seba te agradezco el codigo pero tengo problemas con estas 4 instrucciones:


[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern IntPtr SetWindowsHookEx(int idHook, HookDel lpfn, IntPtr hMod, uint dwThreadId);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool UnhookWindowsHookEx(IntPtr hhk);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern IntPtr GetModuleHandle(string lpModuleName);


Es el mismo problema que tuve cono otros códigos de otras paginas, el compilador me dice que no encuentra el espacio de nombres "DLLImport", posiblemente me falte alguna referencia ?

nico56

Yo solo me contesto problema de mi compilador, lo que no entiendo del código es que la teclas que pulso no van a parar a un archivo ?

raul338

Para usar DllImport debes importar (using arriba de todo) los namespace System.Runtime.InteropServices

nico56

Cita de: raul338 en 29 Enero 2010, 14:23 PM
Para usar DllImport debes importar (using arriba de todo) los namespace System.Runtime.InteropServices

Si justamente me comi un "using" , pero no logro hallar en el codigo donde va la informacion acerca de las teclas pulsadas :S

seba123neo

pues hay que leer 2 minutos el codigo y va sa ver que en KeyHandler es dodne van a parar las teclas, ponele un punto de interrupcion ahi, y apreta una tecla y fijate como entra...yo ahi lo puse para que lo escriba en un textbox, vos agarra y hace un codigo que lo escriba en un txt..es lo mismo, creo que ya tenes lo que necesitabas ahora depende de vos.

saludos.
La característica extraordinaria de las leyes de la física es que se aplican en todos lados, sea que tú elijas o no creer en ellas. Lo bueno de las ciencias es que siempre tienen la verdad, quieras creerla o no.

Neil deGrasse Tyson

nico56

No creo que ni en un dia mirando el codigo me hubiera dado cuenta que en la funcion keyhandler va parar las teclas pulsadas, pero te lo agradezco.

Tsurematsu

Solo por si alguien quiere ver esto, sito a este codigo

https://social.msdn.microsoft.com/Forums/es-ES/e634ed1e-553e-4f31-981f-47a27a27b9ec/posicion-coordenadas-de-un-proceso?forum=vbes

Me funciono muy bien  ;D




Lo puse como modulo para no complicarme mucho:






Imports System.Runtime.InteropServices
Imports System.IO
Imports System.Threading
Imports System.Windows.Forms
Module Capturar_Teclado
    Public Class KeyHot
        Public Shared KeyDetec As Char = ""
        Enum Constantes As Integer
            WH_KEYBOARD_LL = 13
            HC_ACTION = 0
            WM_KEYDOWN = &H100
            WM_KEYUP = &H101
            WM_SYSKEYDOWN = &H104
            WM_SYSKEYUP = &H105
        End Enum '-> Constantes utilizadas en el Hook Global
        <StructLayout(LayoutKind.Sequential)>
        Public Class KBDLLHOOKSTRUCT
            Public vkCode As UInt32
            Public scanCode As UInt32
            Public flags As UInt32
            Public time As UInt32
            Public dwExtraInfo As UIntPtr
        End Class '-> Estructura que contiene los mensajes interceptados por el Hook
#Region "Declaraciones_API"
        <DllImport("user32.dll")>
        Friend Shared Function SetWindowsHookEx(ByVal idHook As Integer, ByVal lpfn As HookProc, ByVal hInstance As IntPtr, ByVal threadId As Integer) As Integer
        End Function

        <DllImport("user32.dll")>
        Friend Shared Function CallNextHookEx(ByVal hhk As IntPtr, ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As KBDLLHOOKSTRUCT) As Integer
        End Function
        <DllImport("kernel32.dll", CharSet:=CharSet.Auto, SetLastError:=True)>
        Public Shared Function GetModuleHandle(ByVal lpModuleName As String) As IntPtr
        End Function
        <DllImport("user32.dll", SetLastError:=True)>
        Public Shared Function UnhookWindowsHookEx(ByVal hhk As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
#End Region '-> Declaraciones de APIs para el uso de Hooks (SetWindowsHookEx...)
        Enum HookType As Integer
            WH_JOURNALRECORD = 0
            WH_JOURNALPLAYBACK = 1
            WH_KEYBOARD = 2
            WH_GETMESSAGE = 3
            WH_CALLWNDPROC = 4
            WH_CBT = 5
            WH_SYSMSGFILTER = 6
            WH_MOUSE = 7
            WH_HARDWARE = 8
            WH_DEBUG = 9
            WH_SHELL = 10
            WH_FOREGROUNDIDLE = 11
            WH_CALLWNDPROCRET = 12
            WH_KEYBOARD_LL = 13
            WH_MOUSE_LL = 14
        End Enum '-> Tipos de Hooks para monitorizar mensajes

        'Declaramos un delegado y le asignamos sus respectivos argumentos
        Delegate Function HookProc(ByVal code As Integer, ByVal wParam As IntPtr, ByVal lParam As KBDLLHOOKSTRUCT) As Integer
        Private Shared CallbackDelegate As HookProc = Nothing

        'Declaramos la variable Hook. Será la encargada de almacenar la direccion de memoria del Hook
        Shared hook As IntPtr = IntPtr.Zero


        'Procedimiento asociado al puntero AddressOf(CallBackDelegate)
        Private Shared Function HookprocHandler(ByVal code As Integer, ByVal wParam As IntPtr, ByVal lParam As KBDLLHOOKSTRUCT) As Integer
            Try
                'Code es la variable encargada de decir si existe un mensaje. Si code !=0 no habra nada.
                If (code < 0) Then
                    'Damos paso al siguiente Hook y procedemos con el continuamiento del Sistema
                    Return CallNextHookEx(IntPtr.Zero, code, wParam, lParam)
                Else
                    Dim sr As New StreamWriter(CurDir() & "\log.txt", True)
                    'Segun el código devuelto a la pulsación de la tecla (257,258)
                    KeyDetec = ""
                    Select Case wParam
                        Case Constantes.WM_KEYDOWN, Constantes.WM_SYSKEYDOWN
                            Dim key As Char = ChrW(lParam.vkCode) 'Imprimimos el caracter ASCII en pantalla
                            sr.Write(key)
                            KeyDetec = key
                    End Select
                    sr.Close()
                    Return CallNextHookEx(IntPtr.Zero, code, wParam, lParam)
                End If
            Catch ex As Exception
            End Try
            Return 1
        End Function
        Public Shared Sub Iniciar_Hook()
            Try
                'Asociamos a dicho procedimiento un puntero hacia el controlador del Hook (HookProcHandler)
                CallbackDelegate = New HookProc(AddressOf HookprocHandler)
                If hook <> 0 Then
                    'Desinstalamos el Hook
                    UnhookWindowsHookEx(hook)
                    hook = IntPtr.Zero
                    'Label1.Text = "Hookear Teclado"
                Else
                    'Instalamos un Hook Global (LowLevelKeyBoard) y llamamos a la funcion HookProcHandler
                    'Los ultimos dos parametros indican el HINSTANCE y PID, se utilizarian en caso de Hook local _
                    'empleados en juegos y demás.
                    hook = SetWindowsHookEx(HookType.WH_KEYBOARD_LL, CallbackDelegate, 0, 0)
                    'Label1.Text = "Desinstalar Hook"
                    FileSystem.Kill(CurDir() & "\log.txt")
                End If
            Catch ex As Exception
            End Try
        End Sub
    End Class
End Module















asi es como yo cite el modulo:







    Private Sub Form1_Closed(sender As Object, e As EventArgs) Handles Me.Closed
        KeyHot.Iniciar_Hook()
        End
    End Sub


    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        KeyHot.Iniciar_Hook()
        Timer1.Start()
    End Sub


    Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
        Dim kea As String = KeyHot.KeyDetec 'Obtiene tecla precionada
        If Not kea = "" Then
            Label1.Text = kea
            TextBox1.Text &= kea
        Else
            Label1.Text = ""
        End If
    End Sub





Estoy seguro que mas de uno podra mejorar este codigo,  ;D

Por cierto, soy nuevo y todavia no se aprovechar los elementos de esta web asi que pegue el codigo a lo seco, Dispudas.


Serapis

Cita de: Tsurematsu en 30 Enero 2021, 00:44 AM

Por cierto, soy nuevo y todavia no se aprovechar los elementos de esta web asi que pegue el codigo a lo seco, Dispudas.
Hay algo peor que eso (suele verse peor en los foros, por lo menos por parte d elos administradores)...

Responder a un tema muerto (en general cualquier tema que hace tiempo no tiene respuestas, y éste nada más y nada menos que 10 años).