You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#实现按Esc键退出程序方案求助(CancelKeyPress事件无效)

实现Esc键随时退出程序的方案

针对你需要按Esc键随时退出程序但CancelKeyPress事件无法满足需求的问题,分不同应用场景给出新手友好的实现方案:

一、控制台应用(以C#为例)

控制台程序的CancelKeyPress仅响应Ctrl+C,要监听Esc键可以用循环检查按键输入:

using System;

class Program
{
    static void Main()
    {
        Console.WriteLine("按Esc键退出程序...");
        
        while (true)
        {
            // 检查是否有按键按下
            if (Console.KeyAvailable)
            {
                var pressedKey = Console.ReadKey(true); // true表示不显示按键字符
                if (pressedKey.Key == ConsoleKey.Escape)
                {
                    Console.WriteLine("\n程序已退出");
                    break; // 退出循环,结束程序
                }
            }
            
            // 这里放你的主业务逻辑,比如处理任务、等待操作等
            System.Threading.Thread.Sleep(100); // 降低CPU占用率
        }
    }
}

二、Windows桌面应用

1. Windows Forms(C#)

给主窗体开启按键预览,并监听KeyDown事件:

  • 选中主窗体,在属性面板把KeyPreview设为True(让窗体优先接收按键事件)
  • 双击窗体的KeyDown事件,添加代码:
private void MainForm_KeyDown(object sender, KeyEventArgs e)
{
    if (e.KeyCode == Keys.Escape)
    {
        Application.Exit(); // 彻底退出整个应用程序
        // 也可以用 this.Close(); 关闭当前窗体
    }
}

2. WPF(C#)

给主窗口添加KeyDown事件:

private void MainWindow_KeyDown(object sender, KeyEventArgs e)
{
    if (e.Key == Key.Escape)
    {
        Application.Current.Shutdown(); // 关闭整个WPF应用
    }
}

三、全局按键监听(适合需要后台也响应Esc的场景)

如果要求不管程序是否在前台,按下Esc都能退出,需要用全局键盘钩子。以下是简化版实现(需引用System.Windows.Forms):

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

class GlobalEscListener
{
    private const int WH_KEYBOARD_LL = 13;
    private const int WM_KEYDOWN = 0x0100;
    private static LowLevelKeyboardProc _hookProc = HookCallback;
    private static IntPtr _hookId = IntPtr.Zero;

    public static void Main()
    {
        _hookId = SetKeyboardHook(_hookProc);
        Application.Run(); // 启动消息循环
        UnhookWindowsHookEx(_hookId); // 释放钩子
    }

    private static IntPtr SetKeyboardHook(LowLevelKeyboardProc proc)
    {
        using (var currentProcess = System.Diagnostics.Process.GetCurrentProcess())
        using (var mainModule = currentProcess.MainModule)
        {
            return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(mainModule.ModuleName), 0);
        }
    }

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

    private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
    {
        if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
        {
            int keyCode = Marshal.ReadInt32(lParam);
            if ((Keys)keyCode == Keys.Escape)
            {
                Console.WriteLine("Esc键触发,程序退出");
                Application.Exit();
            }
        }
        return CallNextHookEx(_hookId, nCode, wParam, lParam);
    }

    // 导入Windows API函数
    [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);
}

注意:全局钩子可能需要管理员权限才能正常运行,适合必须确保随时响应的场景。

内容的提问来源于stack exchange,提问作者WizzzyTM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 22:25:23