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
相关产品推荐
相关产品推荐

