我正在研究C++ DirectX 2D遊戲,我需要鍵盤和鼠標輸入。
維基說:我應該使用DirectInput還是Windows消息循環?
Microsoft建議新的應用程序使用Windows的消息循環的鍵盤和鼠標輸入的DirectInput
代替
所以,我應該如何使用它呢?
我有一個GameScreen類來照顧繪圖和更新(遊戲邏輯),我在Windows消息循環中調用Draw和Update方法。
感謝
我正在研究C++ DirectX 2D遊戲,我需要鍵盤和鼠標輸入。
維基說:我應該使用DirectInput還是Windows消息循環?
Microsoft建議新的應用程序使用Windows的消息循環的鍵盤和鼠標輸入的DirectInput
代替
所以,我應該如何使用它呢?
我有一個GameScreen類來照顧繪圖和更新(遊戲邏輯),我在Windows消息循環中調用Draw和Update方法。
感謝
由於您幾乎必須運行消息泵才能擁有一個窗口,因此您還可以使用該泵來處理鍵盤和鼠標輸入。無論您是否將鍵盤事件發送到子窗口,完全取決於您的泵,如果您願意,可以在泵中處理它們。
你典型的消息泵看起來是這樣的:
while (GetMessage(&msg, NULL, 0, 0))
{
if (WM_QUIT == msg.message)
break;
TranslateMessage(&msg); // post a WM_CHAR message if this is a WM_KEYDOWN
DispatchMessage(&msg); // this sends messages to the msg.hwnd
}
對於一個遊戲,你的泵可能看起來更像是這個
while (true)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE | PM_NOYIELD))
{
bool fHandled = false;
if (msg.message >= WM_MOUSEFIRST && msg.message <= WM_MOUSELAST)
fHandled = MyHandleMouseEvent(&msg);
else if (msg.message >= WM_KEYFIRST && msg.message <= WM_KEYLAST)
fHandled = MyHandleKeyEvent(&msg);
else if (WM_QUIT == msg.message)
break;
if (! fHandled)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else
{
// if there are no more messages to handle right now, do some
// game slice processing.
//
}
}
當然,你的實際的泵將有可能比數量更爲複雜即可能有MsgWaitForMultipleObjects
,這樣即使沒有要處理的消息,也可以定期喚醒,但在有消息時立即進行喚醒。
如果遊戲中有一個窗口,比據我可以告訴區分純粹是口味的問題。但是,如果你有(或正計劃擁有或不能肯定排除未來有多個窗口),那麼Windows消息傳遞可能會讓人厭煩。
問題在於,默認情況下,鍵盤/鼠標消息僅路由到當前焦點窗口,並且通常在希望能夠切換焦點的遊戲中(到高分視圖,雷達視圖上的敵人或任何其他)仍然保持交互性。簡單的解決方案是每個需要鍵盤/鼠標輸入的模塊直接查詢它,而不依賴於消息轉發 - 因此,DirectInput。
我不能說你的具體情況,當然 - 只是我的2C。
鍵盤和鼠標事件不是真的進入焦點窗口。鍵盤事件通過您的消息泵_發送到焦點窗口_(這是DispatchMessage的功能)。鼠標事件進入光標下的窗口。 – 2010-01-30 00:32:27
對。謝謝!我原本只使用鍵盤評論,然後纔將其「固定」到鍵盤/鼠標上。 – 2010-01-30 22:00:40
XInput絕對是最佳選擇。低延遲輸入對遊戲至關重要,XInput(在新的DirectXSDK中替換DirectInput)專爲這些用例設計。
此外,您還支持遊戲控制器,遊戲杆等開箱即用。
DirectInput對於鍵盤和鼠標事件的延遲並不低。但是,如果您稍後想要支持遊戲杆等,它確實會爲您提供更一致的輸入模型。 – 2010-01-30 00:28:53
您是絕對正確的,但我的意思是DirectInput(和XInput是DInputs後繼程序)的延遲低於Windows消息。 – DarthCoder 2010-01-30 01:22:37
但不適用於鍵盤和鼠標輸入。DirectInput只是用於鍵盤和鼠標的Win32 API的一個包裝。 – 2010-01-30 03:10:40
是的,MSDN的帖子是正確的。使用Windows消息,您可以使用多語言支持(對於用戶可能使用的任何類型的鍵盤)/用戶的個人設置(鼠標右鍵而不是左鍵)等。您必須放棄使用DirectInput/XInput 。 僅將這2個用於遊戲手柄/遊戲杆支持。其餘的只是使用Windows消息。
詳情請參閱John Knoeller的答案。
FYI:重新約翰Knoeller的答案......一個簡單的消息泵看起來是這樣的:
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
的WM_QUIT測試,他包括在內,因爲GetMessage函數返回收到WM_QUIT時零永遠是真實的。但是,在PeekMessage循環中測試WM_QUIT的值是,因爲無論是否返回消息,PeekMessage都會返回true/false。由於GetMessage阻塞直到返回一條消息,所以它可以有不同的返回值。
使用,只能使用DirectInput的特殊情況下
約與使用的GetMessage在Windows消息循環的好處是,它使用0%的CPU使用率。如果您正在做非處理器密集型的事情,比如等待用戶的密鑰,從用戶收集數據(例如數據庫或稅務程序,甚至是文字處理器),則只需使用帶有getmessage的Windows消息即可。我所有的上述程序日期是當用戶按下一個鍵時的過程。
Windows消息循環需要處理密鑰的所有內容都是要切換到的程序。鼠標甚至不需要在窗口中。
特殊情況下使用的DirectInput
如果您需要: 1)當一個鍵被按下並釋放認識。您也可能不希望重複檢測爲按鍵。
2)另一個程序切換到後臺處理鍵。
如果以上任一情況屬實,請使用directinput。
如果您只是從用戶收集數據,那麼您將需要使用sleep命令暫停程序的執行。如果程序只是坐在那裏等待用戶的密鑰,您希望程序在任務管理器中的CPU使用率爲0%。
使用休眠功能使程序進入休眠狀態,直到您想輪詢鍵的直接輸入爲止。
因此,如果您正在從用戶那裏收集密鑰的簡單普通任務,那麼直接輸入只會浪費編程時間,正如您所看到的。
我想知道爲什麼我不應該使用DirectInput。 謝謝 – Adir 2010-01-30 10:32:17
通過回答亞歷克斯在http://stackoverflow.com/questions/2165230/should-i-use-directinput-or-windows-message-loop/2168067#2168067 – bobobobo 2010-02-10 04:22:08