Zdarzenia i komunikaty
3.08.1999
  • Odbieranie komunikatów naciśnięcia TAB i klawiszy kursora.

       Czy kiedykolwiek próbowałeś odpowiadać na naciśnięcie klawisza TAB poprzez handler OnKeyPress? Odkryłeś więc prawdopodobnie, że metoda ta nie skutkuje, przynajmniej dla większości kontrolek. Problem tkwi w tym, że Windows wysyła komunikat o naciśnięciu TAB jedynie do tych kontrolek, które sobie tego zażyczą. To samo tyczy się klawiszy kursora. Więc jak system operacyjny dowiaduje się która kontrolka chce otrzymywać komunikat od klawisza TAB? System operacyjny wysyła komunikat WM_GETDLGCODE do aktywnej kontrolki, żeby zapytać, które klawisze chce ona odbierać. Zwracana wartość determinuje, które naciśnięcia klawiszy zostaną wysłane do kontrolki. Zwracana wartość może być kombinacją następujących wartości:

DLGC_BUTTON 
DLGC_DEFPUSHBUTTON 
DLGC_HASSETSEL 
DLGC_RADIOBUTTON 
DLGC_STATIC 
DLGC_UNDEFPUSHBUTTON 
DLGC_WANTALLKEYS 
DLGC_WANTARROWS 
DLGC_WANTCHARS 
DLGC_WANTMESSAGE 
DLGC_WANTTAB
      Żeby otrzymywać naciśnięcie TAB, kontrolka musi zwracać DLGC_WANTTAB, klawisze kursora - DLGC_WANTARROWS, klawisze kursora i TAB - DLGC_WANTARROWS | DLGC_WANTTAB, zaś dla wszystkich klawiszy - DLGC_WANTALLKEYS.

      VCL zawiera wiele przykładów wykorzystania komunikatu WM_GETDLGCODE. TToolBar odpowiada na klawisze kursora, TCustomGrid na TAB i klawisze kursora, zaś TMediaPlayer i TDBNavigator na klawisze kursora. Poniżej kilka fragmentów kodu VCL przetłumaczonych na C++ dla lepszej czytelności.
void __fastcall TToolBar::WMGetDlgCode(TMessage & Message)
{
    // tylko czasem klawisze kursora
    if(FInMenuLoop)
        Message.Result = DLGC_WANTARROWS;
}

void __fastcall TCustomGrid::WMGetDlgCode(TMessage & Message)
{
    // zawsze klawisze kursora
    Msg.Result := DLGC_WANTARROWS;
    ...

    // czasem klawisz TAB
    if (Options.Contains(goTabs))
        Msg.Result |= DLGC_WANTTAB;

    // czasem komunikat WM_CHAR
    if (Options.Contains(goEditing))
        Msg.Result |= DLGC_WANTCHARS;
}

void __fastcall TMediaPlayer::WMGetDlgCode(TMessage &Message)
{
    Message.Result = DLGC_WANTARROWS;
}

Uwaga: Nie twórz handlera WM_GETDLGCODE dla formy. Musisz napisać ten handler na poziomie kontrolki.