2009-12-26 7 views
1

J'ai créé un programme Windows GUI en utilisant C et l'API Windows, et je veux que le programme utilise des accélérateurs de clavier. J'ai mis en place des accélérateurs, qui fonctionnent correctement, mais lorsque l'accent est mis sur une fenêtre enfant de la fenêtre principale de mon programme, comme un contrôle de liste ou un contrôle de barre d'état, les raccourcis clavier sont traduits en messages WM_COMMAND pour les fenêtres enfants plutôt que la fenêtre principale. Pour cette raison, ma gestion des messages WM_COMMAND appropriés dans WndProc de la fenêtre principale est ignorée lorsque le focus est sur un contrôle enfant.Accélérateurs de clavier Windows et fenêtres enfants

Comment résoudre ce problème?

Répondre

2

J'ai trouvé la réponse. Les fenêtres enfants de la fenêtre principale doivent être sous-classées afin que les messages WM_COMMAND générés par les raccourcis clavier puissent être interceptés et transmis à la fenêtre parente.

Cela implique de changer la procédure de la fenêtre de la commande à une autre. La procédure alternative gère les messages qui doivent être interceptés en les envoyant à la fenêtre parente. Un pointeur vers la procédure de fenêtre d'origine doit également être stocké quelque part afin que le contrôle puisse fonctionner correctement.

La procédure de fenêtre peut être modifiée en utilisant SetWindowLongPtr avec GWLP_WNDPROC.

Voici un exemple simple de la façon de le faire en stockant un pointeur vers la procédure de fenêtre d'origine de la valeur des données utilisateur du contrôle (GWLP_USERDATA):

Le code pour changer la procédure de fenêtre et stocker la procédure originale GWLP_USERDATA:

SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)WndProc)); 

La procédure de fenêtre d'interception:

static LRESULT CALLBACK WndProc(const HWND hWnd, const UINT message, const WPARAM wParam, const LPARAM lParam) 
{ 
    switch(message) 
    { 
     case WM_COMMAND: 
      SendMessage(GetParent(hWnd), message, wParam, lParam); 
      return 0; 
     default: 
     //Assume that GWLP_USERDATA has been set to the original window procedure. 
      return CallWindowProc((WNDPROC)GetWindowLongPtr(hWnd, GWLP_USERDATA), hWnd, message, wParam, lParam); 
    } 
} 
0

Une autre façon est éviter d'utiliser TranslateAccelerator pour chi fenêtre ld, exemple de code:

if (mainWidget() && msg.hwnd == mainWidget()->hwnd()) { 
      if (TranslateAccelerator(msg.hwnd, hMainAccelTable, &msg)) { 
       continue; 
      } 
     } 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 

si le message ne sont pas les années mainWidget, nous ne TranslateAccelerator pour l'aide de la table d'accélérateur du widget principal.