1. 程式人生 > >windows 快捷鍵概述(Windows Accelerators)---嚴格來說,應該稱為鍵盤加速器

windows 快捷鍵概述(Windows Accelerators)---嚴格來說,應該稱為鍵盤加速器

https://docs.microsoft.com/zh-cn/windows/desktop/menurc/about-keyboard-accelerators

本文翻譯介紹windows 熱鍵,我們通常所說的熱鍵/快捷鍵,微軟文件中為“Keyboard Accelerators”。翻譯中使用“快捷鍵”表示這一概念。

 

題外話,https://social.technet.microsoft.com/Forums/scriptcenter/en-US/94867ee8-c03e-42d5-90cb-d34f153fb587/show-registered-keyboard-shortcuts-hotkeys?forum=ITCG

 該連結中提到兩個概念keyboard shortcuts 和 keyboard Accelerators ,前一個針對系統全域性範圍的快捷鍵,後一個對應的應用軟體中的快捷鍵,感覺兩者之間還是有卻別的(Accelerators  也包括了應用程式特有的和系統全域性範圍的),應該分別翻譯為“按鍵快捷鍵”、“按鍵加速器”,但我們通常不習慣稱呼“按鍵加速器”。

 

快捷鍵和選單類似,都給使用者提供了一種訪問應用程式的功能集的機會。通常,使用者通過閱讀軟體的選單來了解應用的功能集,之後,使用者可以通過快捷鍵來更加高效的使用應用的功能。快捷鍵使得可以更加快速、準確的使用應用所提供的功能。應用程式至少應該為常見的命令生成快捷鍵,另外,一般快捷鍵是對應選單命令的,但是,也可以只存在快捷鍵而沒有選單(比如esc通常可以退出當前視窗,這種常見的功能不必有選單但可以有快捷鍵)。

文章包含以下內容:

  1. 快捷鍵表
  2. 快捷鍵表的建立
  3. 快捷鍵按鍵分配
  4. 快捷鍵和選單
  5. UI 狀態

快捷鍵表

一個快捷鍵項包含一個ACCEL 結構的陣列,每個ACCEL 結構定義了一個獨立的快捷鍵。每個ACCEL 包括以下的資訊:

typedef struct tagACCEL { BYTE fVirt; WORD key; WORD cmd; WORD fVirt; DWORD cmd; } ACCEL, *LPACCEL;

  • 快捷鍵的鍵組合資訊
  • 快捷鍵的ID
  • 各種標誌,其中包含一個標誌,指示當快捷點被使用的時候時候展示視覺化的反饋,即,如果有對應的選單項的話,是否使其高亮顯示。

為了處理執行緒的快捷鍵擊鍵訊息,開發人員必須線上程的訊息佇列的訊息迴圈中呼叫TranslateAccelerator 函式。該函式監控訊息佇列中的鍵盤輸入,檢查按鍵組合是否匹配了快捷鍵表中的任何一項。如果找到,它將翻譯鍵盤輸入(WM_KEYUP 和 WM_KEYDOWN 訊息)為WM_COMMAND 或 WM_SYSCOMMAND 訊息,並將此訊息傳送給特定的視窗的視窗處理訊息。如下圖所示:

keyboard accelerator processing model

WM_COMMAND 包含了該快捷鍵的ID,視窗處理程式檢查該ID以確定訊息源,並恰當的處理該訊息。

 

快捷鍵表存在兩個等級。系統包含的唯一的,系統範圍的應用於所有應用的快捷鍵表。應用程式不可以修改系統的快捷鍵表。

系統也包含針對每個應用程式的快捷鍵表。一個應用程式可以定義任意數量的它自身使用的快捷鍵。一個唯一的32-bit 控制代碼標誌每個表。對於特定的執行緒來說,只能有一個快捷鍵表是同時活動的。傳給TranslateAccelator 函式的控制代碼決定了當前執行緒中活動的快捷鍵表是哪個。執行緒的快捷鍵表隨時可能改變,因為傳遞給TranslateAccelerator 函式的快捷鍵表的ID 是不確定的。

 

快捷鍵表的建立

為應用程式新增快捷鍵需要幾個步驟:

  1. 使用資源編輯器來建立快捷鍵表資源,並新增它們到應用程式的PE 檔案中
  2. 程式執行時,LoadAccelerators 函式將被呼叫以載入快捷鍵表到記憶體中,並取得快捷鍵表的控制代碼

