DirectInput 鍵盤程式設計入門

2021-06-01 01:59:17 字數 3704 閱讀 6454

標籤:

directinput

鍵盤入門

遊戲程式設計可不僅僅是圖形程式的開發工作,實際上包含了許多方面,本文所要講述的就是關於如何使用directinput來對鍵盤程式設計的問題。

在 dos 時代,我們一般都習慣於接管鍵盤中斷來加入自己的處理**。但這一套生存方式在萬惡的 windows 社會下是行不通的,我們只能靠領 api 或者 directinput 的救濟金過活。

在 windows 的 api 中,有乙個 getasynckeystate() 的函式可以返回乙個指定鍵的當前狀態是按下還是鬆開。這個函式還能返回該指定鍵在上次呼叫 getasynckeystate() 函式以後,是否被按下過。雖然這個函式聽上去很不錯,但現在領這種救濟金的程式設計師是越來越少了。原因無它,只因為 directinput 的救濟金比這豐厚,而且看上去似乎更專業?

為了早日成為職業的救濟金使用者,我們就從學習 directinput 的鍵盤程式設計開始吧。

directinput 的初始化

前面講 directdraw 時,曾經提到,微軟是按 com 來設計directx的,所以就有了乙個 directinput 物件來表示輸入裝置,而某個具體的裝置由 directinputdevice 物件來表示。

實際的建立過程是先建立乙個 directinput 物件,然後在通過此物件的 createdevice 方法來建立 directinputdevice 物件。

示例如下:

#include

#define dinput_buffersize 16

lpdirectinput           lpdirectinput;  // directinput object

lpdirectinputdevice     lpkeyboard;     // directinput device

bool initdinput(hwnd hwnd)

// 建立乙個 directinputdevice 介面

hr = lpdirectinput->createdevice(guid_syskeyboard, &lpkeyboard, null);

if failed(hr)

// 設定為通過乙個 256 位元組的陣列返回查詢狀態值

hr = lpkeyboard->setdataformat(&c_dfdikeyboard);

if failed(hr)

// 設定協作模式

hr = lpkeyboard->setcooperativelevel(hwnd, discl_nonexclusive | discl_foreground);

if failed(hr)

// 設定緩衝區大小

// 如果不設定,緩衝區大小預設值為 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 = lpkeyboard->setproperty(diprop_buffersize, &property.diph);

if failed(hr)

hr = lpkeyboard->acquire();

if failed(hr)

return true;}

在這段**中,我們首先定義了 lpdirectinput 和 lpkeyboard 兩個指標,前者用來指向 directinput 物件,後者指向乙個 directinputdevice 介面。

通過 directinputcreate(), 我們為 lpdirectinput 建立了乙個 directinput 物件。然後我們呼叫 createdevice 來建立乙個 directinputdevice 介面。引數 guid_syskeyboard 指明了建立的是鍵盤物件。

接下來 setdataformat 設定資料格式,setcooperativelevel 設定協作模式,setproperty 設定緩衝區模式。因為這些函式方法的引數很多,我就不逐個去詳細解釋其作用了,請直接檢視 directx 的幫助資訊,那裡面寫得非常清楚。

完成這些工作以後,我們便呼叫 directinputdevice 物件的 acquire 方法來啟用對裝置的訪問許可權。在此要特別說明一點,任何乙個 directinput 裝置,如果未經 acquire,是無法進行訪問的。還有,當系統切換到別的程序時,必須用 unacquire 方法來釋放訪問許可權,在系統切換回本程序時再呼叫 acquire 來重新獲得訪問許可權。

所以,我們通常要在 windowproc 中做如下處理:

哦,對了,前一段例程中還提到了立即模式和緩衝模式。在 directinput 中,這兩種工作模式是有區別的。

如果使用立即模式的話,在查詢資料時,只能返回查詢時的裝置狀態。而緩衝模式則將記錄所有裝置狀態變化過程。就個人喜好而言,筆者偏好後者,因為這樣一般不會丟失任何按鍵資訊。對應的,如果在使用前者時的查詢頻度太低,則很難保證採集資料的完整性。

directinput 的資料查詢

立即模式的資料查詢比較簡單,請看下面的示例:

byte diks[256]; // directinput keyboard state buffer 鍵盤狀態資料緩衝區

hresult updateinputstate(void)

}if(failed(hr))

return hr;

}return s_ok;}

在上面的示例中,關鍵處就是使用 getdevicestate 方法來讀取輸入裝置狀態值以及對異常情況的處理。通過使用 getdevicestate 方法,我們把輸入裝置的狀態值放在了乙個 256 位元組的陣列裡。如果該陣列中某個陣列元素的最高位為 1,則表示相應編碼的那個鍵此時正被按下。例如,如果 diks[1]&0x80>0,那麼就表示 esc 鍵正被按下。

學會了立即模式的資料查詢以後,下面我們開始研究緩衝模式的情況:

hresult updateinputstate(void)

}if(failed(hr))

return hr;

}// getdevicedata() 同 getdevicestate() 不一樣,呼叫它之後,

// dwelements 將指明此次呼叫共讀取到了幾條緩衝區記錄

// 我們再用乙個迴圈來處理每條記錄

for(int i=0; i

其實,每條記錄還有 dwtimestamp 和 dwsequence 兩個欄位來記錄訊息發生的時間和序列編號,以便作更複雜的處理。本文是針對初學者寫的,就不打算去談論這些內容了。

directinput 的結束處理

我們在使用 directinput 時,還要注意的一件事就是當程式結束時,必須要進行釋放處理,其演示**如下:

void releasedinput(void)

lpdirectinput->release();

lpdirectinput = null;}}

這段**很簡單,就是對 directinput 的各個物件去呼叫 release 方法來釋放資源。這種過程同使用 directx 的其它部分時是基本上相同的。

DirectInput 鍵盤程式設計入門

哦,對了,前一段例程中還提到了立即模式和緩衝模式。在 directinput 中,這兩種工作模式是有區別的。如果使用立即模式的話,在查詢資料時,只能返回查詢時的裝置狀態。而緩衝模式則將記錄所有裝置狀態變化過程。就個人喜好而言,筆者偏好後者,因為這樣一般不會丟失任何按鍵資訊。對應的,如果在使用前者時的...

direct input 標準呼叫

讀書筆記 direct input 部分 1.取得idirectinput介面,directinput8create 2.獲得介面後建立裝置 滑鼠,鍵盤.3.設定裝置協作等級,setcooperativelevel 4.設定資料格式,setdataformat 5.獲取裝置,acquire 6.使用...

鍵盤顯示程式設計

include include include include include void defor void defor char dujian int i,k i 1 porta 0x0f if pind 0x0f break if pind 0x0d break if pind 0x0b br...