WM GETDLGCODE

WM_GETDLGCODE,是Windows作業系統內建的一種標準Windows消息。[1]如果使用Windows API函數IsDialogMessage來過濾Windows消息,作業系統在下述情形會發送一條WM_GETDLGCODE消息給對話框或窗體內的控件:[2]

  • 確定控件是否會處理特定類型輸入。
  • 確定編輯框控件(edit control)的內容是否被選中,如果用戶按了TAB鍵使得這個編輯框控件收到了輸入焦點(input focus)。
  • 確定按鈕(button)類型。

參數

WM_GETDLGCODE消息的參數的含義:

  • wParam:按鍵輸入的虛擬鍵碼(virtual key)。
  • lParam:MSG數據結構的指針或者為NULL(如果系統執行一個查詢)。

返回碼

每個預定義控件的窗口過程對WM_GETDLGCODE消息返回1個或多個下述值,可用布爾OR運算符組合:

返回碼 解釋
DLGC_BUTTON Control is a button (of any kind).
DLGC_DEFPUSHBUTTON Control is a default push button.
DLGC_HASSETSEL Windows will send an EM_SETSEL message to the control to select its contents.
DLGC_RADIOBUTTON Control is an option (radio) button.
DLGC_STATIC Control is a static control.
DLGC_UNDEFPUSHBUTTON Control is a push button but not the default push button.
DLGC_WANTALLKEYS Control processes all keyboard input.
DLGC_WANTARROWS Control processes arrow keys.
DLGC_WANTCHARS Control processes WM_CHAR messages.
DLGC_WANTMESSAGE Control processes the message in the MSG structure that lParam points to.
DLGC_WANTTAB Control processes the TAB key.

上述返回值也可用於用戶定義控件或者子類化(subclassing)的預定義控件。子類化一個預定義控件,應該先調用預定義控件的窗口過程,然後修改返回碼的必要的位元。

範例

如果控件處理WM_GETDLGCODE消息時返回某個DLGC_WANT位元組,控件將處理指定的消息類型而Windows將對該類型的消息不會做任何默認處理。

例如,下拉列表控件(list box)處理WM_GETDLGCODE消息返回碼包含了DLGC_WANTARROWS位,指示下拉列表控件將會處理方向鍵。如果下拉列表控件有輸入焦點且用戶按下了「向下方向鍵」, Windows發送WM_GETDLGCODE消息給下拉列表控件。由於返回值包含了DLGC_WANTARROWS值, Windows允許下拉列表控件處理方向鍵且作業系統不會做任何處理。如果返回值不包含DLGC_WANTARROWS值, Windows將繼續處理方向鍵並且把輸入焦點轉移為下一個控件。

另一個例子,編輯框控件返回值包含DLGC_WANTCHARS碼而按鈕控件返回值則不包含。因此如果一個按鈕控件有輸入焦點且用戶按下了一個有效的控件助記符(mnemonic character,顯示為控件標籤中的加了底劃線的字母), Windows將設置輸入焦點到該控件上。如果一個編輯框控件有輸入焦點且用戶輸入了一個助記符, Windows不會把輸入焦點改到別的控件因為編輯框控件會自行處理WM_CHAR消息。

一個控件處理WM_GETDLGCODE 消息時,如果返回值包含了DLGC_WANTMESSAGE碼,表明應用程式不希望系統默認處理lParam參數中包含的消息。這些消息可以是WM_KEYDOWN, WM_SYSCHAR, WM_CHAR.

下述代碼示例,對檢查框控件(check box )子類化,處理WM_GETDLGCODE消息,當用戶按下"X"鍵則選中檢查框,如果按下"O"鍵則清除檢查框。

   case WM_GETDLGCODE:
      // Call the check box window procedure first
      lRet = CallWindowProc(lpCheckProc, hWnd, wMessage, wParam,
                            lParam);

      // If lParam points to an MSG structure
      if (lParam)
      {
         lpmsg = (LPMSG)lParam;
         if (lpmsg->message == WM_CHAR)
         {
            if (lpmsg->wParam == 'x' || lpmsg->wParam == 'X')
            {
               // Select the check box when user presses "X"
               SendMessage(hWnd, BM_SETCHECK, TRUE, 0);
               lRet |= DLGC_WANTMESSAGE;
            }
            else if (lpmsg->wParam == 'o' || lpmsg->wParam == 'O')
            {
               // Clear the check box when user presses "O"
               SendMessage(hWnd, BM_SETCHECK, FALSE, 0);
               lRet |= DLGC_WANTMESSAGE;
            }
         }
      }
      return lRet;

上述代碼使得Windows對X, x, O, o字符的WM_CHAR消息不會做進一步處理,因為WM_GETDLGCODE返回值包含了DLGC_WANTMESSAGE碼。上例中,控件返回值也可以用DLGC_WANTCHARS代替DLGC_WANTMESSAGE。

下例代碼子類化編輯框控件,禁止其通過Tab鍵獲得輸入焦點時默認地全部選中編輯框內的文本。

     // In the subclass procedure
   case WM_GETDLGCODE:
      // Call the original edit control window procedure
      lRet = CallWindowProc(lpEditProc, hWnd, wMessage, wParam,
                            lParam);

      // Clear the DLGC_HASSETSEL bit from the return value
      lRet &= ~DLGC_HASSETSEL;

      return lRet;

參考文獻

  1. ^ MSDN:WM_GETDLGCODE message. [2017-03-09]. (原始內容存檔於2017-05-06). 
  2. ^ How To Use the WM_GETDLGCODE Message. [2017-03-09]. (原始內容存檔於2017-05-17).