4

I'm working on a program, who need to detect when the user press the keyboard or use his mouse, even if the program is minimized or not focused. I think I have to use the windows API, keybd_event (user32), but I don't know how to use the "listener" of this event. I have something like that:

    [DllImport("user32.dll")]
    static extern void keybd_event(byte bVk, byte bScan, uint dwFlags,UIntPtr dwExtraInfo);
    void PressKey(byte keyCode)
    {
        //My code here
    }

I did some research, but it's the first time I have to use DllImport, so I don't know how to continue ... Thanks (Ps:Sorry about my bad English, this is not my native language :) )

(PPs: I've read all of your answers, but it takes a while to read every link, so I'll work on it tonight, but I think I will find the answer. Anyway, thanks for the links everybody ;) )

Edit: So I just finished my code and it's work :) It looks something like:

    [DllImport("user32.dll")]
    public static extern Boolean GetLastInputInfo(ref tagLASTINPUTINFO plii);
    public struct tagLASTINPUTINFO
    {
        public uint cbSize;
        public Int32 dwTime;
    }

    private void timerTemps_Inactif_Tick(object sender, EventArgs e)
    {
        tagLASTINPUTINFO LastInput = new tagLASTINPUTINFO();
        Int32 IdleTime;
        LastInput.cbSize = (uint)Marshal.SizeOf(LastInput);
        LastInput.dwTime = 0;

        if (GetLastInputInfo(ref LastInput))
        {
            IdleTime = System.Environment.TickCount - LastInput.dwTime;
            if (IdleTime > 10000)
            {
                //My code here
            }
        }
    }

Thanks for the help guys ;)

Keenegan
  • 91
  • 7
  • This function (keybd_event) is not designed to listen keyboard, but to generate/simulate key dows, ups, presses etc. In order to listen keyboard events look for hooks: http://msdn.microsoft.com/en-us/library/windows/desktop/ms632589(v=vs.85).aspx – Dmitry Bychenko Sep 09 '13 at 14:24
  • "How do I write a keylogger?" - you might have something completely different in mind, but this is what you would basically make and keyloggers are bad and in some cases illegal. So you probably won't get too much help for that here on SO. – Corak Sep 09 '13 at 14:25
  • Once you understand what system hooks are, this is a duplicate of [difference between WH\_KEYBOARD and WH\_KEYBOARD\_LL?](http://stackoverflow.com/questions/10718009/difference-between-wh-keyboard-and-wh-keyboard-ll) – Black Frog Sep 09 '13 at 14:25
  • I don't want to create a keylogger, I need to detect when someone presses any key, or move his mouse to detect if he's still using the computer. I don't want to know which key is pressed ;) – Keenegan Sep 09 '13 at 14:29
  • @Keenegan - okay, that's something different. Maybe this'll help you: http://forum.codecall.net/topic/69801-user-idle-detection/ – Corak Sep 09 '13 at 14:33
  • Thanks for the link, it's exactly what I am looking for, but it seems to be wrote for c++, not c#. How can I use it in c#? – Keenegan Sep 09 '13 at 14:42
  • @Keenegan - no, it's in c#. the formatting is horrible, though. you might want to download the source code at the end of the article. – Corak Sep 09 '13 at 14:49
  • possible duplicate of [how to use RegisterHotKey() in C#?](http://stackoverflow.com/questions/8911930/how-to-use-registerhotkey-in-c) – Hans Passant Sep 09 '13 at 14:53
  • @Corak Yeah, I figured that a few seconds after posting, I feel a bit stupid right now ^^' Anyway thanks for the link ;) – Keenegan Sep 09 '13 at 15:36

3 Answers3

2

You will need to hook into Windows OS with SetWindowsHookEx function. You should read the article Keyloggers: How they work and how to detect them posted by SecureList to get a understanding ofthe process.

Black Frog
  • 11,595
  • 1
  • 35
  • 66
2

I have always got a good performance by using RegisterHotKey/UnregisterHotKey functions. Sample code:

[DllImport("User32")]
public static extern bool RegisterHotKey(
    IntPtr hWnd,
    int id,
    int fsModifiers,
    int vk
);
[DllImport("User32")]
public static extern bool UnregisterHotKey(
    IntPtr hWnd,
    int id
);
public const int MOD_SHIFT = 0x4;
public const int MOD_CONTROL = 0x2;
public const int MOD_ALT = 0x1;
public const int WM_HOTKEY = 0x312;

protected override void WndProc(ref Message m)
{
    if (m.Msg == WM_HOTKEY && m.WParam == (IntPtr)0)
    {
        IntPtr lParamCTRLA = (IntPtr)4259842;
        IntPtr lParamB = (IntPtr)4325376;
        if (m.LParam == lParamCTRLA)
        {
            MessageBox.Show("CTRL+A was pressed");
        }
        else if (m.LParam == lParamB)
        {
            MessageBox.Show("B was pressed");
        }
    }
    base.WndProc(ref m);
}

private void Form1_Load(object sender, EventArgs e)
{
    this.FormClosing += new FormClosingEventHandler(Form1_FormClosing);

    RegisterHotKey(this.Handle, 0, MOD_CONTROL, (int)Keys.A);
    RegisterHotKey(this.Handle, 0, 0, (int)Keys.B);
}

private void Form1_FormClosing(Object sender, FormClosingEventArgs e)
{
    UnregisterHotKey(this.Handle, 0);
}

You can "register" as many keys (or combination of keys) as you want by emulating the shown structure. All the registered keys will get inside the condition if (m.Msg == WM_HOTKEY && m.WParam == (IntPtr)0); if they are pressed at all (independently upon the program currently being selected). The easiest way to know the specific key/combination being pressed is relying on m.LParam (I got the two values I am including after a quick test with the given keys). You can do a quick research to find out a list of LParam or further constant modifiers (wheel of the mouse, for example).

varocarbas
  • 12,354
  • 4
  • 26
  • 37
2

The final code:

[DllImport("user32.dll")]
public static extern Boolean GetLastInputInfo(ref tagLASTINPUTINFO plii);
public struct tagLASTINPUTINFO
{
    public uint cbSize;
    public Int32 dwTime;
}

private void timerTemps_Inactif_Tick(object sender, EventArgs e)
{
    tagLASTINPUTINFO LastInput = new tagLASTINPUTINFO();
    Int32 IdleTime;
    LastInput.cbSize = (uint)Marshal.SizeOf(LastInput);
    LastInput.dwTime = 0;

    if (GetLastInputInfo(ref LastInput))
    {
        IdleTime = System.Environment.TickCount - LastInput.dwTime;
        if (IdleTime > 10000)
        {
            //My code here
        }
    }
}
Keenegan
  • 91
  • 7