如我們使用joyGetPosEx獲取游戲設備的狀態時,必須先初始化JOYINFOEX結構實例,並要設置dwSize 參數的值,也即是JOYINFOEX結構體所占用的內存空間大小(其值可通過Marshal.SizeOf求得)。而如果 要取得游戲設備的其它參數,則還必須要設置dwFlags參數的值!否則只能獲取坐標值(dwXPos)。如對游 戲手柄來說我們需要獲取其它按鈕的狀態,則設置dwFlags的值為JOY_RETURNBUTTONS,用於指示我們需要 返回所有按鈕的狀態。
示例代碼:
JoystickAPI.JOYINFOEX infoEx = new JoystickAPI.JOYINFOEX();
infoEx.dwSize = Marshal.SizeOf(typeof(JoystickAPI.JOYINFOEX));
infoEx.dwFlags = (int)JoystickAPI.JOY_RETURNBUTTONS;
int result = JoystickAPI.joyGetPosEx(this.Id, ref infoEx);
如果joyGetPosEx函數獲取手柄狀態數據成功,則返回JOYERR_NOERROR(值為0),否則返回其它值的話 表示獲取失敗。
當數據獲取成功後,對應的游戲手柄的狀態數據都已存儲在JOYINFOEX結構實例中了。如要判斷是否按 下了方向鍵,則可判斷dwXPos與dwYPos的值;而判斷是否按了其它按鈕,則可判斷dwButtons的值。判斷 方法在上一章中有講,這裡就不再細說,或者也可以看後面提供的源碼。
因為“主動方式”的“時效性”只有一次,所以為了能夠隨時監視到游戲手柄的按鍵事件,就必須進 行“輪循”獲取,當監視到游戲手柄有按鍵發生時就進行事件通知(噫?好像“被動方式”?嗯,其實當 我們向系統申請捕捉某個游戲手柄時,系統最後也是在幫我們進行“輪循”操作!)。而實現“輪循”的 方式則可以有多種方式,比如采用獨立的線程進行一個死循環;或者采用Timer進行定時執行。
但當我們的操作進入“輪循”後,如果也是直接joyGetPostEx就處理的話也一樣會碰到篇頭所說的那 個糟糕問題 !因為不管是“主動方式”還是“被動方式”都是一樣只能得到游戲手柄按鈕當前的狀態( 按下或未按下)。那怎麼解決呢?
解決按鈕重復狀態的問題
解決這個問題,如果理清了思路,其實也是很簡單的方法。
我們通過API得到的是游戲手柄按鈕當前的狀態(被按下或未按下)。因此我們可以在“輪循”裡,每 當監視到游戲手柄在某次時間有某些按鈕是處於“按下”狀態時,就記錄此次被按下的按鈕號,這樣當下 一次“輪循”操作時,如果也監視到有按鈕按下,則通過與上一次按下的按鈕對比,如果還是相同的按鈕 ,則表明本次按鈕還是繼續上次的按下狀態,那就不再需要向程序裡發出消息通知了。而如果不相同,則 發出新的按鈕按鍵通知,並記錄本次按下的按鈕號。
偽代碼如下:
previousButtons = 無;
//死循環,進入輪循
while(true){
if(joyGetPosEx(手柄號,ref joyInfo) == 成功){
JoyButtons buttons = 取得當前按下的按鈕(joyInfo);
if(buttons != 無){
if(buttons != previousButtons){
//本次按下的按鈕不同於上次按下的按鈕. 所以進行通知
OnClick(buttons);
//記錄本次按下的按鈕
previousButtons = buttons;
}
}
}
暫停uPeriod毫秒;
}