C# | SharpDX.XInput |如何检测控制器上的按钮是否被按下一次并且没有被按下
C# | SharpDX.XInput | How to detect if a button on the controller was pressed once and is not getting hold down
最近我尝试创建一个 XBOX 360 控制器驱动程序。
我需要检测按钮是否被按下或按住。因此,如果您按住它,它也会调用一次特定功能,就像您按下按钮一次一样。
这是我的代码(我在另一个 post 上找到了这个解决方案,但它对我不起作用)
using System;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
using SharpDX.XInput;
using System.Runtime.InteropServices;
namespace Windows_XBOX_Controller_Driver
{
public partial class Form1 : Form
{
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint cButtons, uint dwExtraInfo);
private static Controller controller;
private State stateNew;
private State stateOld;
private int x, y;
public Form1()
{
InitializeComponent();
Setup();
}
private void loop_Tick(object sender, EventArgs e)
{
if(!enabledcb.Checked)
{
return;
}
//
stateNew = controller.GetState();
///////////////////////////////////
x = stateNew.Gamepad.RightThumbX;
y = stateNew.Gamepad.RightThumbY;
x /= 1000;
y /= 1000;
//////////////////////////////
int movementX = x;
int movementY = y;
movementX *= (int)sensnud.Value;
movementY *= (int)sensnud.Value;
movementX /= 2;
movementY /= 2;
movementY *= -1;
////////////////////////
if (x > buffernud.Value || x < -buffernud.Value)
{
Cursor.Position = new Point(Cursor.Position.X + movementX, Cursor.Position.Y);
}
if(y > buffernud.Value || y < -buffernud.Value)
{
Cursor.Position = new Point(Cursor.Position.X, Cursor.Position.Y + movementY);
}
//buttons
CheckButtons();
}
private void CheckButtons()
{
//a left click
if (stateOld.Gamepad.Buttons == GamepadButtonFlags.LeftShoulder && stateNew.Gamepad.Buttons == GamepadButtonFlags.LeftShoulder)
{
LeftClick();
}
//b right click
if (stateOld.Gamepad.Buttons == GamepadButtonFlags.RightShoulder && stateNew.Gamepad.Buttons == GamepadButtonFlags.RightShoulder)
{
RightClick();
}
//dpad up button sens up
if (stateOld.Gamepad.Buttons == GamepadButtonFlags.DPadUp && stateNew.Gamepad.Buttons == GamepadButtonFlags.DPadUp)
{
sensnud.UpButton();
}
//dpad down button sens down
if (stateOld.Gamepad.Buttons == GamepadButtonFlags.DPadDown && stateNew.Gamepad.Buttons == GamepadButtonFlags.DPadDown)
{
sensnud.DownButton();
}
stateOld = stateNew;
}
private void LeftClick()
{
int X = Cursor.Position.X;
int Y = Cursor.Position.Y;
mouse_event(0x02 | 0x04, (uint)X, (uint)Y, 0, 0);
Thread.Sleep(100);
}
private void RightClick()
{
int X = Cursor.Position.X;
int Y = Cursor.Position.Y;
mouse_event(0x08 | 0x10, (uint)X, (uint)Y, 0, 0);
Thread.Sleep(100);
}
private void LoadController()
{
controller = new Controller(UserIndex.One);
if(!controller.IsConnected)
{
MessageBox.Show("Error", "It seems like there is no XBOX 360 Controller connected via USB!");
Application.Exit();
}
}
private void updateLoop_Tick(object sender, EventArgs e)
{
xlbl.Text = "Offset X: " + x;
ylbl.Text = "Offset Y: " + y;
}
private void applybtn_Click(object sender, EventArgs e)
{
loop.Interval = (int)updatenud.Value;
}
private void Setup()
{
LoadController();
}
}
}
使用此代码,您仍然可以按住按钮,它会垃圾点击功能或正在调用的任何内容。
我还尝试使用 'pressed' 布尔值,按下时设置为 true,未按下时设置为 false。它只在 'pressed' 为 == false 时调用。
也没用。
对于这个问题,您还有其他解决方案吗?
抱歉,如果这是一个糟糕的问题。我阅读了问题的规则和提示,并搜索了重复的内容,但除了我从中获得第一个解决方案的那个之外没有找到任何内容。
我已经想通了
愚蠢的错误:我忘记在按钮按下的 if 子句中反转第一个条件
Do you have any other solution for that problem?
Here 是 class 我前几天为另一个引擎写的。但我认为它同样适用于任何其他引擎。希望对您有所帮助:
基本上,它会检查当前帧中的键是否持有,而在最后一帧中是否未持有。它们的关键状态存储在字典中
这是重要的部分:
public bool IsKeyPress(Keys key)
{
bool isCurrentlyPressed = WaveServices.Input.KeyboardState.IsKeyPressed(key);
bool previouslyReleased = this.previousKeyStates[key] == ButtonState.Release;
this.previousKeyStates[key] = isCurrentlyPressed ? ButtonState.Pressed : ButtonState.Release;
return isCurrentlyPressed && previouslyReleased;
}
最近我尝试创建一个 XBOX 360 控制器驱动程序。 我需要检测按钮是否被按下或按住。因此,如果您按住它,它也会调用一次特定功能,就像您按下按钮一次一样。 这是我的代码(我在另一个 post 上找到了这个解决方案,但它对我不起作用)
using System;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
using SharpDX.XInput;
using System.Runtime.InteropServices;
namespace Windows_XBOX_Controller_Driver
{
public partial class Form1 : Form
{
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint cButtons, uint dwExtraInfo);
private static Controller controller;
private State stateNew;
private State stateOld;
private int x, y;
public Form1()
{
InitializeComponent();
Setup();
}
private void loop_Tick(object sender, EventArgs e)
{
if(!enabledcb.Checked)
{
return;
}
//
stateNew = controller.GetState();
///////////////////////////////////
x = stateNew.Gamepad.RightThumbX;
y = stateNew.Gamepad.RightThumbY;
x /= 1000;
y /= 1000;
//////////////////////////////
int movementX = x;
int movementY = y;
movementX *= (int)sensnud.Value;
movementY *= (int)sensnud.Value;
movementX /= 2;
movementY /= 2;
movementY *= -1;
////////////////////////
if (x > buffernud.Value || x < -buffernud.Value)
{
Cursor.Position = new Point(Cursor.Position.X + movementX, Cursor.Position.Y);
}
if(y > buffernud.Value || y < -buffernud.Value)
{
Cursor.Position = new Point(Cursor.Position.X, Cursor.Position.Y + movementY);
}
//buttons
CheckButtons();
}
private void CheckButtons()
{
//a left click
if (stateOld.Gamepad.Buttons == GamepadButtonFlags.LeftShoulder && stateNew.Gamepad.Buttons == GamepadButtonFlags.LeftShoulder)
{
LeftClick();
}
//b right click
if (stateOld.Gamepad.Buttons == GamepadButtonFlags.RightShoulder && stateNew.Gamepad.Buttons == GamepadButtonFlags.RightShoulder)
{
RightClick();
}
//dpad up button sens up
if (stateOld.Gamepad.Buttons == GamepadButtonFlags.DPadUp && stateNew.Gamepad.Buttons == GamepadButtonFlags.DPadUp)
{
sensnud.UpButton();
}
//dpad down button sens down
if (stateOld.Gamepad.Buttons == GamepadButtonFlags.DPadDown && stateNew.Gamepad.Buttons == GamepadButtonFlags.DPadDown)
{
sensnud.DownButton();
}
stateOld = stateNew;
}
private void LeftClick()
{
int X = Cursor.Position.X;
int Y = Cursor.Position.Y;
mouse_event(0x02 | 0x04, (uint)X, (uint)Y, 0, 0);
Thread.Sleep(100);
}
private void RightClick()
{
int X = Cursor.Position.X;
int Y = Cursor.Position.Y;
mouse_event(0x08 | 0x10, (uint)X, (uint)Y, 0, 0);
Thread.Sleep(100);
}
private void LoadController()
{
controller = new Controller(UserIndex.One);
if(!controller.IsConnected)
{
MessageBox.Show("Error", "It seems like there is no XBOX 360 Controller connected via USB!");
Application.Exit();
}
}
private void updateLoop_Tick(object sender, EventArgs e)
{
xlbl.Text = "Offset X: " + x;
ylbl.Text = "Offset Y: " + y;
}
private void applybtn_Click(object sender, EventArgs e)
{
loop.Interval = (int)updatenud.Value;
}
private void Setup()
{
LoadController();
}
}
}
使用此代码,您仍然可以按住按钮,它会垃圾点击功能或正在调用的任何内容。
我还尝试使用 'pressed' 布尔值,按下时设置为 true,未按下时设置为 false。它只在 'pressed' 为 == false 时调用。
也没用。
对于这个问题,您还有其他解决方案吗?
抱歉,如果这是一个糟糕的问题。我阅读了问题的规则和提示,并搜索了重复的内容,但除了我从中获得第一个解决方案的那个之外没有找到任何内容。
我已经想通了 愚蠢的错误:我忘记在按钮按下的 if 子句中反转第一个条件
Do you have any other solution for that problem?
Here 是 class 我前几天为另一个引擎写的。但我认为它同样适用于任何其他引擎。希望对您有所帮助:
基本上,它会检查当前帧中的键是否持有,而在最后一帧中是否未持有。它们的关键状态存储在字典中
这是重要的部分:
public bool IsKeyPress(Keys key)
{
bool isCurrentlyPressed = WaveServices.Input.KeyboardState.IsKeyPressed(key);
bool previouslyReleased = this.previousKeyStates[key] == ButtonState.Release;
this.previousKeyStates[key] = isCurrentlyPressed ? ButtonState.Pressed : ButtonState.Release;
return isCurrentlyPressed && previouslyReleased;
}