简体   繁体   English

背景按键监听器

[英]Background Key Press Listener

I've got a simple window form application that turns on capslock when I press space and turns it off if I press a letter.我有一个简单的 window 表单应用程序,当我按下空格时打开大写锁定,如果按下字母则将其关闭。

Problem is that I have to focus on the window for it to work (top-most doesn't work either, top-most doesn't focus it just displaying the window above all other unfocused).问题是我必须专注于 window 才能使其工作(最上面的也不起作用,最上面的也不专注于它,只是显示 window 高于所有其他不重点)。

Anyone has any idea how can I make it work even if im writing in a notepad?任何人都知道即使我在记事本上写字,我怎样才能让它工作?

Key logging can be used for naughty stuff, and manipulating Caps Lock like that seems rather strange, but since the info is already publicly available, and you know your user stories better than me, I've posted a solution.密钥记录可用于顽皮的东西,像这样操纵 Caps Lock 似乎很奇怪,但由于信息已经公开,而且你比我更了解你的用户故事,我已经发布了一个解决方案。

Here's an example based on the code snippet posted from keylogger code in C# in the MSDN forum.这是一个基于 MSDN 论坛中 C# 中的键盘记录器代码发布的代码片段的示例。

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

class Program
{
    private const int WH_KEYBOARD_LL = 13;
    private const int WM_KEYDOWN = 0x0100;
    private static LowLevelKeyboardProc _proc = HookCallback;
    private static IntPtr _hookID = IntPtr.Zero;
    private static bool lastKeyWasLetter = false;

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

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

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

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

    [DllImport("user32.dll")]
    static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo);

    private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);

    [STAThread]
    static void Main(string[] args)
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        _hookID = SetHook(_proc);
        Application.Run();

        UnhookWindowsHookEx(_hookID);
    }

    private static IntPtr SetHook(LowLevelKeyboardProc proc)
    {
        using (Process curProcess = Process.GetCurrentProcess())
        using (ProcessModule curModule = curProcess.MainModule)
        {
            return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
        }
    }

    private static void ToggleCapsLock()
    {
        const int KEYEVENTF_EXTENDEDKEY = 0x1;
        const int KEYEVENTF_KEYUP = 0x2;

        UnhookWindowsHookEx(_hookID);
        keybd_event(0x14, 0x45, KEYEVENTF_EXTENDEDKEY, (UIntPtr)0);
        keybd_event(0x14, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, (UIntPtr)0);
        _hookID = SetHook(_proc);
    }

    private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
    {
        if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
        {
            if (lastKeyWasLetter)
            {
                if (Control.IsKeyLocked(System.Windows.Forms.Keys.CapsLock))
                {
                    ToggleCapsLock();
                }
                lastKeyWasLetter = false;
            }
            Keys key = (Keys)Marshal.ReadInt32(lParam);            
            if (key == Keys.Space)
            {
                if (!Control.IsKeyLocked(System.Windows.Forms.Keys.CapsLock))
                {
                    ToggleCapsLock();
                }
            }
            else if (key >= Keys.A && key <= Keys.Z)
            {
                lastKeyWasLetter = true;
            }
        }
        return CallNextHookEx(_hookID, nCode, wParam, lParam);
    }
}

Paste that into a new Windows application's Program.cs in Visual Studio to try it out.将其粘贴到 Visual Studio 中新的 Windows 应用程序的 Program.cs 中进行试用。

If you intercept a key down event to turn Caps Lock on and off, then the event is intercepted before the application handles it.如果您拦截按键按下事件以打开和关闭 Caps Lock,则该事件会在应用程序处理它之前被拦截。 This means that turning Caps Lock off when a letter key is pressed will result in the application you are typing in receiving a lower case letter, even directly after a space.这意味着在按下字母键时关闭 Caps Lock 将导致您正在输入的应用程序接收到小写字母,即使在空格之后也是如此。

I've assumed you are trying to force the capitalization of the first letter in each word (and if so, you may need to handle other keys such as Return too), so my snippet will only turn Caps Lock off on the next key down event following a letter being pressed.我假设您正在尝试强制每个单词中的第一个字母大写(如果是这样,您可能还需要处理其他键,例如 Return),所以我的代码片段只会在下一个键关闭时关闭 Caps Lock按下字母后的事件。 Note that you can't just try and capture the key up, as when typing fast you may hold the initial key down until after you've pressed the following key.请注意,您不能只是尝试抓住键,因为在快速打字时,您可能会按住初始键,直到按下下一个键。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM