C# 如何在不关注窗体的情况下在Windows窗体应用程序中记录键?

C# 如何在不关注窗体的情况下在Windows窗体应用程序中记录键?,c#,windows,winforms,C#,Windows,Winforms,我想制作一个应用程序,每当我在10秒内输入“A片”时,它就会退出Microsoft Edge或Google Chrome。当我让我的应用程序显示表单时,这可以很好地工作,但我希望它能够在我的应用程序未聚焦时识别密钥 以下是我的全部代码: public partial class Form1 : Form { private NotifyIcon icon; private int counter; private Timer timer; public Fo

我想制作一个应用程序,每当我在10秒内输入“A片”时,它就会退出Microsoft Edge或Google Chrome。当我让我的应用程序显示表单时,这可以很好地工作,但我希望它能够在我的应用程序未聚焦时识别密钥

以下是我的全部代码:

public partial class Form1 : Form
{


    private NotifyIcon icon;
    private int counter;
    private Timer timer;

    public Form1()
    {
        InitializeComponent();


        this.Visible = false;
        this.WindowState = FormWindowState.Minimized;
        this.ShowInTaskbar = false;


        counter = 0;

        string path = System.IO.Path.GetDirectoryName(Application.ExecutablePath);

        Icon pornIcon = new Icon(path + "/pornquitter.ico");

        icon = new NotifyIcon();
        icon.BalloonTipTitle = "Porn Quitter v0.1";
        icon.Icon = pornIcon;
        icon.Visible = true;

        MenuItem item1 = new MenuItem();
        item1.Text = "Porn Quitter v0.1";
        MenuItem item2 = new MenuItem();
        item2.Text = "Quit !";

        ContextMenu menu = new ContextMenu();
        menu.MenuItems.Add(item1);
        menu.MenuItems.Add(item2);

        icon.ContextMenu = menu;

        item2.Click += Item2_Click;


        timer = new Timer();
        timer.Interval = 10000;
        timer.Start();

        timer.Tick += Timer_Tick;

    }

    private void Timer_Tick(object sender, EventArgs e)
    {
        counter = 0;
    }

    private void Item2_Click(object sender, EventArgs e)
    {
        icon.Dispose();
        timer.Stop();
        this.Close();

    }
    private void Form1_KeyPress(object sender, KeyPressEventArgs e)
    {
        if(counter < 4)
        {
            if (e.KeyChar.ToString().ToLower().ToCharArray(0,1)[0] == 'p' && counter == 0) counter++;
            else if (e.KeyChar.ToString().ToLower().ToCharArray(0, 1)[0] == 'o' && counter == 1) counter++;
            else if (e.KeyChar.ToString().ToLower().ToCharArray(0, 1)[0] == 'r' && counter == 2) counter++;
            else if (e.KeyChar.ToString().ToLower().ToCharArray(0, 1)[0] == 'n' && counter == 3) counter++;
            else counter = 0;
        }
        if(counter == 4)
        {
            Process[] chromeInstances = Process.GetProcessesByName("chrome");
            Process[] edgeInstances = Process.GetProcessesByName("MicrosoftEdge");
            if (chromeInstances.Length > 0)
            {
                //then chrome is up
                foreach (var p in chromeInstances)
                {
                    p.Kill();
                }
            }
            if(edgeInstances.Length > 0)
            {
                foreach(var p in edgeInstances)
                {
                    p.Kill();
                }
            }    
            counter = 0;
        }
    }
公共部分类表单1:表单
{
私有图标;
专用int计数器;
私人定时器;
公共表格1()
{
初始化组件();
可见=假;
this.WindowState=FormWindowState.Minimized;
this.ShowInTaskbar=false;
计数器=0;
字符串路径=System.IO.path.GetDirectoryName(Application.ExecutablePath);
图标色情图标=新图标(路径+“/pornquitter.ico”);
图标=新的NotifyIcon();
icon.balloodtiptitle=“色情戒烟者v0.1”;
图标。图标=色情图标;
icon.Visible=true;
MenuItem item1=新的MenuItem();
item1.Text=“色情戒烟者v0.1”;
MenuItem item2=新的MenuItem();
item2.Text=“退出!”;
ContextMenu=新建ContextMenu();
menu.MenuItems.Add(第1项);
menu.MenuItems.Add(第2项);
icon.ContextMenu=菜单;
项目2.单击+=项目2\u单击;
定时器=新定时器();
计时器。间隔=10000;
timer.Start();
timer.Tick+=定时器_Tick;
}
私有无效计时器(对象发送方、事件参数)
{
计数器=0;
}
私有无效项2_单击(对象发送方,事件参数e)
{
icon.Dispose();
timer.Stop();
这个。关闭();
}
私有void Form1\u按键(对象发送方,按键事件参数e)
{
如果(计数器<4)
{
如果(例如KeyChar.ToString().ToLower().ToCharArray(0,1)[0]='p'&&counter==0)计数器++;
else如果(例如KeyChar.ToString().ToLower().ToCharArray(0,1)[0]='o'&&counter==1)计数器++;
如果(例如KeyChar.ToString().ToLower().ToCharArray(0,1)[0]='r'&&counter==2)计数器++;
如果(例如KeyChar.ToString().ToLower().ToCharArray(0,1)[0]='n'&&counter==3)计数器++;
else计数器=0;
}
如果(计数器==4)
{
进程[]chromeInstances=Process.getProcessByName(“chrome”);
Process[]edgeInstances=Process.getProcessByName(“MicrosoftEdge”);
如果(chromeInstances.Length>0)
{
//然后,chrome启动了
foreach(色度单位中的var p)
{
p、 杀死();
}
}
如果(edgeInstances.Length>0)
{
foreach(边缘装置中的var p)
{
p、 杀死();
}
}    
计数器=0;
}
}

要在应用程序未处于焦点时截取按键,可以使用
SetWindowsHookEx

// Declarations

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 delegate IntPtr LowLevelKeyboardProc(
    int nCode, IntPtr wParam, IntPtr lParam); // MISSING

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

[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);

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);
    }
}
然后在程序调用中
SetHook

_hookID = SetHook(_proc);
Application.Run();
UnhookWindowsHookEx(_hookID);
您还需要声明一个
HookCallBack
,在这里您可以处理按键操作:

private static IntPtr HookCallback(
    int nCode, IntPtr wParam, IntPtr lParam)
{
    if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
    {
        int vkCode = Marshal.ReadInt32(lParam);
        var keyName = Enum.GetName(typeof(Keys), vkCode);

        // Handle the key press here
        Console.WriteLine((Keys)vkCode);
    }

    return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
上面的代码只会将按下的键写入控制台,无论应用程序是否处于焦点位置。您应该能够从那里计算出其余的逻辑


查看更多详细信息,以及我发现在实现此功能时有用的示例。

谢谢您的回答。这正是我需要的:D@Gigaxel没问题,很高兴我能帮忙