diff --git a/mRemoteV1/App/NativeMethods.cs b/mRemoteV1/App/NativeMethods.cs
index c9250671d..595046262 100644
--- a/mRemoteV1/App/NativeMethods.cs
+++ b/mRemoteV1/App/NativeMethods.cs
@@ -382,12 +382,12 @@ namespace mRemoteNG.App
public const int WM_KEYUP = 0x101;
///
- ///
+ /// Posted to the window with the keyboard focus when a WM_KEYDOWN message is translated by the TranslateMessage function. The WM_CHAR message contains the character code of the key that was pressed.
///
public const int WM_CHAR = 0x102;
///
- ///
+ /// Sent when the user selects a command item from a menu, when a control sends a notification message to its parent window, or when an accelerator keystroke is translated.
///
public const int WM_COMMAND = 0x111;
diff --git a/mRemoteV1/Tools/MultiSSHController.cs b/mRemoteV1/Tools/MultiSSHController.cs
new file mode 100644
index 000000000..60384e6b7
--- /dev/null
+++ b/mRemoteV1/Tools/MultiSSHController.cs
@@ -0,0 +1,134 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+using System.Collections;
+using mRemoteNG.App;
+using mRemoteNG.Connection;
+using mRemoteNG.Connection.Protocol;
+
+namespace mRemoteNG.Tools
+{
+ class MultiSSHController
+ {
+ private ArrayList processHandlers = new ArrayList();
+ private ArrayList previousCommands = new ArrayList();
+ private int previousCommandIndex = 0;
+
+ public int CommandHistoryLength { get; set; } = 100;
+
+ public MultiSSHController(TextBox txtBox)
+ {
+ DecorateTextBox(txtBox);
+ }
+
+ public MultiSSHController(ToolStripTextBox txtBox)
+ {
+ DecorateTextBox(txtBox.TextBox);
+ }
+
+ private void DecorateTextBox(TextBox toBeDecorated)
+ {
+ toBeDecorated.Enter += refreshActiveConnections;
+ toBeDecorated.KeyDown += processKeyPress;
+ toBeDecorated.KeyUp += processKeyRelease;
+ }
+
+ private void SendAllKeystrokes(int keyType, int keyData)
+ {
+ if (processHandlers.Count == 0)
+ {
+ return;
+ }
+ foreach (PuttyBase proc in processHandlers)
+ {
+ NativeMethods.PostMessage(proc.PuttyHandle, keyType, new IntPtr(keyData), new IntPtr(0));
+ }
+ }
+
+#region Event Processors
+ private void refreshActiveConnections(object sender, EventArgs e)
+ {
+ var previouslyOpenedConnections = Runtime.ConnectionTreeModel.GetRecursiveChildList().Where(item => item.OpenConnections.Count > 0);
+
+ processHandlers.Clear();
+ foreach (ConnectionInfo connection in previouslyOpenedConnections)
+ {
+ foreach (ProtocolBase _base in connection.OpenConnections)
+ {
+ if (_base.GetType().IsSubclassOf(typeof(PuttyBase)))
+ {
+ processHandlers.Add((PuttyBase)_base);
+ }
+ }
+ }
+ }
+
+ private void processKeyPress(object sender, KeyEventArgs e)
+ {
+ TextBox txtMultiSSH = sender as TextBox;
+ if (txtMultiSSH == null) return;
+
+ if (processHandlers.Count == 0)
+ {
+ e.SuppressKeyPress = true;
+ return;
+ }
+
+ if (e.KeyCode == Keys.Up || e.KeyCode == Keys.Down)
+ {
+ e.SuppressKeyPress = true;
+ if (e.KeyCode == Keys.Up && previousCommandIndex - 1 >= 0)
+ {
+ previousCommandIndex -= 1;
+ }
+
+ if (e.KeyCode == Keys.Down && previousCommandIndex + 1 < previousCommands.Count)
+ {
+ previousCommandIndex += 1;
+ }
+
+ txtMultiSSH.Text = previousCommands[previousCommandIndex].ToString();
+ txtMultiSSH.Select(txtMultiSSH.TextLength, 0);
+ }
+
+ if (e.Control == true && e.KeyCode != Keys.V && e.Alt == false)
+ {
+ SendAllKeystrokes(NativeMethods.WM_KEYDOWN, e.KeyValue);
+ }
+
+ if (e.KeyCode == Keys.Enter)
+ {
+ string strLine = txtMultiSSH.Text;
+ foreach (char chr1 in strLine)
+ {
+ SendAllKeystrokes(NativeMethods.WM_CHAR, Convert.ToByte(chr1));
+ }
+ SendAllKeystrokes(NativeMethods.WM_KEYDOWN, 13); // Enter = char13
+ }
+ }
+
+ private void processKeyRelease(object sender, KeyEventArgs e)
+ {
+ TextBox txtMultiSSH = sender as TextBox;
+ if (txtMultiSSH == null) return;
+
+ if (e.KeyCode == Keys.Enter)
+ {
+ if (txtMultiSSH.Text.Trim() != "")
+ {
+ previousCommands.Add(txtMultiSSH.Text.Trim());
+ }
+ if (previousCommands.Count >= CommandHistoryLength)
+ {
+ previousCommands.RemoveAt(0);
+ }
+
+ previousCommandIndex = previousCommands.Count - 1;
+ txtMultiSSH.Clear();
+ }
+ }
+#endregion
+ }
+}
diff --git a/mRemoteV1/UI/Forms/frmMain.Designer.cs b/mRemoteV1/UI/Forms/frmMain.Designer.cs
index 7d8b6ca86..6f05da256 100644
--- a/mRemoteV1/UI/Forms/frmMain.Designer.cs
+++ b/mRemoteV1/UI/Forms/frmMain.Designer.cs
@@ -808,9 +808,6 @@ namespace mRemoteNG.UI.Forms
this.txtMultiSSH.Name = "txtMultiSSH";
this.txtMultiSSH.Size = new System.Drawing.Size(300, 25);
this.txtMultiSSH.ToolTipText = "Press ENTER to send. Ctrl+C is sent immediately.";
- this.txtMultiSSH.Enter += new System.EventHandler(this.txtMultiSSH_Enter);
- this.txtMultiSSH.KeyDown += new System.Windows.Forms.KeyEventHandler(this.txtMultiSSH_KeyDown);
- this.txtMultiSSH.KeyUp += new System.Windows.Forms.KeyEventHandler(this.txtMultiSSH_KeyUp);
//
// tmrAutoSave
//
diff --git a/mRemoteV1/UI/Forms/frmMain.cs b/mRemoteV1/UI/Forms/frmMain.cs
index 9b085fc40..25f34aa80 100644
--- a/mRemoteV1/UI/Forms/frmMain.cs
+++ b/mRemoteV1/UI/Forms/frmMain.cs
@@ -45,6 +45,7 @@ namespace mRemoteNG.UI.Forms
private SystemMenu _systemMenu;
private ConnectionTreeWindow ConnectionTreeWindow { get; set; }
private readonly IConnectionInitiator _connectionInitiator = new ConnectionInitiator();
+ private MultiSSHController _multiSSHController ;
private frmMain()
{
@@ -52,7 +53,8 @@ namespace mRemoteNG.UI.Forms
InitializeComponent();
_fullscreen = new Fullscreen(this);
pnlDock.Theme = new VS2012LightTheme();
- }
+ _multiSSHController = new MultiSSHController(txtMultiSSH);
+ }
static frmMain()
{
@@ -977,106 +979,6 @@ namespace mRemoteNG.UI.Forms
}
#endregion
- #region Multi SSH
- private ArrayList processHandlers = new ArrayList();
- private ArrayList previousCommands = new ArrayList();
- private int previousCommandIndex = 0;
-
- private void txtMultiSSH_Enter(object sender, EventArgs e)
- {
- var previouslyOpenedConnections = Runtime.ConnectionTreeModel.GetRecursiveChildList().Where(item => item.OpenConnections.Count > 0);
-
- processHandlers.Clear();
- foreach (ConnectionInfo connection in previouslyOpenedConnections)
- {
- foreach (ProtocolBase _base in connection.OpenConnections)
- {
- if (_base.GetType().IsSubclassOf(typeof(PuttyBase)))
- {
- processHandlers.Add((PuttyBase)_base);
- }
- }
- }
- }
-
- private void txtMultiSSH_KeyDown(object sender, KeyEventArgs e)
- {
- if (processHandlers.Count == 0)
- {
- e.SuppressKeyPress = true;
- return;
- }
-
- if (e.KeyCode == Keys.Up || e.KeyCode == Keys.Down)
- {
- e.SuppressKeyPress = true;
- if (e.KeyCode == Keys.Up && previousCommandIndex - 1 >= 0)
- {
- previousCommandIndex -= 1;
- }
-
- if (e.KeyCode == Keys.Down && previousCommandIndex + 1 < previousCommands.Count)
- {
- previousCommandIndex += 1;
- }
-
- txtMultiSSH.Text = previousCommands[previousCommandIndex].ToString();
- txtMultiSSH.Select(txtMultiSSH.TextLength, 0);
- }
-
- if (e.Control == true && e.KeyCode != Keys.V && e.Alt == false)
- {
- sendAllKey(NativeMethods.WM_KEYDOWN, e.KeyValue);
- }
-
- if (e.KeyCode == Keys.Enter)
- {
- string strLine = txtMultiSSH.Text;
- foreach (char chr1 in strLine)
- {
- sendAllKey(NativeMethods.WM_CHAR, Convert.ToByte(chr1));
- }
- sendAllKey(NativeMethods.WM_KEYDOWN, 13); // Enter = char13
- }
- }
-
- private void saveLastCommand()
- {
- if (txtMultiSSH.Text.Trim() != "")
- {
- previousCommands.Add(txtMultiSSH.Text.Trim());
- }
- if (previousCommands.Count >= 100)
- {
- // Don't keep too many. TODO: make this configurable
- previousCommands.RemoveAt(0);
- }
-
- previousCommandIndex = previousCommands.Count - 1;
- txtMultiSSH.Clear();
- }
-
- private void sendAllKey(int keyType, int keyData)
- {
- if (processHandlers.Count == 0)
- {
- return;
- }
- foreach (PuttyBase proc in processHandlers)
- {
- NativeMethods.PostMessage(proc.PuttyHandle, keyType, new IntPtr(keyData), new IntPtr(0));
- }
- }
-
- private void txtMultiSSH_KeyUp(object sender, KeyEventArgs e)
- {
- if (e.KeyCode == Keys.Enter)
- {
- saveLastCommand();
- }
- }
- #endregion
-
#region Info
private void mMenInfoHelp_Click(object sender, EventArgs e)
{
diff --git a/mRemoteV1/mRemoteV1.csproj b/mRemoteV1/mRemoteV1.csproj
index 22f9436f9..895bc606d 100644
--- a/mRemoteV1/mRemoteV1.csproj
+++ b/mRemoteV1/mRemoteV1.csproj
@@ -220,6 +220,7 @@
+