MSDN.WhiteKnight - Stack Overflow answers
Ответ на "Как отлеживать нажатие левой кнопки мыши в консольном приложении C#?"
Answer 1202008
Ответ aepot правильный, но он слишком переусложнен (в первой редакции) и это можно реализовать проще. Здесь асинхронный код вообще не нужен, без него проблемы дедлока не будет и можно дождаться завершения через WaitHandle.WaitOne:
public class ConsoleInputHandler : IDisposable { public delegate void ConsoleMouseEvent(MouseRecord r); public delegate void ConsoleKeyEvent(KeyboardRecord r); public delegate void ConsoleWindowBufferSizeEvent(WindowBufferSizeRecord r); public event ConsoleMouseEvent MouseEvent; public event ConsoleKeyEvent KeyEvent; public event ConsoleWindowBufferSizeEvent WindowBufferSizeEvent; private readonly CancellationTokenSource _cts; public ConsoleInputHandler() { _cts = new CancellationTokenSource(); } public void Run() { IntPtr handle = NativeMethods.GetStdHandle(ConsoleInputHandle.StandardInput); InputRecord[] inputBuffer = new InputRecord[10]; CancellationToken token = _cts.Token; int numRead = 0; while (!token.IsCancellationRequested) { if (NativeMethods.ReadConsoleInput(handle, inputBuffer, inputBuffer.Length, ref numRead)) { for (int i = 0; i < numRead; i++) { switch (inputBuffer[i].EventType) { case ConsoleEventType.Mouse: MouseEvent?.Invoke(inputBuffer[i].MouseEvent); break; case ConsoleEventType.Keyboard: KeyEvent?.Invoke(inputBuffer[i].KeyEvent); break; case ConsoleEventType.WindowBufferSize: WindowBufferSizeEvent?.Invoke(inputBuffer[i].WindowBufferSizeEvent); break; case ConsoleEventType.Menu: case ConsoleEventType.Focus: break; } } } else break; } } public void Stop() { if (disposed) throw new ObjectDisposedException(nameof(ConsoleInputHandler)); if (!_cts.IsCancellationRequested) _cts.Cancel(); _cts.Token.WaitHandle.WaitOne(); } private bool disposed; public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (disposed) throw new ObjectDisposedException(nameof(ConsoleInputHandler)); if (!_cts.IsCancellationRequested) { _cts.Cancel(); } _cts.Token.WaitHandle.WaitOne(); if (disposing) { _cts.Dispose(); } disposed = true; } ~ConsoleInputHandler() => Dispose(false); } class Program { static ConsoleInputHandler inputHandler; static void Main(string[] args) { SetupConsole(); using (inputHandler = new ConsoleInputHandler()) { inputHandler.MouseEvent += ConsoleListener_MouseEvent; inputHandler.KeyEvent += ConsoleListener_KeyEvent; inputHandler.Run(); } Console.WriteLine("Exited."); Console.ReadKey(); } private static void ConsoleListener_KeyEvent(KeyboardRecord r) { if (r.KeyDown && r.VirtualKeyCode == (ushort)ConsoleKey.Escape) { inputHandler.Stop(); } else { int width = Console.BufferWidth - 1; Console.SetCursorPosition(0, 0); Console.WriteLine($"KeyDown: {r.KeyDown}".PadRight(width)); Console.WriteLine($"KeyChar: {r.UnicodeChar}, ConsoleKey: {(ConsoleKey)r.VirtualKeyCode}".PadRight(width)); Console.WriteLine($"RepeatCount: {r.RepeatCount}".PadRight(width)); Console.WriteLine($"Controls: {r.ControlKeyState}".PadRight(width)); } } private static void SetupConsole() { IntPtr handle = NativeMethods.GetStdHandle(ConsoleInputHandle.StandardInput); ConsoleMode mode = 0; NativeMethods.GetConsoleMode(handle, ref mode); mode &= ~ConsoleMode.QuickEditMode; NativeMethods.SetConsoleMode(handle, mode); } private static void ConsoleListener_MouseEvent(MouseRecord r) { int width = Console.BufferWidth - 1; Console.SetCursorPosition(0, 0); Console.WriteLine($"Position: {r.Position.X}, {r.Position.Y}".PadRight(width)); Console.WriteLine($"Buttons: {r.ButtonState}".PadRight(width)); Console.WriteLine($"Flags: {r.EventFlags}".PadRight(width)); Console.WriteLine($"Controls: {r.ControlKeyState}".PadRight(width)); } }
Content is retrieved from StackExchange API.
Auto-generated by ruso-archive tools.