另外,通過傳遞ACCEL 結構陣列給CreateAcceleratorTable 函式在程式執行時建立快捷鍵表。這個方法支援使用者定義快捷鍵。系統自動銷燬快捷鍵表,但是當應用程式不需要快捷鍵表時,可以通過呼叫DestroyAcceleratorTable 函式來顯式銷燬快捷鍵表。

 

已經存在的快捷鍵是可以被複制和修改的。通過CopyAcceleratorTable 函式來複制快捷鍵表,如果被拷貝的表被修改,CreateAcceleratorTable 函式被呼叫以生成新的快捷鍵表控制代碼。

快捷鍵按鍵分配

使用ASCII 字元碼或者虛擬鍵碼來標識快捷鍵,ASCII字元使得快捷鍵大小寫敏感。但要考慮capslk 按鍵以及shift 按鍵對大小寫的影響。

通常,快捷鍵不需要大小寫敏感,所以,大部分應用程式使用虛擬鍵來標識快捷鍵。

不要講快捷鍵和選單的助記符搞混了。

如果一個應用程式的快捷鍵和系統範圍的快捷鍵衝突了,應用程式的快捷鍵表覆蓋系統的快捷鍵表,當且僅當當前的執行緒上下文是應用程式的上下文。應該儘量避免這種衝突。系統範圍的快捷鍵表如下:

快捷鍵和選單

使用快捷鍵或選擇一個選單項都將導致系統給對應的視窗傳送一個WM_COMMAND 或 WM_SYSCOMMOND 訊息。WM_COMMAND 訊息包含一個ID,標識了訊息源,如果是快捷鍵表,是快捷鍵表的ID,如果是選單,標識了選單項。因為快捷鍵提供了選擇某個選單的捷徑,應用程式經常為快捷鍵和對應的選單使用同樣的ID。儘管如此,WM_COMMAOND 訊息包含一個標記,區別快捷鍵和選單,以防萬一需要區別這兩者。WM_SYSCOMMAND 訊息不包含這個標誌。

ID 決定了快捷鍵生成的訊息是WM_COMMAND 還是 WM_SYSCOMMAND。如果ID和系統選單的一個項值相同,生成WM_SYSCOMMAND。否則,生成WM_COMMAND。

如果快捷鍵對應的選單被禁用,不產生WM_COMMAND 或 WM_SYSCOMMAND 訊息。另外,如果對應的視窗被最小化了,快捷鍵將不會產生命令訊息。

當用戶使用了有對應選單項的快捷鍵,視窗處理程式接收到WM_INITMENU和 WM_INITMENUPOPUP訊息,就像使用者選擇了選單項。https://docs.microsoft.com/zh-cn/windows/desktop/menurc/menus 指示瞭如何處理該訊息。

選單項對應的快捷鍵應該被包含在選單項的文字中。

 

UI 狀態

Windows 使得應用程式可以在它的UI上隱藏或者顯示各種功能,這些狀態被稱為UI 狀態,包含下面的設定:

  1. 聚焦指示(如當前輸入位置等)
  2. 敲擊快捷鍵(通過在控制標籤打下劃線)

視窗可以傳送訊息一請求UI狀態的改變,可以解析UI 狀態,可以強制他的子視窗為特定的狀態,分別使用了下面的訊息:

預設,所有的頂層視窗的子視窗與建立它們的父視窗的UI 狀態是相同的。

系統在視窗建立的時候正確的初始化其狀態,所有的子空間繼承這個狀態。視窗建立後,系統監控使用者按鍵,如果UI狀態設定被隱藏,此時使用者使用按鍵,系統更新UI狀態,比如,如果使用者按tab 鍵以移動焦點到下一個控制元件,系統呼叫WM_CHANGEUISTATE以指示這個聚焦的改變。如果使用者按Alt 鍵,系統呼叫WM_CHANGEUISTATE 使得按鍵快捷鍵可見。

 

如果一個控制元件支援它包含的UI 狀態的改變,他可以更新自己的UI 狀態。控制元件可以呼叫WM_QUERYUISTATE 以解析和快取初始的UI 狀態。無論何時控制元件接收到WM_UPDATEUISTATE訊息,它可以更新自己的UI併發送UI_CHANGEUISTATE訊息給他的父視窗。每個視窗將包持續的傳送該訊息給父視窗指導它到了頂層視窗。頂層視窗傳送WM_UPDATEUISTATE 訊息到視窗樹種的視窗們。如果視窗不傳輸WM_CHANGEUISTATE訊息,訊息將不到達頂層視窗,UI 狀態也得不到更新。