整个程序太复杂,无法在此处显示.基本上,只需注意我最近的git提交中的绿色亮点.我对DirectInput很新,所以我希望我犯了几个错误.我已经非常仔细地研究了MSDN文档,所以我保证我不会把它扔到那里并在它上面加上FIX IT FOR ME.:)
基本上,我认为我已经将我的问题缩小到了围绕Engine :: getEvent(第238行)的代码区域.我不明白这些功能是如何工作的,而且我已经弄乱了某些部分来实现不同的结果.我的目标是直接读取键盘事件并将这些原始数字输出到屏幕上(稍后我将处理数字的含义).这里的问题与KEYBOARD_BUFFER_SIZE有关.如果我把它变小,程序似乎运行正常,但它不输出任何事件.如果我把它变大,它运行得更好,但它开始变慢然后冻结(OpenGL窗口只有一个旋转的彩色立方体).如何正确捕获键盘事件?
我检查了代码中更高的所有设置步骤的返回值.他们都返回DI_OK就好了.
如何使用DirectInput模拟按键?我目前有初始化(但我不确定它是否好):
#include <dinput.h>
#pragma comment (lib, "dinput8.lib")
#pragma comment (lib, "dxguid.lib")
LPDIRECTINPUT8 din; // the pointer to our DirectInput interface
LPDIRECTINPUTDEVICE8 dinkeyboard; // the pointer to the keyboard device
BYTE keystate[256]; // the storage for the key-information
void initDInput(HINSTANCE hInstance, HWND hWnd); // sets up and initializes DirectInput
void detect_input(void); // gets the current input state
void cleanDInput(void); // closes DirectInput and releases memory
Run Code Online (Sandbox Code Playgroud)
那么有人可以告诉我如何模拟例如在游戏中按下左箭头键吗?
有时(大约50%的运行),EnumDevices需要5-10秒才能返回.通常它几乎是即时的.我找不到任何关于这种行为的其他报道.
当事情变得缓慢时,可以通过观看标准输出来进行分析:)这:
std::cout << "A";
directInput8Interface->EnumDevices(DI8DEVCLASS_GAMECTRL, MyCallback, NULL, DIEDFL_ATTACHEDONLY);
std::cout << "C";
...
BOOL CALLBACK MyCallback(LPCDIDEVICEINSTANCE, LPVOID)
{
std::cout << "B";
return DIENUM_CONTINUE;
}
Run Code Online (Sandbox Code Playgroud)
似乎通过枚举设备随机挂起 - 有时它会在回调被调用之前,有时在一对之后,有时它会在最后一次调用之后.
这显然是一个简化的代码块; 我实际上正在使用OIS输入库(http://sourceforge.net/projects/wgois/),因此对于上下文,请在此处查看完整的源代码:
然而,似乎没有任何特别的果味,但可能是他们初始化的原因可能是原因 - 我不太了解DI8发现它.
任何有关它为何如此缓慢的想法将不胜感激!
编辑:
我已设法抓住etl跟踪文件中的挂起并在Windows性能分析器中对其进行分析.看起来EnumDevices最终调用DInput8.dll!fGetProductStringFromDevice,调用HIDUSB.SYS!HumCallUSB,调用KeWaitForSingleObject和等待.10次中有9次(字面意思是 - 跟踪中有10个样本)这很快就会返回(每次324us),其中包含usbport.sys!USBPORT_Core_iCompleteDoneTransfer紧随其后的readstack HIDUSB.SYS!HumCallUsbComplete,这看起来很正常.
但是10次中的1次,这几乎需要5秒才能返回.在准备好的callstack ntkrnlmp.exe!KiTimerExpiration而不是HIDUSB.SYS函数.我想这一切都表明HIDUSB.SYS驱动程序异步查询设备的超时时间为5秒,有时它会失败并达到此超时.
我不知道这个故障是否与任何一个设备特别相关(我确实有一些USB HID)或者它是随机的 - 它很难测试,因为它并不总是发生.同样,任何人都可以给我的任何信息都会受到赞赏,但是由于DirectInput出现了奇怪的情况,我不希望微软很快解决这个问题!
也许我只需要在早期,异步地开始初始化输入,并接受有时在用户输入发生之前会有5秒的延迟.
我正在尝试使用 DirectInput 捕获 XBOX One 控制器输入信号。我将其绑定到 C# WinForms 应用程序。我遇到的问题是:当表单具有焦点时,它可以很好地捕获输入。当窗口失去焦点时,我不会得到任何反馈。在 Windows 7 上,这不是问题。
我在 Windows 10 上尝试过其他控制器:PS4、罗技、方向盘等...一切都按预期工作:当窗口失去焦点时,我仍然会收到反馈。它只是 Windows 10 上的 XBOX One 控制器。
我想这可能与这一行有关:
dev.SetCooperativeLevel(_ctlParent, CooperativeLevel.Background | CooperativeLevel.Nonexclusive);
Run Code Online (Sandbox Code Playgroud)
但是,即使我去掉那条线,一切仍然表现相同。
看起来 XBOX One 控制器会忽略该CooperativeLevel.Background标志并添加该CooperativeLevel.Foreground标志。这是有关标志的更多信息。
还有其他熟悉这个问题的人已经找到了解决方法吗?
好吧,我试图避免使用已弃用的DirectInput.
但是我需要在游戏的每个"框架"或"迭代"中抢夺所有关键状态,以便我可以采取相应的行动.例如,如果玩家在VK_RIGHT键上按下,那么他将在该帧上仅移动一个smidgen.
WM_INPUT消息的问题是它们每帧可能出现不可预测的次数,因为游戏循环的编写方式如下:
MSG message ;
while( 1 )
{
if( PeekMessage( &message, NULL, 0, 0, PM_REMOVE ) )
{
if( message.message == WM_QUIT )
{
break ; // bail when WM_QUIT
}
TranslateMessage( &message ) ;
DispatchMessage( &message ) ;
}
else
{
// No messages, so run the game.
Update() ;
Draw() ;
}
}
因此,如果堆叠了多个 WM_INPUT消息,那么它们将在Update()/ Draw()之前被处理.
我通过使用BOOL数组来解决这个问题,以记住关键是什么:
bool array_of_keys_that_are_down[ 256 ] ;
case WM_INPUT :
if( its keyboard input )
{
array_of_keys_that_are_down[ VK_CODE … 我想将从Android客户端收到的鼠标和键盘输入发送到在Windows上运行的游戏.
SendInput适用于我迄今为止工作过的几乎所有游戏.但是为了SendInput工作,游戏必须是前景窗口.
要解决我用PostMessage(hwnd,...)hwnd处理游戏窗口的问题.但是如果游戏使用DirectInput,这不起作用.这是通过挂钩解决的GetDeviceState.现在我开始工作的另一个游戏是使用WM_INPUT或原始输入,我必须创建原始输入以使其工作.
根据这篇MSDN文章
DirectInput是一组API调用,用于抽象系统上的输入设备.在内部,DirectInput创建第二个线程来读取WM_INPUT数据,并且使用DirectInput API将比直接读取WM_INPUT增加更多的开销.
directInput使用WM_INPUT工作.
的SendInput函数插入在输入结构的事件串联到键盘或鼠标输入流.这些事件不会插入用户(使用键盘或鼠标)插入的其他键盘或鼠标输入事件,也不会调用keybd_event,mouse_event或其他SendInput调用.
所以SendInput也提供抽象.
我想要的是即使它的窗口没有聚焦,也可以独立地将输入发送到应用程序.这样我就可以一次向多个游戏发送输入.有没有办法使用一个更高级别的API调用,如SendInput来实现这一目标?这可以用SendInput完成吗?那有没有C/C++库?
我使用DirectInput来处理输入设备,我枚举每个设备上的设备和元素.
在我的游戏手柄上使用模拟棒时,它们会报告0-65535范围内的值.这是始终为所有类型的绝对轴的情况下?
如果没有:有没有办法找出DX8输入元素的范围DIDEVICEOBJECTDATA :: dwData(用DIDFT_ABSAXIS枚举)?我能想到的唯一另一个选择是在我的应用程序中使用一些自制的内部校准,这听起来也是80年代的真实.