模拟CMD命令窗体
定义一个继承TextBox的控件类
1:拥有自定义命令开头标识(如:>> )可自行调整为CMD等
2:接收回传信息自动换行并加上命令开头标识
3:可以通过上下键翻指令
4:回车发送指令
5:可以复杂粘贴指令
6:可以监听组合键,实现组合键执行特定指令操作(如:Ctrl+C清除输出记录)
public class CommandTextControl : TextBox
{
#region 常量
const string topLable = ">>";
#endregion
#region 属性值
private int ItemIndex = 0;//命令下标索引
private int cmdtextlineNum;
/// <summary>
/// 当前可以输入命令的行号
/// </summary>
public int MycmdtextlineNum
{
get => cmdtextlineNum;
set
{
value = value < 0 ? value++ : value;
cmdtextlineNum = value;
}
}
/// <summary>
/// 默认命令集合
/// </summary>
private List<string> DefaultCommandLiat = new List<string>
{ "CHDHelp","CMDLogOFF","CMDNormal"};
/// <summary>
/// 发送命令集合
/// </summary>
private List<string> SendCommandLiat = new List<string> { };
private string commandStr;
/// <summary>
/// 发送指令
/// </summary>
public string CommandStr
{
get => commandStr;
set
{
commandStr= value.Replace(topLable,"");
}
}
#endregion
public CommandTextControl()
{
this.Text += topLable;
this.PreviewKeyDown += new KeyEventHandler(ConsoleTextBox_KeyDown);
this.TextChanged += CMD_Changed;
}
#region 公有方法
private void ConsoleTextBox_KeyDown(object sender, KeyEventArgs e)
{
string AdhesivePlate = this.SelectedText;
GetLineNum();
if (e.KeyboardDevice.Modifiers.HasFlag(ModifierKeys.Control) && e.Key == Key.C)
{
if (!string.IsNullOrEmpty(AdhesivePlate))
{
Clipboard.SetDataObject(AdhesivePlate);
}
else
{
CommandStr = DefaultCommandLiat.Last();
SendCommand();
}
}
switch (e.Key)
{
case Key.Up:
OverRecored(true);
e.Handled = true;
break;
case Key.Down:
OverRecored(false);
e.Handled = true;
break;
case Key.Left:
case Key.Right:
case Key.Back:
LR_AND_ReMove(e);
break;
case Key.Enter:
CommandStr = lines.Count>0?lines[MycmdtextlineNum - 1]:"";
SendCommand();
break;
default:
if (!string.IsNullOrEmpty(AdhesivePlate))
{
return;
}
break;
}
}
#endregion
#region 私有方法
StringCollection lines = new StringCollection();
/// <summary>
/// 获取总行数
/// </summary>
/// <returns></returns>
private StringCollection GetLineNum()
{
lines.Clear();
for (int line = 0; line < MycmdtextlineNum; line++)
lines.Add(this.GetLineText(line));
return lines;
}
/// <summary>
/// 新增命令输入行
/// </summary>
/// <param name="comm">命令内容可空</param>
private void AddOneLine(string comm=null)
{
this.Text += "\r\n" + topLable+ comm;
this.SelectionStart = this.Text.Length;
}
/// <summary>
/// 输出命令反馈内容
/// </summary>
/// <param name="outvalue">反馈内容</param>
private void AddLogOutput(string outvalue)
{
this.Text += "\r\n" + outvalue;
AddOneLine();
this.SelectionStart = this.Text.Length;
}
/// <summary>
/// 发送指令
/// </summary>
private void SendCommand()
{
if (CommandStr.ToLower().Equals("cls"))
{
Clear();
this.Text += topLable;
this.SelectionStart = this.Text.Length;
return;
}
if (string.IsNullOrEmpty(CommandStr))
{
return;
}
if (SendCommandLiat.Count>0)
{
string obj= SendCommandLiat.Last();
if (obj!= CommandStr)
{
SendCommandLiat.Add(CommandStr);
}
}
else
{
SendCommandLiat.Add(CommandStr);
}
ItemIndex = SendCommandLiat.Count - 1;
AddLogOutput(string.Format("发送执行》》》{0}", CommandStr));
}
/// <summary>
/// 翻阅指令记录
/// </summary>
/// <param name="isUp"></param>
private void OverRecored(bool isUp)
{
if (SendCommandLiat.Count > 0)
{
string[] sArray = this.Text.Split(new char[2] { '\r', '\n' });
if (isUp)
{
ItemIndex = ItemIndex >= 1 ? (ItemIndex - 1) : 0;
CommandStr = SendCommandLiat[ItemIndex];
}
else
{
ItemIndex = ItemIndex < (SendCommandLiat.Count - 1) ? ItemIndex + 1 : ItemIndex;
CommandStr = SendCommandLiat[ItemIndex];
}
if (sArray.Last()== topLable || sArray.Last().Contains(topLable))
{
string oldvalues= this.Text;
string newvalues= oldvalues.Remove(oldvalues.Length - sArray.Last().Length);
this.Dispatcher.Invoke(new Action((delegate {
this.Text="";
this.Text += newvalues + topLable + CommandStr;
})));
this.SelectionStart = this.Text.Length;
}
else
{
}
}
}
/// <summary>
/// 左右移动光标
/// </summary>
private void LR_AND_ReMove(KeyEventArgs e)
{
//获取光标所在行
int CurrentLineNumber = GetLineIndexFromCharacterIndex(this.SelectionStart);
//光标所在行第一个字符偏移量
int lineFristCharOffset = this.GetCharacterIndexFromLineIndex(CurrentLineNumber);
//当前光标偏移量
int currentCharOffset =e.Key==Key.Left?this.SelectionStart-1:this.SelectionStart+1;
//计算当前行的光标的偏移量
int spanHeadLength = currentCharOffset - lineFristCharOffset;
if (CurrentLineNumber + 1 != MycmdtextlineNum)
{
this.SelectionStart = this.Text.Length;
e.Handled = true;
return;
}
else
{
if (spanHeadLength >= topLable.Length)
{
if (e.Key == Key.Back)
{
if (spanHeadLength == topLable.Length+1)
{
e.Handled = true;
return;
}
}
return;
}
else
{
e.Handled = true;
return;
}
}
}
private void CMD_Changed(object sender, TextChangedEventArgs e)
{
MycmdtextlineNum = this.LineCount;
}
#endregion
}
界面引用该控件
<Window x:Class="NewLayout.CMD_Window"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:Com="clr-namespace:NewLayout"
mc:Ignorable="d"
Title="CMD_Window" Height="450" Width="800">
<Com:CommandTextControl Foreground="White" Background="Black"/>
</Window>
效果演示
回车发送指令以及上下翻指令记录