rawinput擷取資料的2個api getrawinputdata()和getrawinputbuffer()
msdn並未說明什麼情況下使用哪種api,而一般來說getrawinputdata()就可以擷取到資料的,想當然的我們就會認為只需要使用其中一種就可以。
但是實際測試說明光使用getrawinputdata()是會丟失輸入資料的。
做一個簡單的測試:
第一步:WM_INPUT響應中同時使用data和buffer方法取輸入資料。
可以看到data是立即擷取了資料,而buffer方法擷取到資料為0.
第二步:在WM_INPUT裡面加上延遲Sleep(100).
現在將會發現data和buffer裡面都有資料了。
現在來分析為什麼會有這種情況。
以滑鼠輸入為例:
當我們移動滑鼠的時候,滑鼠會源源不斷的產生資料發送給系統。此時產生WM_INPUT訊息,如果訊息被立即處理掉,那麼新的input 訊息來的時候會再產生一個wm_input
如果訊息產生的速度過快,來不及處理,就像上面的例子中,每秒只能處理10個wm_input那麼新的input來時就會放到buffer裡面供下次擷取(這裡丟棄也是一種選擇,但是輸入裝置的資料被丟棄的話,會造成卡鍵之類很噁心使用者的結果)。
所以對使用rawinput的程式來說,最好的處理方法是2個api都要處理。
另外一個問題就是buffer裡面的資料和data裡面的資料順序問題,也就是哪個資料是最後產生的?
這個問題msdn裡面沒有說明,測試結果,buffer裡面是曆史資料,data是最近的。
這個問題也會造成卡鍵,按下和釋放鍵的順序是很重要,搞反了鍵就卡住了。
最後一個問題:getrawinputbuffer在wow64資料對齊上面很噁心人
wow64是win64對win32的一個類比層。如果你開發的程式是32位的,而且有可能在64位win上面用,就要多小心了。
getrawinputdata在wow64下面和win32一樣,但是getrawinputbuffer對齊是64位的。也就是說直接使用RAWINPUT結構讀資料,獲得的是錯誤的結果,必須檢測是否wow64然後做相應的處理(加上位移)。這點msdn上面有一點提示,沒看到的話找bug找死人了。