2017-07-08 2 views
0

Je sous-classe un contrôle et à ce stade je veux y ajouter des raccourcis clavier. Il y en a environ une douzaine définie dans un accelerator table dans la ressource.Comment utiliser la table d'accélération dans un contrôle sous-classé?

Je sais que je peux utiliser ces accélérateurs de l'application principale, en appelant TranslateAccelerator puis TranslateMessage et DispatchMessage de sa boucle principale. Mais puis-je vérifier si la séquence de touches de l'accélérateur est pressée à partir d'une commande sous-classée à partir de WndProc elle-même?

EDIT: En d'autres termes, serait-ce mauvais de faire quelque chose comme ça?

LRESULT CSubclassedWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
{ 
    // TODO: Add your specialized code here and/or call the base class 

    if(message == WM_KEYDOWN || 
     message == WM_CHAR || 
     message == WM_SYSKEYDOWN || 
     message == WM_SYSCHAR) 
    { 
     if(hAccel) 
     { 
      CRect rcThis; 
      this->GetWindowRect(&rcThis); 
      this->ScreenToClient(&rcThis); 
      POINT pnt = {(rcThis.right + rcThis.left)/2, (rcThis.bottom + rcThis.top)/2}; 

      MSG msg = {this->GetSafeHwnd(), message, wParam, lParam, ::GetTickCount(), pnt}; 
      if(::TranslateAccelerator(this->GetSafeHwnd(), hAccel, &msg)) 
      { 
       //Accelerator was recognized and sent as WM_COMMAND message to the same window 
       return 0; 
      } 
     } 
    } 

    switch(message) 
    { 
    case WM_COMMAND: 
     { 
      //Special accelerator commands 
      if(HIWORD(wParam) == 1 && 
       lParam == 0) 
      { 
       //See which command was it 
       switch(LOWORD(wParam)) 
       { 
       case ID_MY_ACCELERATOR_ID1: 
        { 
         //Do work... 
        } 
        return 0; 

       case ID_MY_ACCELERATOR_ID2: 
        { 
         //Do work... 
        } 
        return 0; 
       } 
      } 
     } 
     break; 

    case WM_ERASEBKGND: 
     //process it 
     return TRUE; 
    case WM_PAINT: 
     //process it 
     return TRUE; 
    case WM_KEYDOWN: 
     //process it 
     break; 

    //etc. 
    } 

    return CWnd::WindowProc(message, wParam, lParam); 
} 

Répondre

1

je crois que les contrôles Windows standard utilisent simplement WM_KEYDOWN/CHAR et GetKeyState mais je ne vois pas pourquoi vous ne pouvez pas utiliser TranslateAccelerator.

TranslateAccelerator est à certains égards, mieux parce qu'il sait comment gérer Alt.Gr mais il ignorera également la clé si la souris est capturée (IIRC) donc cela dépend de vos besoins.

Appel TranslateAccelerator sur la fenêtre de niveau supérieur après GetMessage est bien sûr la meilleure option, car il vérifiera le menu de la fenêtre pour voir si la commande est désactivée ...

+0

Merci. Non, ce n'est pas une fenêtre de haut niveau. La fenêtre que je sous-classe est une fenêtre enfant. Partie d'une fenêtre de dialogue. Donc, il n'aura pas un menu de lui-même. La raison pour laquelle je demande est parce que je n'ai jamais vu 'TranslateAccelerator' appelé à partir d'une boucle de message lui-même. – c00000fd

+0

Vous voulez dire jamais vu en dehors de la boucle de message? Je sais que ce n'est pas votre fenêtre de haut niveau, mais il serait préférable que votre fenêtre de haut niveau puisse gérer tous les accélérateurs. – Anders

+0

Ouais. Je voulais dire dans 'WndProc'. – c00000fd