当有2个键盘的时候,怎么区别不同键盘的按键命令

时间:2023-02-20 00:01:17
用C#的钩子类,可以获取键盘事件,但是现在我有2个USB键盘的,更要命的,是需要区分这2个键盘的输入,
google好几个小时了,还是没有结果,不知道有没有作过相关的东西,
指点小菜我一下。。

34 个解决方案

#1


么做过,关注一下

#2


API截取键盘命令的时候,能再区分这个命令的来源吗?

#3


顶一下

#4


BlockInput

#5


哟 ,很新鲜但很现实,不过不好办吧。

#6


看看能不能区分是来自哪个USB口的。

#7


这个比较困难哦

#8


难道从都USB设备获取开始?
而且键盘数据还拿不到的,USB键盘的数据不能通过报文共享的方式获取

#9


去C++那里问吧。要不写个驱动?

#10


那成驱动级别了,那还有什么不能实现的,那就不是都键盘事件了,是获取USB的原始数据了。。
我现在没有搞明白怎么通过API方式获取USB键盘的报文,WINIO也不行,
已经被处理成键盘事件的命令了,我还要设备做什么,就是因为键盘命令中不带设备区分

#11


比较棘手的现实问题,顶起来

#12


上班开始,UP下。。等待高手的指点

#13


up

#14


UP

#15


这个可以用C++做。。

#16


引用 9 楼 liyoubaidu 的回复:
去C++那里问吧。要不写个驱动?



友情up

#17


用WMI取出硬件媒体对象遍历,取其编号属性试试

#18


关注下

#19


C++比较初级的方法也就是调用API,建立连接后去BULK管道读取数据,调用IRP_MJ_READ和IRP_MJ_WRITE,最后不还是调用readfile来处理的。。如果只是建立连接C++才能写的话,HID是自动识别建立的,问题是这个数据怎么拿?

#20


不好判断。

#21


极度关注本帖!

#22


UP

#23


不会,我感觉这时候应该用分时系统。。

#24


给他不同的时间片吧。这个和系统就有关了呵呵,,,,

#25


UP

#26


关注!!

#27


顶一下

#28


UP

#29


该回复于2009-09-16 09:53:40被版主删除

#30


同前面讲键盘编程的过程一样,我们还是先从 DIRECTINPUT 的初始化开始吧:
  #include <dinput.h>

  #define DINPUT_BUFFERSIZE 16

  LPDIRECTINPUT lpDirectInput; // DirectInput object
  LPDIRECTINPUTDEVICE lpMouse; // DirectInput device

  BOOL InitDInput(HWND hWnd)
  { 
    HRESULT hr;

    // 创建一个 DIRECTINPUT 对象
    hr = DirectInputCreate(hInstanceCopy, DIRECTINPUT_VERSION, &lpDirectInput, NULL);

    if FAILED(hr)
    {
     // 失败
     return FALSE;
    }

    // 创建一个 DIRECTINPUTDEVICE 界面
    hr = lpDirectInput->CreateDevice(GUID_SysMouse, &lpMouse, NULL);
    if FAILED(hr)
    {
     // 失败
     return FALSE;
    }

    // 设定查询鼠标状态的返回数据格式
    hr = lpMouse->SetDataFormat(&c_dfDIMouse); 
    if FAILED(hr) 
    { 
     // 失败
     return FALSE;
    }

    // 设定协作模式
    hr = lpMouse->SetCooperativeLevel(hWnd,
       DISCL_EXCLUSIVE | DISCL_FOREGROUND);
    if FAILED(hr) 
    {
     // 失败
     return FALSE;
    }

    // 设定缓冲区大小
    // 如果不设定,缓冲区大小默认值为 0,程序就只能按立即模式工作
    // 如果要用缓冲模式工作,必须使缓冲区大小超过 0
    DIPROPDWORD property;

    property.diph.dwSize = sizeof(DIPROPDWORD);
    property.diph.dwHeaderSize = sizeof(DIPROPHEADER);
    property.diph.dwObj = 0;
    property.diph.dwHow = DIPH_DEVICE;
    property.dwData = DINPUT_BUFFERSIZE;

    hr = lpMouse->SetProperty(DIPROP_BUFFERSIZE, &property.diph);

    if FAILED(hr)
    {
     // 失败
     return FALSE;
    }

    hr = lpMouse->Acquire(); 
    if FAILED(hr)
    {
     // 失败
     return FALSE;
    }

  return TRUE;
  } 
  除了少数几处改动以外,这段代码同前面讲的键盘编程的代码基本上完全一样。
  注意调用 CreateDevice 来建立一个 DIRECTINPUTDEVICE 界面时,我们用的参数是 GUID_SysMouse 而不是 G
