作者ypf791 (路人1號)
看板EE_DSnP
標題[心得] testAsc雜談
時間Sun Oct 7 02:17:59 2012
開始玩testAsc了
一開始就發現我的程式編譯不過 上版一查
FLAG的問題 comment掉就沒事了 (
#1GR_Es0d (EE_DSnP))
正常編譯後開始測按鍵 結果所有非字元鍵全死...
原來是因為cmdCharDef.cpp裡面的處理函數只處理了單碼按鍵
雙碼以上都是空的
於是先把下面助教會用的那段code毫不猶豫的抄過來
重新編譯後 開始讀的到特殊碼了
但是!! Backspace, Home, End這三個按鍵沒有正常顯示
不幸啊...
====以下正文====
真的像我這麼不幸(好吧只有三個鍵已經很幸福了)的話要怎麼辦
基本上就是"讓程式看懂這串輸入是啥鬼"
所以第一件事就是紀錄自己的按鍵傳出怎樣的碼
以我的例子 Home傳出來的是27->79->72
End傳出來的是27->79->70
什麼? 你問我怎麼知道的?
就算認不得你的按鍵 testAsc還是會老實的印出來啊(笑)
接下來是分析
首先我們觀察助教的鍵盤
cmdCharDef.h Line:54開始是enum ParseChar的定義
這裡面包含了所有按鍵會傳出來的碼 大致上分為
1) 所有系統都一樣的單碼字元(Line 56:63)
Tab啦Enter啦Esc啦大概都在這裡
2) 跟系統有關的單碼字元(Line 65:78)
只有一個Backspace
3) 跟系統有關的多碼字元(Line 80:105)
Arrow keys & Mod keys
4) 未定義字元, 嗶一聲等等根本跟鍵盤無關的常數
我們可能需要改動的地方是2和3
我很幸運的 Backspace跟助教一樣是127
所以把助教的抄過來就好了
為了讓我們能適當的定義對應到自己按鍵的常數 我們要先了解編碼規則
第三區的按鍵編碼規則 以助教的鍵盤為例
Ex: ARROW_UP = 27 -> 91 -> 65
第一碼是特殊按鍵識別 一定是Esc
第二碼是特殊按鍵種類識別 助教的鍵盤在這裡沒有分別 Arrow和Mod都是91
像我的鍵盤就有分91和79的
第三碼是區分特殊按鍵 像UP是65 DOWN是66 諸如此類
Ex: PG_UP = 27 -> 91 -> 53 -> 126
前三碼的意義同上
第四碼是後綴修飾 助教的Mod鍵全都有這個後綴
接著來分析自己的按鍵的編碼規則
以我的為例 就是Esc -> [種類識別碼79] -> [識別碼]
所以就這樣定義常數:
//
// --HOME_END keys: 27 -> 79 -> {72,70}
//
MY_KEY_FLAG = 1 << 10,
MY_KEY_INT = 79,
MY_HOME_KEY = 72 + MY_KEY_FLAG,
MY_END_KEY = 70 + MY_KEY_FLAG,
注意到因為我的按鍵是不連續的(天知道為什麼)
所以我定義_BEGIN和_END毫無用處
然後因為ARROW用掉了1<<8 MOD用掉了1<<9
所以我的_FLAG是1<<10
這裡說明一下_BEGIN, _END & _FLAG 這些其實是設計者的巧思:
i) 因為這些特殊碼的第三碼是連續的 所以如果把頭尾記錄下來
到時候想要判斷這些碼的時候就只要看範圍就好
這是_BEGIN和_END
ii) 如果我們今天拿到一個代表某按鍵的常數 我們想知道它是哪種按鍵
我們自然也可以去看範圍 但是有_FLAG就會更方便
例如我們可以寫這樣:
bool isArrowKey(ParseChar ch){ return ch & ARROW_KEY_FLAG; }
這樣就可以把兩個邏輯運算變成一個位元運算了
注意到當成FLAG的bit在char的範圍外
所以可以用char(ARROW_UP_KEY)這種方式把FLAG遮起來
這就是為什麼會有 PG_UP_KEY = 53 + MOD_KEY_FLAG 這種寫法
常數定義完之後就要處理
處理的函數是ParseChar checkChar(char,istream&) @ cmdCharDef.cpp, Line 73:109
基本上當然是在那個switch裡作文章
處理的邏輯是如果讀到ESC就去抓下一個碼
根據這碼所代表的特殊鍵種類進行不同的處理
只要記得回傳的時候 是傳原本定義好的常數而不是自己定義的那個
(因為我們只動這兩個地方 其他部份的程式都不知道我們有偷改這裡
所以他們根本不認得我們定義的常數)
(不過如果是原本沒定義過的常數 也是可以硬傳回去 只是接收端的處理可能要改寫)
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 111.248.9.32
推 jackervator:推一下 10/07 02:49
推 OckhamsRazor:推原PO 我也是這三個鍵不一樣XD 10/07 11:36
推 vegired:推一下,我這三個鍵也是另外改的XD 10/07 22:35
推 ric2k1:很實用的心得分享,先置底一下到 HW#2 due!! 10/07 23:30
推 XDucka:如果is Arrowkey那樣寫 不是要先確定 home 跟 uparrow雖然 10/09 21:49
→ XDucka:flag不一樣 但是也要確定key值不一樣 要是 pageup也是53 10/09 21:49
→ XDucka:leftarrow也是53不就G了@@ 既然這個不會重複 那當初幹嘛 10/09 21:50
→ XDucka:要多設定這種27 -> 91 -> xx 的方法阿.. 10/09 21:50
推 taldehyde:可以問一下1<<10的意思嗎? 10/12 20:47
推 OckhamsRazor:樓上裝弱... 10/12 21:04
→ taldehyde:樓上別這樣...後來查到是bitwise-shifting 10/12 21:17
推 andy13579372:感謝樓上 剛自D了一篇同樣的問題文 10/13 22:48
推 abc346289:所以意思是說我的home是27->79->72改完之後執行testAsc 10/14 00:19
→ abc346289:按home顯示"27 79 72 Home key"這樣就是完成了嗎? 10/14 00:20
推 ric2k1:會顯示 Home Key 而且再按下一個 key 也是正常的話,應該 10/14 13:44
→ ric2k1:就是 OK 囉! 10/14 13:44
推 ss355227:自己改完的經驗,如果定義成MY_HOME_KEY,testAsc好像會 10/18 03:49
→ ss355227:看不懂,應該只要HOME_KEY就好了 好像是原本就定好了 10/18 03:49
推 Phantasnix:參看這篇心得指點了自己的迷惑,感謝這麼用心又條理明 10/18 20:36
→ Phantasnix:晰的心得 <(_ _)> 10/18 20:36
→ ypf791:姆...其實我的意思是checkChar裡面 判斷用MY_KEY_INT和 10/19 00:55
→ ypf791:MY_KEY_FLAG之類的 但是return的時候用已經定義過的 10/19 00:55
→ ypf791:直接回傳MY_HOME_KEY的話的確會看不懂 10/19 00:56