WingMan – Rev 4
?pathlinks?
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Resources;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Gma.System.MouseKeyHook;
using WingMan.Communication;
using WingMan.Host;
namespace WingMan
{
public partial class WingManForm : Form
{
private MQTTServer MQTTServer { get; set; }
private MQTTClient MQTTClient { get; set; }
private SemaphoreSlim MQTTServerSemaphore {get; set;} = new SemaphoreSlim(1, 1);
private SemaphoreSlim MQTTClientSemaphore { get; set; } = new SemaphoreSlim(1, 1);
private static IKeyboardMouseEvents MouseKeyApplicationHook { get; set; }
private static IKeyboardMouseEvents MouseKeyGlobalHook { get; set; }
private List<string> MouseKeyCombo { get; set; }
private HelmBindings HelmBindings { get; set; }
private BindingSource HelmBindingSource { get; set; }
public ConcurrentDictionary<string, HelmBindings> WingBindings { get; set; }
public WingManForm()
{
InitializeComponent();
MouseKeyGlobalHook = Hook.GlobalEvents();
MQTTClient = new MQTTClient(this);
MQTTServer = new MQTTServer(this);
HelmBindings = new HelmBindings();
HelmBindings.Bindings = new List<HelmBinding>();
HelmBindingSource = new BindingSource();
HelmBindingSource.DataSource = HelmBindings.Bindings;
HelmBindingsListBox.DisplayMember = "DisplayName";
HelmBindingsListBox.ValueMember = "Keys";
HelmBindingsListBox.DataSource = HelmBindingSource;
WingBindings = new ConcurrentDictionary<string, HelmBindings>();
}
private void AddressTextBoxClick(object sender, EventArgs e)
{
Address.BackColor = Color.Empty;
}
private void PortTextBoxClick(object sender, EventArgs e)
{
Port.BackColor = Color.Empty;
}
private async void HostButtonClickAsync(object sender, EventArgs e)
{
// Stop the MQTT server if it is running.
if (MQTTServer.ServerRunning)
{
await StopServer();
toolStripStatusLabel.Text = Properties.Strings.Server_stopped;
HostButton.BackColor = Color.Empty;
// Enable controls.
ConnectButton.Enabled = true;
EnableConnectionControls();
return;
}
if (!ValidateAddressPort(out var ipAddress, out var port, out var nick))
return;
// Start the MQTT server.
await StartServer(ipAddress, port, nick);
toolStripStatusLabel.Text = Properties.Strings.Server_started;
HostButton.BackColor = Color.Aquamarine;
// Disable controls
ConnectButton.Enabled = false;
DisableConnectionControls();
}
private void DisableConnectionControls()
{
Address.Enabled = false;
Port.Enabled = false;
Nick.Enabled = false;
}
private void EnableConnectionControls()
{
Address.Enabled = true;
Port.Enabled = true;
Nick.Enabled = true;
}
private bool ValidateAddressPort(out IPAddress address, out int port, out string nick)
{
address = IPAddress.Any;
port = 0;
nick = string.Empty;
if (string.IsNullOrEmpty(Address.Text) &&
string.IsNullOrEmpty(Port.Text) &&
string.IsNullOrEmpty(Nick.Text))
{
Address.BackColor = Color.LightPink;
Port.BackColor = Color.LightPink;
Nick.BackColor = Color.LightPink;
return false;
}
if (!IPAddress.TryParse(Address.Text, out address))
{
Address.BackColor = Color.LightPink;
return false;
}
if (!uint.TryParse(Port.Text, out var uPort))
{
Port.BackColor = Color.LightPink;
return false;
}
port = (int) uPort;
if (string.IsNullOrEmpty(Nick.Text))
{
Nick.BackColor = Color.LightPink;
return false;
}
nick = Nick.Text;
Address.BackColor = Color.Empty;
Port.BackColor = Color.Empty;
Nick.BackColor = Color.Empty;
return true;
}
private async Task StartServer(IPAddress ipAddress, int port, string nick)
{
await MQTTServerSemaphore.WaitAsync();
try
{
await MQTTServer.Start(ipAddress, port, nick);
}
finally
{
MQTTServerSemaphore.Release();
}
}
private async Task StopServer()
{
await MQTTServerSemaphore.WaitAsync();
try
{
await MQTTServer.Stop();
}
finally
{
MQTTServerSemaphore.Release();
}
}
private async void ConnectButtonClickAsync(object sender, EventArgs e)
{
if (MQTTClient.ClientRunning)
{
await StopClient();
ConnectButton.Text = Properties.Strings.Connect;
ConnectButton.BackColor = Color.Empty;
EnableConnectionControls();
HostButton.Enabled = true;
return;
}
if (!ValidateAddressPort(out var ipAddress, out var port, out var nick))
return;
await StartClient(ipAddress, port, nick);
toolStripStatusLabel.Text = Properties.Strings.Client_started;
ConnectButton.Text = Properties.Strings.Disconnect;
ConnectButton.BackColor = Color.Aquamarine;
HostButton.Enabled = false;
DisableConnectionControls();
}
private async Task StopClient()
{
await MQTTClientSemaphore.WaitAsync();
try
{
await MQTTClient.Stop();
}
finally
{
MQTTClientSemaphore.Release();
}
}
private async Task StartClient(IPAddress ipAddress, int port, string nick)
{
await MQTTClientSemaphore.WaitAsync();
try
{
await MQTTClient.Start(ipAddress, port, nick);
}
finally
{
MQTTClientSemaphore.Release();
}
}
private async void LobbySayTextBoxKeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode != Keys.Enter)
return;
if (MQTTServer.ServerRunning)
{
await MQTTServer.BroadcastLobbyMessage(LobbySayTextBox.Text);
}
if (MQTTClient.ClientRunning)
{
await MQTTClient.BroadcastLobbyMessage(LobbySayTextBox.Text);
}
}
private void HelmAddButtonClick(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(HelmNameTextBox.Text))
{
HelmNameTextBox.BackColor = Color.LightPink;
return;
}
HelmAddButton.Enabled = false;
MouseKeyCombo = new List<string>();
MouseKeyApplicationHook = Hook.AppEvents();
MouseKeyApplicationHook.MouseDown += MouseKeyHookOnMouseDown;
MouseKeyApplicationHook.KeyUp += MouseKeyHookOnKeyUp;
MouseKeyApplicationHook.KeyDown += MouseKeyHookOnKeyDown;
MouseKeyApplicationHook.MouseUp += MouseKeyHookOnMouseUp;
}
private void MouseKeyHookOnKeyUp(object sender, KeyEventArgs e)
{
HelmBindings.Bindings.Add(new HelmBinding
{
Keys = MouseKeyCombo,
Name = HelmNameTextBox.Text
});
HelmBindingSource.ResetBindings(false);
MouseKeyApplicationHook.KeyDown -= MouseKeyHookOnKeyDown;
MouseKeyApplicationHook.KeyUp -= MouseKeyHookOnKeyUp;
MouseKeyApplicationHook.Dispose();
HelmNameTextBox.Text = string.Empty;
HelmAddButton.Enabled = true;
}
private void MouseKeyHookOnMouseUp(object sender, MouseEventArgs e)
{
HelmBindings.Bindings.Add(new HelmBinding
{
Keys = MouseKeyCombo,
Name = HelmNameTextBox.Text
});
HelmBindingSource.ResetBindings(false);
MouseKeyApplicationHook.KeyDown -= MouseKeyHookOnKeyDown;
MouseKeyApplicationHook.KeyUp -= MouseKeyHookOnKeyUp;
MouseKeyApplicationHook.Dispose();
HelmNameTextBox.Text = string.Empty;
HelmAddButton.Enabled = true;
}
private void MouseKeyHookOnMouseDown(object sender, MouseEventArgs e)
{
MouseKeyCombo.Add(MouseButtonToName(e.Button));
}
private void MouseKeyHookOnKeyDown(object sender, KeyEventArgs e)
{
e.SuppressKeyPress = true;
MouseKeyCombo.Add(KeyCodeToName((int) e.KeyCode));
}
private void HelmNameTextBoxClick(object sender, EventArgs e)
{
HelmNameTextBox.BackColor = Color.Empty;
}
private string MouseButtonToName(MouseButtons button)
{
var mouseButton = string.Empty;
switch (button)
{
case MouseButtons.Left:
mouseButton = "Left Mouse Button";
break;
case MouseButtons.Middle:
mouseButton = "Middle Mouse Button";
break;
case MouseButtons.Right:
mouseButton = "Right Mouse Button";
break;
}
return mouseButton;
}
private string KeyCodeToName(int code)
{
var keyString = string.Empty;
switch (code)
{
case 0:
break;
case 1:
keyString = "Mouse Left";
break;
case 2:
keyString = "Mouse Right";
break;
case 3:
keyString = "Cancel";
break;
case 4:
keyString = "Mouse Middle";
break;
case 5:
keyString = "Special 1";
break;
case 6:
keyString = "Special 2";
break;
case 8:
keyString = "Back";
break;
case 9:
keyString = "TAB";
break;
case 12:
keyString = "Clear";
break;
case 13:
keyString = "Enter";
break;
case 16:
keyString = "Shift";
break;
case 17:
keyString = "Ctrl";
break;
case 18:
keyString = "Menu";
break;
case 19:
keyString = "Pause";
break;
case 20:
keyString = "Caps Lock";
break;
case 21:
keyString = "Kana/Hangul";
break;
case 23:
keyString = "Junja";
break;
case 24:
keyString = "Final";
break;
case 25:
keyString = "Hanja/Kanji";
break;
case 27:
keyString = "Esc";
break;
case 28:
keyString = "Convert";
break;
case 29:
keyString = "NonConvert";
break;
case 30:
keyString = "Accept";
break;
case 31:
keyString = "Mode";
break;
case 32:
keyString = "Space";
break;
case 33:
keyString = "Page Up";
break;
case 34:
keyString = "Page Down";
break;
case 35:
keyString = "End";
break;
case 36:
keyString = "Home";
break;
case 37:
keyString = "Left";
break;
case 38:
keyString = "Up";
break;
case 39:
keyString = "Right";
break;
case 40:
keyString = "Down";
break;
case 41:
keyString = "Select";
break;
case 42:
keyString = "Print";
break;
case 43:
keyString = "Execute";
break;
case 44:
keyString = "Snapshot";
break;
case 45:
keyString = "Insert";
break;
case 46:
keyString = "Delete";
break;
case 47:
keyString = "Help";
break;
case 48:
keyString = "Num 0";
break;
case 49:
keyString = "Num 1";
break;
case 50:
keyString = "Num 2";
break;
case 51:
keyString = "Num 3";
break;
case 52:
keyString = "Num 4";
break;
case 53:
keyString = "Num 5";
break;
case 54:
keyString = "Num 6";
break;
case 55:
keyString = "Num 7";
break;
case 56:
keyString = "Num 8";
break;
case 57:
keyString = "Num 9";
break;
case 65:
keyString = "A";
break;
case 66:
keyString = "B";
break;
case 67:
keyString = "C";
break;
case 68:
keyString = "D";
break;
case 69:
keyString = "E";
break;
case 70:
keyString = "F";
break;
case 71:
keyString = "G";
break;
case 72:
keyString = "H";
break;
case 73:
keyString = "I";
break;
case 74:
keyString = "J";
break;
case 75:
keyString = "K";
break;
case 76:
keyString = "L";
break;
case 77:
keyString = "M";
break;
case 78:
keyString = "N";
break;
case 79:
keyString = "O";
break;
case 80:
keyString = "P";
break;
case 81:
keyString = "Q";
break;
case 82:
keyString = "R";
break;
case 83:
keyString = "S";
break;
case 84:
keyString = "T";
break;
case 85:
keyString = "U";
break;
case 86:
keyString = "V";
break;
case 87:
keyString = "W";
break;
case 88:
keyString = "X";
break;
case 89:
keyString = "Y";
break;
case 90:
keyString = "Z";
break;
case 91:
keyString = "Windows Left";
break;
case 92:
keyString = "Windows Right";
break;
case 93:
keyString = "Application";
break;
case 95:
keyString = "Sleep";
break;
case 96:
keyString = "NumPad 0";
break;
case 97:
keyString = "NumPad 1";
break;
case 98:
keyString = "NumPad 2";
break;
case 99:
keyString = "NumPad 3";
break;
case 100:
keyString = "NumPad 4";
break;
case 101:
keyString = "NumPad 5";
break;
case 102:
keyString = "NumPad 6";
break;
case 103:
keyString = "NumPad 7";
break;
case 104:
keyString = "NumPad 8";
break;
case 105:
keyString = "NumPad 9";
break;
case 106:
keyString = "NumPad *";
break;
case 107:
keyString = "NumPad +";
break;
case 108:
keyString = "NumPad .";
break;
case 109:
keyString = "NumPad -";
break;
case 110:
keyString = "NumPad ,";
break;
case 111:
keyString = "NumPad /";
break;
case 112:
keyString = "F1";
break;
case 113:
keyString = "F2";
break;
case 114:
keyString = "F3";
break;
case 115:
keyString = "F4";
break;
case 116:
keyString = "F5";
break;
case 117:
keyString = "F6";
break;
case 118:
keyString = "F7";
break;
case 119:
keyString = "F8";
break;
case 120:
keyString = "F9";
break;
case 121:
keyString = "F10";
break;
case 122:
keyString = "F11";
break;
case 123:
keyString = "F12";
break;
case 124:
keyString = "F13";
break;
case 125:
keyString = "F14";
break;
case 126:
keyString = "F15";
break;
case 127:
keyString = "F16";
break;
case 128:
keyString = "F17";
break;
case 129:
keyString = "F18";
break;
case 130:
keyString = "F19";
break;
case 131:
keyString = "F20";
break;
case 132:
keyString = "F21";
break;
case 133:
keyString = "F22";
break;
case 134:
keyString = "F23";
break;
case 135:
keyString = "F24";
break;
case 144:
keyString = "Num lock";
break;
case 145:
keyString = "Scroll";
break;
case 160:
keyString = "Shift Left";
break;
case 161:
keyString = "Shift Right";
break;
case 162:
keyString = "Ctrl Left";
break;
case 163:
keyString = "Ctrl Right";
break;
case 164:
keyString = "Menu Left";
break;
case 165:
keyString = "Menu Right";
break;
default:
break;
}
return keyString;
}
private void HelmRemoveButtonClick(object sender, EventArgs e)
{
var helmBinding = (HelmBinding)HelmBindingsListBox.SelectedItem;
if (helmBinding == null)
return;
HelmBindings.Bindings.Remove(helmBinding);
HelmBindingSource.ResetBindings(false);
}
}
}