UID_SysKeyboard,我们以此来指明了建立的是鼠标对象。相应的,在用 SetDataFormat 来设定返回数据的格式时
,我们用的参数是 &c_dfDIMouse 而不是 &c_dfDIKeyboard。
  还有要特别注意的是,前面讲到的键盘,在设置协作方式时,是只能按非独占方式工作的,而鼠标即可以按非
独占方式工作,也可以按独占方式工作。

2、DIRECTINPUT 的数据查询
  在作 DIRECTINPUT 的鼠标数据查询时, 我一般都是使用的缓冲模式而不是立即模式。原因很简单,因为鼠标
移动事件的频率很高, 按立即模式去处理就很难保证不丢失数据。至于 DIRECTX SDK 里的例程使用立即模式读取
数据则是因为它们用了一个多媒体计时器来保证以每秒三十次的频率处理接受鼠标数据。
  明白这一点后, 下面我们就来看看相应的代码。由于 DIRECTX SDK 里的例程有立即模式的代码,我就偷点懒
,下面只给出了一段缓冲模式下的代码:
  HRESULT UpdateInputState(void)
  {
    DWORD i;

    if(lpMouse != NULL) 
    {
     DIDEVICEOBJECTDATA didod; // Receives buffered data
     DWORD dwElements;
     HRESULT hr;

     while(TRUE)
     {
      dwElements = 1; // 每次从缓冲区中读一个数据
      hr = lpMouse->GetDeviceData(sizeof(DIDEVICEOBJECTDATA),&didod,&dwElements,0);

      if FAILED(hr)
      {
       // 发生了一个错误
       if(hr == DIERR_INPUTLOST)
       {
        hr = lpMouse->Acquire(); // 试图重新取回设备
        if FAILED(hr)
        {
         return S_FALSE; // 失败
        }
       }
      }
      else
      if(elements == 1)
      {
       switch(didod.dwOfs)
       {
        case DIMOFS_X: // X 轴偏移量
                // didod.dwData 里是具体偏移相对值,单位为像素
          break;
        case DIMOFS_Y: // Y 轴偏移量
                // didod.dwData 里是具体偏移相对值,单位为像素
          break;
        case DIMOFS_BUTTON0: // 0 号键(左键)状态 
                   // didod.dwData 里是具体状态值
                   // 低字节最高位为 1 则表示按下
                   // 低字节最高位为 0 表示未按下
          break;
        case DIMOFS_BUTTON1: // 1 号键(右键)状态 
                   // 同上
          break;
        case DIMOFS_BUTTON2: // 2 号键(中键)状态 
                   // 同上
          break;
        case DIMOFS_BUTTON3: // 3 号键状态 
                   // 同上
          break;
       }
      }
      else if (elements == 0) break; // 缓冲区读空
     }
   }

  return S_OK;
  }
  这段代码注释得非常详细,相信你很快就能看懂。

3、DIRECTINPUT 的结束处理
  还记得当程序结束时必须要进行的释放处理吧,其代码如下:
  void ReleaseDInput(void) 
  { 
   if (lpDirectInput) 
   { 
    if(lpMouse) 
    { 
     // Always unacquire the device before calling Release(). 
     lpMouse->Unacquire(); 
     lpMouse->Release();
     lpMouse = NULL; 
    }
    lpDirectInput->Release();
    lpDirectInput = NULL; 
   } 
  } 
以上是C++的一种获取方式,我对C++不了解,有没有了解的人,给我通俗的解释下

