如何调整 Cheet.NET 以绑定到我的 C# 窗体?
How can I adapt Cheet.NET to bind to my C# Form?
所以我在设置键绑定以在我的项目中执行某些操作时遇到了问题(右 Alt + 左 Control)
而且我尝试使用一个名为 Cheet.NET 的 API,它说它可以轻松调整项目并允许制作可以调用函数的自定义 "konami" 代码。
Cheet.NET 的(小)文档:http://jamiehumphries.github.io/Cheet.NET/
所以我在 Visual Studio 中使用 NuGet 包管理器安装它,保存并重新加载我的项目。
回来了,试着写一个简单的键绑定,我已经从初始化代码中得到了很多错误:
// Initialization
var cheet = new Cheet();
myUIElement.PreviewKeyDown += cheet.OnKeyDown;
cheet.Map("↑ ↑ ↓ ↓", () => { Debug.WriteLine("Voilà!"); } );
这是我放置代码的地方:
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
// Initialization
var cheet = new Cheet();
myUIElement.PreviewKeyDown += cheet.OnKeyDown;
cheet.Map("↑ ↑ ↓ ↓", () => { Debug.WriteLine("Voilà!"); });
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
}
}
很多代码都无法识别,还给我很多计算错误:
Invalid token '+=' in class, struct, or interface member declaration
type expected
Tuple must contain atleast Two Elements
Invalid token '"↑ ↑ ↓ ↓"' in class, struct, or interface member declaration
我听说我应该 "bind" 我的项目的包,但我不知道该怎么做。
感谢任何未来的帮助。
更新(因为您已将错误输出添加到问题中):
Invalid token '+=' in class, struct, or interface member declaration
type expected
您不能只将 C# 代码放在 class 的顶层,您必须遵循一个最小结构。您可以将此类代码放在 class 的构造函数方法或其他方法或某些静态初始化块中(如果您只在代码中引用静态内容)
下次更新(更新错误后):
Using the generic type 'Cheet' requires 1 type arguments
您使用的是通用包,而不是他们使用的 Wpf 包:
public class Cheet : Cheet<Key>, ICheet
很不幸,我认为他们使用相同的 class 名称
所以需要一个不同的 using 来引用这个 class(查看它的命名空间,它是 CheetNET.Wpf):
https://github.com/jamiehumphries/Cheet.NET/blob/master/Cheet.Wpf/Cheet.cs and not the CheetNET Core one from https://github.com/jamiehumphries/Cheet.NET/blob/master/Cheet.Core/Cheet.cs 您似乎正在使用
更多信息:
Cheet class 版本中 WPF 的唯一 WPF 内容似乎是 System.Windows.Input。可能只是将它与 WinForms/WPF 互操作一起使用(请参阅 https://www.codeproject.com/Articles/37360/WinForms-WPF-Interop), but I'd consider writing a similar class to the WPF one for WinForms. See In Winforms, PreviewKeyDown() never fired for ANY key 了解如何为 WinForms
启用和执行密钥预览
旧回复:
如果您刚刚在解决方案中安装了包(我认为控制台中有一个下拉菜单可以选择目标),请确保您还右键单击 Visual Studio 中的项目并管理其 Nuget 包.
也可以右键单击 Solution/Source 资源管理器窗格中的 solution/top 节点,并从 Nuget 包管理 window select 特定安装包的项目可用。
请注意,online/available 有一个单独的选项卡,在管理器中安装和更新。
总之,新手不用控制台,直接用UI,简单易用
存储库中有一个 WPF 演示应用程序,它让您在 Window 构造函数中进行初始化:
public MainWindow()
{
var cheet = new Cheet();
PreviewKeyDown += cheet.OnKeyDown;
cheet.Map("↑ ↑ ↓ ↓ ← → ← → b a", () => { WriteLine("Voilà!"); });
cheet.Map("i d d q d", () => {
WriteLine("god mode enabled");
});
[etc.]
因此您使用 cheet.OnKeyDown
处理 PreviewKeyDown
事件,并且大概在 OnKeyDown
中 Cheet 将遍历其映射并寻找适合的映射。
我设置了一个测试 WinForms 项目并添加了 Cheet.NET,如果您想将它与 WinForms 一起使用,看来您还有一些工作要做。
Cheet.Core
有一个 Cheet<T>
class,但它是抽象的。看起来 T
应该是 "key" 类型。 Cheet.Wpf 库有一个 Cheet
class 继承自 Cheet<Key>
,使用 WPF Key
类型。
看来您需要创建自己的 Cheet
class 继承(最有可能)自 Cheet<System.Windows.Forms.Keys>
。
我想此时的问题是哪个工作量更大:为 WinForms 实施 Cheet,还是在 WPF 中重新开始您的项目。
在最简单的情况下,您几乎可以 copy/paste 来自 github 的 Wpf 实现,并更改为对 windows 形式使用正确的 eventhandlers/enums:
using CheetNET.Core;
using System;
using System.Text.RegularExpressions;
using System.Windows.Forms;
public class Cheet : Cheet<System.Windows.Forms.Keys>
{
private static readonly Regex LetterKeysNamePattern = new Regex(@"^[a-z]$");
private static readonly Regex NumberKeysNamePattern = new Regex(@"^[0-9]$");
private static readonly Regex KeyspadNumberKeysNamePattern = new Regex(@"^kp_[0-9]$");
private static readonly Regex FunctionKeysNamePattern = new Regex(@"^(?:f[1-9]|f1[0-2])$");
private PreviewKeyDownEventArgs lastHandledEvent;
public virtual void OnKeyDown(object sender, PreviewKeyDownEventArgs e)
{
if (e == lastHandledEvent)
{
return;
}
OnKeyDown(e.KeyCode);
lastHandledEvent = e;
}
protected override Keys GetKey(string KeysName)
{
if (LetterKeysNamePattern.IsMatch(KeysName))
{
return ParseKey(KeysName.ToUpper());
}
if (NumberKeysNamePattern.IsMatch(KeysName))
{
return ParseKey("D" + KeysName);
}
if (KeyspadNumberKeysNamePattern.IsMatch(KeysName))
{
return ParseKey(KeysName.Replace("kp_", "NumPad"));
}
if (FunctionKeysNamePattern.IsMatch(KeysName))
{
return ParseKey(KeysName.ToUpper());
}
switch (KeysName)
{
case "left":
case "L":
case "←":
return Keys.Left;
case "up":
case "U":
case "↑":
return Keys.Up;
case "right":
case "R":
case "→":
return Keys.Right;
case "down":
case "D":
case "↓":
return Keys.Down;
case "backspace":
return Keys.Back;
case "tab":
return Keys.Tab;
case "enter":
return Keys.Enter;
case "return":
return Keys.Return;
case "shift":
case "⇧":
return Keys.LShiftKey;
case "control":
case "ctrl":
case "^":
return Keys.LControlKey;
case "alt":
case "option":
case "⌥":
return Keys.Alt;
case "command":
case "⌘":
return Keys.LWin;
case "pause":
return Keys.Pause;
case "capslock":
return Keys.CapsLock;
case "esc":
return Keys.Escape;
case "space":
return Keys.Space;
case "pageup":
return Keys.PageUp;
case "pagedown":
return Keys.PageDown;
case "end":
return Keys.End;
case "home":
return Keys.Home;
case "insert":
return Keys.Insert;
case "delete":
return Keys.Delete;
case "equal":
case "=":
return Keys.Oemplus;
case "comma":
case ",":
return Keys.Oemcomma;
case "minus":
case "-":
return Keys.OemMinus;
case "period":
case ".":
return Keys.OemPeriod;
case "kp_multiply":
return Keys.Multiply;
case "kp_plus":
return Keys.Add;
case "kp_minus":
return Keys.Subtract;
case "kp_decimal":
return Keys.Decimal;
case "kp_divide":
return Keys.Divide;
}
throw new ArgumentException(String.Format("Could not map Keys named '{0}'.", KeysName));
}
private static Keys ParseKey(string KeysName)
{
return (Keys)Enum.Parse(typeof(Keys), KeysName);
}
}
然后,只要将代码放入表单加载处理程序中,它就会按预期工作:
protected override void OnLoad(EventArgs e)
{
var cheet = new Cheet();
PreviewKeyDown += cheet.OnKeyDown;
cheet.Map("c h e a t", () => { MessageBox.Show("Voilà!"); });
base.OnLoad(e);
}
所以我在设置键绑定以在我的项目中执行某些操作时遇到了问题(右 Alt + 左 Control)
而且我尝试使用一个名为 Cheet.NET 的 API,它说它可以轻松调整项目并允许制作可以调用函数的自定义 "konami" 代码。
Cheet.NET 的(小)文档:http://jamiehumphries.github.io/Cheet.NET/
所以我在 Visual Studio 中使用 NuGet 包管理器安装它,保存并重新加载我的项目。
回来了,试着写一个简单的键绑定,我已经从初始化代码中得到了很多错误:
// Initialization
var cheet = new Cheet();
myUIElement.PreviewKeyDown += cheet.OnKeyDown;
cheet.Map("↑ ↑ ↓ ↓", () => { Debug.WriteLine("Voilà!"); } );
这是我放置代码的地方:
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
// Initialization
var cheet = new Cheet();
myUIElement.PreviewKeyDown += cheet.OnKeyDown;
cheet.Map("↑ ↑ ↓ ↓", () => { Debug.WriteLine("Voilà!"); });
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
}
}
很多代码都无法识别,还给我很多计算错误:
Invalid token '+=' in class, struct, or interface member declaration
type expected
Tuple must contain atleast Two Elements
Invalid token '"↑ ↑ ↓ ↓"' in class, struct, or interface member declaration
我听说我应该 "bind" 我的项目的包,但我不知道该怎么做。
感谢任何未来的帮助。
更新(因为您已将错误输出添加到问题中):
Invalid token '+=' in class, struct, or interface member declaration type expected
您不能只将 C# 代码放在 class 的顶层,您必须遵循一个最小结构。您可以将此类代码放在 class 的构造函数方法或其他方法或某些静态初始化块中(如果您只在代码中引用静态内容)
下次更新(更新错误后):
Using the generic type 'Cheet' requires 1 type arguments
您使用的是通用包,而不是他们使用的 Wpf 包:
public class Cheet : Cheet<Key>, ICheet
很不幸,我认为他们使用相同的 class 名称
所以需要一个不同的 using 来引用这个 class(查看它的命名空间,它是 CheetNET.Wpf): https://github.com/jamiehumphries/Cheet.NET/blob/master/Cheet.Wpf/Cheet.cs and not the CheetNET Core one from https://github.com/jamiehumphries/Cheet.NET/blob/master/Cheet.Core/Cheet.cs 您似乎正在使用
更多信息:
Cheet class 版本中 WPF 的唯一 WPF 内容似乎是 System.Windows.Input。可能只是将它与 WinForms/WPF 互操作一起使用(请参阅 https://www.codeproject.com/Articles/37360/WinForms-WPF-Interop), but I'd consider writing a similar class to the WPF one for WinForms. See In Winforms, PreviewKeyDown() never fired for ANY key 了解如何为 WinForms
启用和执行密钥预览旧回复:
如果您刚刚在解决方案中安装了包(我认为控制台中有一个下拉菜单可以选择目标),请确保您还右键单击 Visual Studio 中的项目并管理其 Nuget 包.
也可以右键单击 Solution/Source 资源管理器窗格中的 solution/top 节点,并从 Nuget 包管理 window select 特定安装包的项目可用。
请注意,online/available 有一个单独的选项卡,在管理器中安装和更新。
总之,新手不用控制台,直接用UI,简单易用
存储库中有一个 WPF 演示应用程序,它让您在 Window 构造函数中进行初始化:
public MainWindow()
{
var cheet = new Cheet();
PreviewKeyDown += cheet.OnKeyDown;
cheet.Map("↑ ↑ ↓ ↓ ← → ← → b a", () => { WriteLine("Voilà!"); });
cheet.Map("i d d q d", () => {
WriteLine("god mode enabled");
});
[etc.]
因此您使用 cheet.OnKeyDown
处理 PreviewKeyDown
事件,并且大概在 OnKeyDown
中 Cheet 将遍历其映射并寻找适合的映射。
我设置了一个测试 WinForms 项目并添加了 Cheet.NET,如果您想将它与 WinForms 一起使用,看来您还有一些工作要做。
Cheet.Core
有一个 Cheet<T>
class,但它是抽象的。看起来 T
应该是 "key" 类型。 Cheet.Wpf 库有一个 Cheet
class 继承自 Cheet<Key>
,使用 WPF Key
类型。
看来您需要创建自己的 Cheet
class 继承(最有可能)自 Cheet<System.Windows.Forms.Keys>
。
我想此时的问题是哪个工作量更大:为 WinForms 实施 Cheet,还是在 WPF 中重新开始您的项目。
在最简单的情况下,您几乎可以 copy/paste 来自 github 的 Wpf 实现,并更改为对 windows 形式使用正确的 eventhandlers/enums:
using CheetNET.Core;
using System;
using System.Text.RegularExpressions;
using System.Windows.Forms;
public class Cheet : Cheet<System.Windows.Forms.Keys>
{
private static readonly Regex LetterKeysNamePattern = new Regex(@"^[a-z]$");
private static readonly Regex NumberKeysNamePattern = new Regex(@"^[0-9]$");
private static readonly Regex KeyspadNumberKeysNamePattern = new Regex(@"^kp_[0-9]$");
private static readonly Regex FunctionKeysNamePattern = new Regex(@"^(?:f[1-9]|f1[0-2])$");
private PreviewKeyDownEventArgs lastHandledEvent;
public virtual void OnKeyDown(object sender, PreviewKeyDownEventArgs e)
{
if (e == lastHandledEvent)
{
return;
}
OnKeyDown(e.KeyCode);
lastHandledEvent = e;
}
protected override Keys GetKey(string KeysName)
{
if (LetterKeysNamePattern.IsMatch(KeysName))
{
return ParseKey(KeysName.ToUpper());
}
if (NumberKeysNamePattern.IsMatch(KeysName))
{
return ParseKey("D" + KeysName);
}
if (KeyspadNumberKeysNamePattern.IsMatch(KeysName))
{
return ParseKey(KeysName.Replace("kp_", "NumPad"));
}
if (FunctionKeysNamePattern.IsMatch(KeysName))
{
return ParseKey(KeysName.ToUpper());
}
switch (KeysName)
{
case "left":
case "L":
case "←":
return Keys.Left;
case "up":
case "U":
case "↑":
return Keys.Up;
case "right":
case "R":
case "→":
return Keys.Right;
case "down":
case "D":
case "↓":
return Keys.Down;
case "backspace":
return Keys.Back;
case "tab":
return Keys.Tab;
case "enter":
return Keys.Enter;
case "return":
return Keys.Return;
case "shift":
case "⇧":
return Keys.LShiftKey;
case "control":
case "ctrl":
case "^":
return Keys.LControlKey;
case "alt":
case "option":
case "⌥":
return Keys.Alt;
case "command":
case "⌘":
return Keys.LWin;
case "pause":
return Keys.Pause;
case "capslock":
return Keys.CapsLock;
case "esc":
return Keys.Escape;
case "space":
return Keys.Space;
case "pageup":
return Keys.PageUp;
case "pagedown":
return Keys.PageDown;
case "end":
return Keys.End;
case "home":
return Keys.Home;
case "insert":
return Keys.Insert;
case "delete":
return Keys.Delete;
case "equal":
case "=":
return Keys.Oemplus;
case "comma":
case ",":
return Keys.Oemcomma;
case "minus":
case "-":
return Keys.OemMinus;
case "period":
case ".":
return Keys.OemPeriod;
case "kp_multiply":
return Keys.Multiply;
case "kp_plus":
return Keys.Add;
case "kp_minus":
return Keys.Subtract;
case "kp_decimal":
return Keys.Decimal;
case "kp_divide":
return Keys.Divide;
}
throw new ArgumentException(String.Format("Could not map Keys named '{0}'.", KeysName));
}
private static Keys ParseKey(string KeysName)
{
return (Keys)Enum.Parse(typeof(Keys), KeysName);
}
}
然后,只要将代码放入表单加载处理程序中,它就会按预期工作:
protected override void OnLoad(EventArgs e)
{
var cheet = new Cheet();
PreviewKeyDown += cheet.OnKeyDown;
cheet.Map("c h e a t", () => { MessageBox.Show("Voilà!"); });
base.OnLoad(e);
}