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()
.