#31


DirectInput 说是也可以获取USB数据的,但我不知道怎么用

#32


UP

#33


关注本贴!UP

#34


还没解决

#1


么做过,关注一下

#2


API截取键盘命令的时候,能再区分这个命令的来源吗?

#3


顶一下

#4


BlockInput

#5


哟 ,很新鲜但很现实,不过不好办吧。

#6


看看能不能区分是来自哪个USB口的。

#7


这个比较困难哦

#8


难道从都USB设备获取开始?
而且键盘数据还拿不到的,USB键盘的数据不能通过报文共享的方式获取

#9


去C++那里问吧。要不写个驱动?

#10


那成驱动级别了,那还有什么不能实现的,那就不是都键盘事件了,是获取USB的原始数据了。。
我现在没有搞明白怎么通过API方式获取USB键盘的报文,WINIO也不行,
已经被处理成键盘事件的命令了,我还要设备做什么,就是因为键盘命令中不带设备区分

#11


比较棘手的现实问题,顶起来

#12


上班开始,UP下。。等待高手的指点

#13


up

#14


UP

#15


这个可以用C++做。。

#16


引用 9 楼 liyoubaidu 的回复:
去C++那里问吧。要不写个驱动?



友情up

#17


用WMI取出硬件媒体对象遍历,取其编号属性试试

#18


关注下

#19


C++比较初级的方法也就是调用API,建立连接后去BULK管道读取数据,调用IRP_MJ_READ和IRP_MJ_WRITE,最后不还是调用readfile来处理的。。如果只是建立连接C++才能写的话,HID是自动识别建立的,问题是这个数据怎么拿?

#20


不好判断。

#21


极度关注本帖!

#22


UP

#23


不会,我感觉这时候应该用分时系统。。

#24


给他不同的时间片吧。这个和系统就有关了呵呵,,,,

#25


UP

#26


关注!!

#27


顶一下

#28


UP

#29


该回复于2009-09-16 09:53:40被版主删除

#30


同前面讲键盘编程的过程一样,我们还是先从 DIRECTINPUT 的初始化开始吧:
  #include <dinput.h>

  #define DINPUT_BUFFERSIZE 16

  LPDIRECTINPUT lpDirectInput; // DirectInput object
  LPDIRECTINPUTDEVICE lpMouse; // DirectInput device

  BOOL InitDInput(HWND hWnd)
  { 
    HRESULT hr;

    // 创建一个 DIRECTINPUT 对象
    hr = DirectInputCreate(hInstanceCopy, DIRECTINPUT_VERSION, &lpDirectInput, NULL);

    if FAILED(hr)
    {
     // 失败
     return FALSE;
    }

    // 创建一个 DIRECTINPUTDEVICE 界面
    hr = lpDirectInput->CreateDevice(GUID_SysMouse, &lpMouse, NULL);
    if FAILED(hr)
    {
     // 失败
     return FALSE;
    }

    // 设定查询鼠标状态的返回数据格式
    hr = lpMouse->SetDataFormat(&c_dfDIMouse); 
    if FAILED(hr) 
    { 
     // 失败
     return FALSE;
    }

    // 设定协作模式
    hr = lpMouse->SetCooperativeLevel(hWnd,
       DISCL_EXCLUSIVE | DISCL_FOREGROUND);
    if FAILED(hr) 
    {
     // 失败
     return FALSE;
    }

    // 设定缓冲区大小
    // 如果不设定,缓冲区大小默认值为 0,程序就只能按立即模式工作
    // 如果要用缓冲模式工作,必须使缓冲区大小超过 0
    DIPROPDWORD property;

    property.diph.dwSize = sizeof(DIPROPDWORD);
    property.diph.dwHeaderSize = sizeof(DIPROPHEADER);
    property.diph.dwObj = 0;
    property.diph.dwHow = DIPH_DEVICE;
    property.dwData = DINPUT_BUFFERSIZE;

    hr = lpMouse->SetProperty(DIPROP_BUFFERSIZE, &property.diph);

    if FAILED(hr)
    {
     // 失败
     return FALSE;
    }

    hr = lpMouse->Acquire(); 
    if FAILED(hr)
    {
     // 失败
     return FALSE;
    }

  return TRUE;
  } 
  除了少数几处改动以外,这段代码同前面讲的键盘编程的代码基本上完全一样。
  注意调用 CreateDevice 来建立一个 DIRECTINPUTDEVICE 界面时,我们用的参数是 GUID_SysMouse 而不是 G
