2018年9月10日 星期一

DirectInput的學習心得(1)

DirectInput的使用(1)

前言

  在偵測輸入時可以採用XInput來偵測,可以參考XInput的使用這一篇,但XInput並不支援鍵盤與滑鼠,且手把要是年代較久遠的話也會無法被XInput偵測到。為什麼不用訊息幫浦來偵測輸入呢?理由很簡單,作業系統的訊息幫浦沒辦法調整偵測的速度,像現代電玩時常需求的FPS60偵測速度是達不到的,就我以前實測的經驗,訊息幫浦不但偵測速度不夠,而且偶爾還有掉輸入(明明有輸入卻沒反應),雖然不知是否為偵測速度不夠造成,但用DirectInput偵測鍵盤的輸入,這個狀況就可以得到解決。這次的紀錄只會記錄到鍵盤的偵測與使用,在此做個紀錄。

內容

  使用DirectInput的過程並不會太繁雜,首先使用DirectInputCreate()製造出IDirectInput8,這個介面只需造一次即可,接著用IDirectInput8來製造出IDirectInputDevice8,而依據製造的參數不同可以讓IDirectInputDevice8代表鍵盤、滑鼠與手把,本篇將說明如何將IDirectInputDevice8初始化為鍵盤。
  初始化鍵盤的範例碼如下

#include <dinput>
#include <dinputd>
void DetectedKeyboardKeys(IDirectInputDevice8* pDIDeviceKeyboard)
{
  unsigned char keyState[256];
  if(pDIDeviceKeyboard->etDeviceState(256,keyState) != DI_OK)
    return;
  //if GetDeviceState() is fined,keyState will save all key state from keyboard...
  //Follow detect sample...
  //Is num 0 pressed? 
  if(keyState[DIK_0])
  {
    //do something...
  }
  //Is key a pressed? 
  if(keyState[DIK_A])
  {
    //do something...
  }
  
}
int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow )
{
  //Init main window
  //...
  HWND mainWin = initMainWindow;
  //Init DiectInput...
  IDirectInput8* pDirectInput = nullptr;
  if(DirectInput8Create(hInstance,DIRECTINPUT_VERSION,IID_IDirectInput8,(void**)&pDirectInput ,NULL) != DI_OK)
    return 1;
  //Init keyboard
  IDirectInputDevice8* pDIDeviceKeyboard = nullptr;
  if(pDirectInput->CreateDevice(GUID_SysKeyboard,&pDIDeviceKeyboard ,NULL) != DI_OK)
  {
    pDirectInput->Release(); 
    return 1;
  }
  //
  if(pDIDeviceKeyboard->SetCooperativeLevel(mainWin,DISCL_FOREGROUND|DISCL_NONEXCLUSIVE) != DI_OK)
  {
    pDIDeviceKeyboard->Release();
    pDirectInput->Release(); 
    return 1;
  }
  if(pDIDeviceKeyboard->SetDataFormat((DIDATAFORMAT*)&amp;c_dfDIKeyboard) != DI_OK)
  {
    pDIDeviceKeyboard->Release();
    pDirectInput->Release(); 
    return 1;
  }
  //
  pDIDeviceKeyboard->Acquire();
  //Init keyboard end
  // 
  return 0;
}

在主程式一如之前所說製造出IDirectInput8,要注意HINSTANCE是必要的參數,再來是透過 IDirectInput8的CreateDevice()來製造出IDirectInputDevice8,並可載參數上看到"GUID_SysKeyboard",這個參數會決定裝置是鍵盤、滑鼠或手把,接著是SetCooperativeLevel(),主要的目的確定要偵測哪個視窗的輸入,SetDataFormat()決定偵測資料的輸出格式,在鍵盤時這是固定的,所以用c_dfDIKeyboard來設定即可,接著Acquire(),這個過程很重要,初始化的最後一個流程,勢必要流程請勿省略,Acquire()如果失敗表示該裝置目前沒連上,以上就是初始化鍵盤的部分。偵測的部分在DetectedKeyboardKeys(),首先準備好一塊Buffer,範例使用的是keyState,256是鍵盤上所有的鍵的大小,透過GetDeviceState()來取得所有按鍵的輸入狀態,取完之後如何取得要偵測的按鍵的狀態呢?可以參考
Keyboard Device Enumeration,用該列舉來做為索引值取得目前按鍵的狀態,如果不是0就代表按下。

參考資料

Capturing DirectX DirectInput Keyboard and Mouse Input
DirectInput
Keyboard Device Enumeration

相關文章

DirectInput的學習心得(2)

沒有留言:

張貼留言