C#Windows命令Shell-拦截/捕获Ctrl-A,Shift-Left/Right等 我编写Windows Shell(CMD,而不是PS)应用程序,并创建了自定义输入字段处理程序,我希望UI支持传统的控制键进行导航/选择/选择/copying/

问题描述 投票:0回答:1
TreatCtrlCAsInput

'标志,但是我在拦截这些输入并将外壳的鼻子放在其上方面没有任何成功。 还有另一个功能吗?我需要设置另一个标志吗?我无法想象命令壳应用程序运行时不可能拥有键盘,但是,在搜索一段时间后,我发现的所有信息都与Windows“表单”范围内的工作有关,我没有t找到了与命令壳的天生行为有关的任何内容。 这是我目前构建的输入管理函数: public override ConsoleKeyInfo Activate( string value = "" ) { base.Value = string.IsNullOrEmpty( value ) ? this.Value : value; this.Active = true; this.CursorPosition = new( 0, 0 ); bool saveState = Console.TreatControlCAsInput; while (true) { var key = Console.ReadKey( true ); switch (key.Key) { case ConsoleKey.DownArrow: if (this.CursorPosition.Y + 1 >= this.Size.Height) return key; CursorPosition = new( CursorPosition.X, CursorPosition.Y + 1 ); break; case ConsoleKey.UpArrow: if (this.CursorPosition.Y == 0) return key; CursorPosition = new( CursorPosition.X, CursorPosition.Y - 1 ); break; case ConsoleKey.RightArrow: if (this.CurrentIndex < MaxLength) { int start = this.CurrentIndex; if (key.Modifiers.HasFlag( ConsoleModifiers.Control )) { int i = this.CurrentIndex; while (i < Length && this.Value[ i++ ] == ' ') ; while (i < Length && this.Value[ i++ ] != ' ') ; this.CurrentIndex = Math.Min( Length, i ); } else this.CurrentIndex += 1; if (key.Modifiers.HasFlag( ConsoleModifiers.Shift )) this.Selection = (start, this.CurrentIndex - start); } break; case ConsoleKey.LeftArrow: if (this.CurrentIndex > 0) { int start = this.CurrentIndex; if (key.Modifiers.HasFlag( ConsoleModifiers.Control )) { int i = this.CurrentIndex; while (i > 0 && this.Value[ --i ] == ' ') ; while (i > 0 && this.Value[ --i ] != ' ') ; this.CurrentIndex = Math.Max( 0, i + 1 ); } else this.CurrentIndex -= 1; if (key.Modifiers.HasFlag( ConsoleModifiers.Shift )) this.Selection = (this.CurrentIndex, start - this.CurrentIndex); } break; case ConsoleKey.Home: if (key.Modifiers.HasFlag( ConsoleModifiers.Control )) this.CurrentIndex = 0; else this.CursorPosition = new( 0, this.CursorPosition.Y ); break; case ConsoleKey.End: if (key.Modifiers.HasFlag( ConsoleModifiers.Control )) this.CurrentIndex = this.Value.Length; else this.CursorPosition = new( this.Lines[ this.CursorPosition.Y ].Length, this.CursorPosition.Y ); break; case ConsoleKey.Backspace: if (Enabled && this.CurrentIndex > 0) { this.CurrentIndex -= 1; goto Delete; } break; case ConsoleKey.Delete: Delete: if (Enabled && SelectedText.Length > 0) { if (key.Modifiers.HasFlag( ConsoleModifiers.Shift )) { System.Windows.Forms.Clipboard.SetText( this.Value.Substring( this.SelectionStart, this.SelectionLength ) ); SystemSounds.Asterisk.Play(); } this.Value = this.Value.Remove( this.SelectionStart, this.SelectionLength ); break; } if (Enabled && this.CurrentIndex < this.Value.Length) this.Value = this.Value.Remove( this.CurrentIndex, 1 ); break; case ConsoleKey.A: if (!key.Modifiers.HasFlag( ConsoleModifiers.Control )) goto default; this.Selection = (0, Length); Draw(); break; case ConsoleKey.V: if (key.Modifiers.HasFlag( ConsoleModifiers.Control )) goto Insert; goto default; case ConsoleKey.Insert: if (!key.Modifiers.HasFlag( ConsoleModifiers.Shift ) || !System.Windows.Forms.Clipboard.ContainsText()) break; Insert: string s = System.Windows.Forms.Clipboard.GetText(); this.SelectionLength = s.Length; this.SelectedText = s; break; case ConsoleKey.Tab: case ConsoleKey.Enter: case ConsoleKey.Escape: this.Active = false; Console.TreatControlCAsInput = saveState; return key; case ConsoleKey.X: // Cut if (!key.Modifiers.HasFlag( ConsoleModifiers.Control )) goto default; if (this.SelectionLength > 0) { System.Windows.Forms.Clipboard.SetText( this.SelectedText ); SystemSounds.Asterisk.Play(); this.SelectedText = ""; } break; case ConsoleKey.C: if (!key.Modifiers.HasFlag( ConsoleModifiers.Control )) goto default; if (this.SelectionLength > 0) { System.Windows.Forms.Clipboard.SetText( this.SelectedText ); SystemSounds.Asterisk.Play(); } break; default: if (Length < MaxLength && RxFilter.IsMatch( $"{key.KeyChar}" )) { this.Value = this.Value.Insert( this.CurrentIndex, $"{key.KeyChar}" ); this.CurrentIndex += 1; } else SystemSounds.Beep.Play(); break; } }; }

编辑(澄清):好的,与我先前的看法相反,上面的代码显然是不参见/响应有关键的输入,它没有处理它们,甚至不认识他们被按下。壳本身肯定在捕获并行动在他们身上...

    
您已经在Windows上遇到了一个非常具体且具有挑战性的领域,并且您对核心问题绝对正确:命令shell(cmd.exe)本身正在拦截您应用程序之前的这些特定的密钥组合有机会通过
Console.ReadKey()

。 您在您的假设中也是正确的,即您的应用程序cmd.exe接管根本不会处理关键组合!这解释了甚至没有显示的基本修饰符。

CMD.EXE是一个非常古老的应用程序,它具有通过许多版本的Windows延续的深深根深蒂固的关键绑定和行为。 CTRL+A,CTRL+HOME/END和SHIFT+ARROW等关键组合传统上用于各种控制台级操作。

这些关键组合在键盘输入管道的早期就被

cmd.exe
拦截了。这是一个尚无法拦截的时刻。

使用Console.ReadKey().

时,不是一个单一的直接解决方案,可以完全防止Windows命令Shell从标准CMD控制台内部拦截特定的输入键。
c# windows user-interface input cmd
1个回答
0
投票

© www.soinside.com 2019 - 2025. All rights reserved.