UID_SysKeyboard,我们以此来指明了建立的是鼠标对象。相应的,在用 SetDataFormat 来设定返回数据的格式时
,我们用的参数是 &c_dfDIMouse 而不是 &c_dfDIKeyboard。
  还有要特别注意的是,前面讲到的键盘,在设置协作方式时,是只能按非独占方式工作的,而鼠标即可以按非
独占方式工作,也可以按独占方式工作。

2、DIRECTINPUT 的数据查询
  在作 DIRECTINPUT 的鼠标数据查询时, 我一般都是使用的缓冲模式而不是立即模式。原因很简单,因为鼠标
移动事件的频率很高, 按立即模式去处理就很难保证不丢失数据。至于 DIRECTX SDK 里的例程使用立即模式读取
数据则是因为它们用了一个多媒体计时器来保证以每秒三十次的频率处理接受鼠标数据。
  明白这一点后, 下面我们就来看看相应的代码。由于 DIRECTX SDK 里的例程有立即模式的代码,我就偷点懒
,下面只给出了一段缓冲模式下的代码:
  HRESULT UpdateInputState(void)
  {
    DWORD i;

    if(lpMouse != NULL) 
    {
     DIDEVICEOBJECTDATA didod; // Receives buffered data
     DWORD dwElements;
     HRESULT hr;

     while(TRUE)
     {
      dwElements = 1; // 每次从缓冲区中读一个数据
      hr = lpMouse->GetDeviceData(sizeof(DIDEVICEOBJECTDATA),&didod,&dwElements,0);

      if FAILED(hr)
      {
       // 发生了一个错误
       if(hr == DIERR_INPUTLOST)
       {
        hr = lpMouse->Acquire(); // 试图重新取回设备
        if FAILED(hr)
        {
         return S_FALSE; // 失败
        }
       }
      }
      else
      if(elements == 1)
      {
       switch(didod.dwOfs)
       {
        case DIMOFS_X: // X 轴偏移量
                // didod.dwData 里是具体偏移相对值,单位为像素
          break;
        case DIMOFS_Y: // Y 轴偏移量
                // didod.dwData 里是具体偏移相对值,单位为像素
          break;
        case DIMOFS_BUTTON0: // 0 号键(左键)状态 
                   // didod.dwData 里是具体状态值
                   // 低字节最高位为 1 则表示按下
                   // 低字节最高位为 0 表示未按下
          break;
        case DIMOFS_BUTTON1: // 1 号键(右键)状态 
                   // 同上
          break;
        case DIMOFS_BUTTON2: // 2 号键(中键)状态 
                   // 同上
          break;
        case DIMOFS_BUTTON3: // 3 号键状态 
                   // 同上
          break;
       }
      }
      else if (elements == 0) break; // 缓冲区读空
     }
   }

  return S_OK;
  }
  这段代码注释得非常详细,相信你很快就能看懂。

3、DIRECTINPUT 的结束处理
  还记得当程序结束时必须要进行的释放处理吧,其代码如下:
  void ReleaseDInput(void) 
  { 
   if (lpDirectInput) 
   { 
    if(lpMouse) 
    { 
     // Always unacquire the device before calling Release(). 
     lpMouse->Unacquire(); 
     lpMouse->Release();
     lpMouse = NULL; 
    }
    lpDirectInput->Release();
    lpDirectInput = NULL; 
   } 
  } 
以上是C++的一种获取方式,我对C++不了解,有没有了解的人,给我通俗的解释下

#31


DirectInput 说是也可以获取USB数据的,但我不知道怎么用

#32


UP

#33


关注本贴!UP

#34


还没解决