WingMan

Subversion Repositories:
Compare Path: Rev
With Path: Rev
?path1? @ 9  →  ?path2? @ 10
/trunk/WingMan/MouseKey/KeySimulator.cs
@@ -0,0 +1,122 @@
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using MQTTnet;
using SimWinInput;
using WingMan.Communication;
 
namespace WingMan.MouseKey
{
public class KeySimulator : IDisposable
{
public delegate void MouseKeyBindingExecuting(object sender, KeyBindingExecutingEventArgs args);
 
public KeySimulator(LocalKeyBindings localLocalKeyBindings, MqttCommunication mqttCommunication,
TaskScheduler formTaskScheduler, CancellationToken cancellationToken)
{
LocalLocalKeyBindings = localLocalKeyBindings;
MqttCommunication = mqttCommunication;
TaskScheduler = formTaskScheduler;
CancellationToken = cancellationToken;
 
MqttCommunication.OnMessageReceived += OnMqttMessageReceived;
}
 
private MqttCommunication MqttCommunication { get; }
private TaskScheduler TaskScheduler { get; }
private CancellationToken CancellationToken { get; }
private LocalKeyBindings LocalLocalKeyBindings { get; }
 
public void Dispose()
{
MqttCommunication.OnMessageReceived -= OnMqttMessageReceived;
}
 
public event MouseKeyBindingExecuting OnMouseKeyBindingExecuting;
 
private async void OnMqttMessageReceived(object sender, MqttApplicationMessageReceivedEventArgs e)
{
if (e.ApplicationMessage.Topic != "execute")
return;
 
using (var memoryStream = new MemoryStream(e.ApplicationMessage.Payload))
{
var executeMouseKeyBinding =
(ExecuteKeyBinding) ExecuteKeyBinding.XmlSerializer.Deserialize(memoryStream);
 
// Do not process own mouse key bindings.
if (!string.Equals(executeMouseKeyBinding.Nick, MqttCommunication.Nick, StringComparison.Ordinal))
return;
 
await Task.Delay(0, CancellationToken)
.ContinueWith(
_ => OnMouseKeyBindingExecuting?.Invoke(sender,
new KeyBindingExecutingEventArgs(executeMouseKeyBinding.Nick,
executeMouseKeyBinding.Name)),
CancellationToken,
TaskContinuationOptions.None, TaskScheduler);
 
Simulate(executeMouseKeyBinding);
}
}
 
private void Simulate(ExecuteKeyBinding executeBinding)
{
foreach (var localBinding in LocalLocalKeyBindings.Bindings)
{
if (!string.Equals(localBinding.Name, executeBinding.Name, StringComparison.Ordinal))
continue;
 
// Press
foreach (var key in localBinding.Keys)
{
if (KeyConversion.StringToKeys.TryGetValue(key, out var pressKey))
{
SimKeyboard.KeyDown(pressKey);
continue;
}
 
if (KeyConversion.StringToMouseButtons.TryGetValue(key, out var pressMouse))
switch (pressMouse)
{
case MouseButtons.Left:
SimMouse.Act(SimMouse.Action.LeftButtonDown, Cursor.Position.X, Cursor.Position.Y);
break;
case MouseButtons.Middle:
SimMouse.Act(SimMouse.Action.MiddleButtonDown, Cursor.Position.X, Cursor.Position.Y);
break;
case MouseButtons.Right:
SimMouse.Act(SimMouse.Action.RightButtonDown, Cursor.Position.X, Cursor.Position.Y);
break;
}
}
 
// Depress
foreach (var key in localBinding.Keys)
{
if (KeyConversion.StringToKeys.TryGetValue(key, out var pressKey))
{
SimKeyboard.KeyUp(pressKey);
continue;
}
 
if (KeyConversion.StringToMouseButtons.TryGetValue(key, out var pressMouse))
switch (pressMouse)
{
case MouseButtons.Left:
SimMouse.Act(SimMouse.Action.LeftButtonUp, Cursor.Position.X, Cursor.Position.Y);
break;
case MouseButtons.Middle:
SimMouse.Act(SimMouse.Action.MiddleButtonUp, Cursor.Position.X, Cursor.Position.Y);
break;
case MouseButtons.Right:
SimMouse.Act(SimMouse.Action.RightButtonUp, Cursor.Position.X, Cursor.Position.Y);
break;
}
}
}
}
}
}