Add ability for emulator to emulate keyboard events for ring button emulation
parent
b73e88f1da
commit
48cdfd0e72
|
@ -25,6 +25,9 @@
|
|||
<setting name="UserLanguage" serializeAs="String">
|
||||
<value />
|
||||
</setting>
|
||||
<setting name="IsRingButtonEmulationEnabled" serializeAs="String">
|
||||
<value>False</value>
|
||||
</setting>
|
||||
</WpfMaiTouchEmulator.Properties.Settings>
|
||||
</userSettings>
|
||||
</configuration>
|
|
@ -3,7 +3,7 @@ using System.Windows.Controls;
|
|||
|
||||
namespace WpfMaiTouchEmulator;
|
||||
|
||||
enum TouchValue: long
|
||||
public enum TouchValue: long
|
||||
{
|
||||
A1 = 1 << 0, // 2^0
|
||||
A2 = 1 << 1, // 2^1
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d"
|
||||
Closing="MainWindow_Closing"
|
||||
Title="MainWindow" Height="360" Width="500" ResizeMode="NoResize" WindowStartupLocation="CenterScreen">
|
||||
Title="MainWindow" Height="384" Width="500" ResizeMode="NoResize" WindowStartupLocation="CenterScreen">
|
||||
<StackPanel VerticalAlignment="Top">
|
||||
<Menu Width="Auto" Height="20">
|
||||
<MenuItem Header="{Binding LbMenuCategoryHelp}" d:Header="_Help">
|
||||
|
@ -38,6 +38,7 @@
|
|||
<Label x:Name="label1" Content="{Binding LbConnectionState}" d:Content="Connection state" HorizontalAlignment="Left" Margin="238,8,0,0" VerticalAlignment="Top"/>
|
||||
<Label x:Name="connectionStateLabel" Content="{Binding LbConnectionStateNotConnected}" d:Content="Not connected" HorizontalAlignment="Left" Margin="238,31,0,0" VerticalAlignment="Top" FontSize="10"/>
|
||||
<CheckBox x:Name="exitWithSinmai" Content="{Binding LbExitWithSinmai}" d:Content="Exit with Sinmai" HorizontalAlignment="Left" Margin="10,277,0,0" VerticalAlignment="Top" Height="17" Width="224" IsChecked="{Binding IsExitWithSinmaiEnabled}" Click="exitWithSinmai_Click" ToolTip="{Binding LbExitWithSinmaiTT}"/>
|
||||
<CheckBox x:Name="emulateRingButtons" Content="{Binding LbEmulateRingButtons}" d:Content="Emulate ring buttons" HorizontalAlignment="Left" Margin="10,299,0,0" VerticalAlignment="Top" Height="17" Width="224" IsChecked="{Binding IsRingButtonEmulationEnabled}" ToolTip="{Binding LbEmulateRingButtonsTT}" Click="emulateRingButtons_Click"/>
|
||||
<Button x:Name="buttonInstallComPort" Content="{Binding LbInstallComPort}" d:Content="Install COM port" HorizontalAlignment="Left" Margin="10,9,0,0" VerticalAlignment="Top" Click="buttonInstallComPort_Click" Width="130"/>
|
||||
<Button x:Name="buttonUninstallComPorts" Content="{Binding LbUninstallComPort}" d:Content="Uninstall COM port" HorizontalAlignment="Left" Margin="10,34,0,0" VerticalAlignment="Top" Click="buttonUninstallComPorts_Click" Width="130"/>
|
||||
<Button x:Name="buttonListComPorts" Content="{Binding LbListComPorts}" d:Content="List installed COM ports" HorizontalAlignment="Left" Margin="10,59,0,0" VerticalAlignment="Top" Click="buttonListComPorts_Click" Width="130"/>
|
||||
|
|
|
@ -19,6 +19,7 @@ public partial class MainWindow : Window
|
|||
IsAutomaticPortConnectingEnabled = Properties.Settings.Default.IsAutomaticPortConnectingEnabled,
|
||||
IsAutomaticPositioningEnabled = Properties.Settings.Default.IsAutomaticPositioningEnabled,
|
||||
IsExitWithSinmaiEnabled = Properties.Settings.Default.IsExitWithSinmaiEnabled,
|
||||
IsRingButtonEmulationEnabled = Properties.Settings.Default.IsRingButtonEmulationEnabled
|
||||
};
|
||||
|
||||
Title = "Mai Touch Emulator";
|
||||
|
@ -241,4 +242,14 @@ public partial class MainWindow : Window
|
|||
{
|
||||
ShowSetupInstructionsDialog();
|
||||
}
|
||||
|
||||
private void emulateRingButtons_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var dataContext = (MainWindowViewModel)DataContext;
|
||||
var enabled = !dataContext.IsRingButtonEmulationEnabled;
|
||||
dataContext.IsRingButtonEmulationEnabled = !enabled;
|
||||
Properties.Settings.Default.IsRingButtonEmulationEnabled = dataContext.IsRingButtonEmulationEnabled;
|
||||
Properties.Settings.Default.Save();
|
||||
_touchPanel.SetEmulateRingButton(dataContext.IsRingButtonEmulationEnabled);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,6 +40,10 @@ public class MainWindowViewModel : INotifyPropertyChanged
|
|||
{
|
||||
get; set;
|
||||
}
|
||||
public string LbEmulateRingButtons
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
public string LbInstallComPort
|
||||
{
|
||||
get; set;
|
||||
|
@ -174,12 +178,18 @@ public class MainWindowViewModel : INotifyPropertyChanged
|
|||
get;
|
||||
private set;
|
||||
}
|
||||
public string? LbEmulateRingButtonsTT
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
private bool _isAutomaticPortConnectingEnabled;
|
||||
private bool _isDebugEnabled;
|
||||
private bool _isAutomaticPositioningEnabled;
|
||||
private bool _isExitWithSinmaiEnabled;
|
||||
private CultureInfo _selectedLanguage;
|
||||
private bool _isRingButtonEmulationEnabled;
|
||||
private readonly ResourceManager resourceManager;
|
||||
private readonly CultureInfo cultureInfo;
|
||||
|
||||
|
@ -248,6 +258,17 @@ public class MainWindowViewModel : INotifyPropertyChanged
|
|||
}
|
||||
}
|
||||
|
||||
public bool IsRingButtonEmulationEnabled
|
||||
{
|
||||
get => _isRingButtonEmulationEnabled;
|
||||
set
|
||||
{
|
||||
_isRingButtonEmulationEnabled = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public CultureInfo SelectedLanguage
|
||||
{
|
||||
get => _selectedLanguage;
|
||||
|
@ -282,6 +303,7 @@ public class MainWindowViewModel : INotifyPropertyChanged
|
|||
LbConnectToPort = resourceManager.GetString("lbConnectToPort");
|
||||
LbDebugMode = resourceManager.GetString("lbDebugMode");
|
||||
LbExitWithSinmai = resourceManager.GetString("lbExitWithSinmai");
|
||||
LbEmulateRingButtons = resourceManager.GetString("lbEmulateRingButtons");
|
||||
LbInstallComPort = resourceManager.GetString("lbInstallComPort");
|
||||
LbLanguageDropdown = resourceManager.GetString("lbLanguageDropdown");
|
||||
LbListComPorts = resourceManager.GetString("lbListComPorts");
|
||||
|
@ -294,6 +316,7 @@ public class MainWindowViewModel : INotifyPropertyChanged
|
|||
LbAutoPortConnectingTT = resourceManager.GetString("lbAutoPortConnectingTT");
|
||||
LbAutoSensorPositioningTT = resourceManager.GetString("lbAutoSensorPositioningTT");
|
||||
LbExitWithSinmaiTT = resourceManager.GetString("lbExitWithSinmaiTT");
|
||||
LbEmulateRingButtonsTT = resourceManager.GetString("lbEmulateRingButtonsTT");
|
||||
LbMenuCategoryHelp = resourceManager.GetString("lbMenuCategoryHelp");
|
||||
LbMenuItemSetup = resourceManager.GetString("lbMenuItemSetup");
|
||||
|
||||
|
|
|
@ -94,5 +94,17 @@ namespace WpfMaiTouchEmulator.Properties {
|
|||
this["UserLanguage"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("False")]
|
||||
public bool IsRingButtonEmulationEnabled {
|
||||
get {
|
||||
return ((bool)(this["IsRingButtonEmulationEnabled"]));
|
||||
}
|
||||
set {
|
||||
this["IsRingButtonEmulationEnabled"] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,5 +20,8 @@
|
|||
<Setting Name="UserLanguage" Type="System.String" Scope="User">
|
||||
<Value Profile="(Default)" />
|
||||
</Setting>
|
||||
<Setting Name="IsRingButtonEmulationEnabled" Type="System.Boolean" Scope="User">
|
||||
<Value Profile="(Default)">False</Value>
|
||||
</Setting>
|
||||
</Settings>
|
||||
</SettingsFile>
|
|
@ -141,6 +141,24 @@ namespace WpfMaiTouchEmulator.Resources {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Emulate ring buttons.
|
||||
/// </summary>
|
||||
internal static string lbEmulateRingButtons {
|
||||
get {
|
||||
return ResourceManager.GetString("lbEmulateRingButtons", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Useful when navigating the menus without a keyboard.
|
||||
/// </summary>
|
||||
internal static string lbEmulateRingButtonsTT {
|
||||
get {
|
||||
return ResourceManager.GetString("lbEmulateRingButtonsTT", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Exit when Sinmai exits.
|
||||
/// </summary>
|
||||
|
|
|
@ -144,6 +144,12 @@
|
|||
<data name="lbDebugMode" xml:space="preserve">
|
||||
<value>デバッグモード</value>
|
||||
</data>
|
||||
<data name="lbEmulateRingButtons" xml:space="preserve">
|
||||
<value>リングボタンをエミュレートする</value>
|
||||
</data>
|
||||
<data name="lbEmulateRingButtonsTT" xml:space="preserve">
|
||||
<value>キーボードがないときにメニュー操作に便利</value>
|
||||
</data>
|
||||
<data name="lbExitWithSinmai" xml:space="preserve">
|
||||
<value>Sinmai終了時に終了</value>
|
||||
</data>
|
||||
|
|
|
@ -144,6 +144,12 @@
|
|||
<data name="lbDebugMode" xml:space="preserve">
|
||||
<value>Debug mode</value>
|
||||
</data>
|
||||
<data name="lbEmulateRingButtons" xml:space="preserve">
|
||||
<value>Emulate ring buttons</value>
|
||||
</data>
|
||||
<data name="lbEmulateRingButtonsTT" xml:space="preserve">
|
||||
<value>Useful when navigating the menus without a keyboard</value>
|
||||
</data>
|
||||
<data name="lbExitWithSinmai" xml:space="preserve">
|
||||
<value>Exit when Sinmai exits</value>
|
||||
</data>
|
||||
|
|
|
@ -144,6 +144,12 @@
|
|||
<data name="lbDebugMode" xml:space="preserve">
|
||||
<value>调试模式</value>
|
||||
</data>
|
||||
<data name="lbEmulateRingButtons" xml:space="preserve">
|
||||
<value>模拟环形按钮</value>
|
||||
</data>
|
||||
<data name="lbEmulateRingButtonsTT" xml:space="preserve">
|
||||
<value>在没有键盘的情况下导航菜单时很有用</value>
|
||||
</data>
|
||||
<data name="lbExitWithSinmai" xml:space="preserve">
|
||||
<value>随Sinmai退出</value>
|
||||
</data>
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace WpfMaiTouchEmulator;
|
||||
public partial class RingButtonEmulator
|
||||
{
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo);
|
||||
|
||||
private static readonly IDictionary<TouchValue, byte> touchRingMapping = new Dictionary<TouchValue, byte>()
|
||||
{
|
||||
{ TouchValue.A1, 0x57 }, // W
|
||||
{ TouchValue.A2, 0x45 }, // E
|
||||
{ TouchValue.A3, 0x44 }, // D
|
||||
{ TouchValue.A4, 0x43 }, // C
|
||||
{ TouchValue.A5, 0x58 }, // X
|
||||
{ TouchValue.A6, 0x5A }, // Z
|
||||
{ TouchValue.A7, 0x41 }, // A
|
||||
{ TouchValue.A8, 0x51 }, // Q
|
||||
};
|
||||
private const uint KEYEVENTF_KEYUP = 0x0002;
|
||||
|
||||
public static bool HasRingButtonMapping(TouchValue touchValue)
|
||||
{
|
||||
return touchRingMapping.ContainsKey(touchValue);
|
||||
}
|
||||
|
||||
public static void PressButton(TouchValue touchValue)
|
||||
{
|
||||
if (touchRingMapping.TryGetValue(touchValue, out var vk))
|
||||
{
|
||||
keybd_event(vk, 0, 0, UIntPtr.Zero);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ReleaseButton(TouchValue touchValue)
|
||||
{
|
||||
if (touchRingMapping.TryGetValue(touchValue, out var vk))
|
||||
{
|
||||
keybd_event(vk, 0, KEYEVENTF_KEYUP, UIntPtr.Zero);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ReleaseAllButtons()
|
||||
{
|
||||
foreach (var vk in touchRingMapping.Values)
|
||||
{
|
||||
keybd_event(vk, 0, KEYEVENTF_KEYUP, UIntPtr.Zero);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,6 +17,7 @@ public partial class TouchPanel : Window
|
|||
private readonly TouchPanelPositionManager _positionManager;
|
||||
private List<Polygon> buttons = [];
|
||||
private bool isDebugEnabled = Properties.Settings.Default.IsDebugEnabled;
|
||||
private bool isRingButtonEmulationEnabled = Properties.Settings.Default.IsRingButtonEmulationEnabled;
|
||||
|
||||
private enum ResizeDirection
|
||||
{
|
||||
|
@ -106,7 +107,15 @@ public partial class TouchPanel : Window
|
|||
{
|
||||
// Highlight the element and add it to the active touches tracking.
|
||||
HighlightElement(element, true);
|
||||
onTouch?.Invoke((TouchValue)element.Tag);
|
||||
var touchValue = (TouchValue)element.Tag;
|
||||
if (isRingButtonEmulationEnabled && RingButtonEmulator.HasRingButtonMapping((TouchValue)element.Tag))
|
||||
{
|
||||
RingButtonEmulator.PressButton((TouchValue)element.Tag);
|
||||
}
|
||||
else
|
||||
{
|
||||
onTouch?.Invoke((TouchValue)element.Tag);
|
||||
}
|
||||
activeTouches[e.TouchDevice.Id] = element;
|
||||
}
|
||||
e.Handled = true;
|
||||
|
@ -149,6 +158,7 @@ public partial class TouchPanel : Window
|
|||
if (activeTouches.TryGetValue(e.TouchDevice.Id, out var element))
|
||||
{
|
||||
HighlightElement(element, false);
|
||||
RingButtonEmulator.ReleaseButton((TouchValue)element.Tag);
|
||||
onRelease?.Invoke((TouchValue)element.Tag);
|
||||
activeTouches.Remove(e.TouchDevice.Id);
|
||||
}
|
||||
|
@ -165,6 +175,7 @@ public partial class TouchPanel : Window
|
|||
onRelease?.Invoke((TouchValue)element.Tag);
|
||||
}
|
||||
activeTouches.Clear();
|
||||
RingButtonEmulator.ReleaseAllButtons();
|
||||
}
|
||||
|
||||
public void SetDebugMode(bool enabled)
|
||||
|
@ -176,6 +187,11 @@ public partial class TouchPanel : Window
|
|||
});
|
||||
}
|
||||
|
||||
public void SetEmulateRingButton(bool enabled)
|
||||
{
|
||||
isRingButtonEmulationEnabled = enabled;
|
||||
}
|
||||
|
||||
private void HighlightElement(Polygon element, bool highlight)
|
||||
{
|
||||
if (isDebugEnabled)
|
||||
|
|
Loading…
Reference in New Issue