Question

Pour autant que je sache, Windows ne propose pas de fonction API permettant de savoir quelle application a enregistré un raccourci clavier global (via RegisterHotkey). Je peux seulement découvrir qu'un raccourci clavier est enregistré si RegisterHotkey renvoie false, mais pas qui est le propriétaire de " le raccourci clavier.

En l'absence d'une API directe, pourrait-il y avoir un moyen détourné? Windows conserve le descripteur associé à chaque touche de raccourci enregistrée. Il est un peu déconcertant de constater qu’il ne devrait y avoir aucun moyen d’obtenir ces informations.

Exemple de quelque chose qui ne fonctionnerait probablement pas: envoyez (simulez) un raccourci clavier enregistré, puis interceptez le message de raccourci clavier que Windows enverra au processus qui l'a enregistré. Premièrement, je ne pense pas que l’interception du message révélerait le handle de la fenêtre de destination. Deuxièmement, même si cela était possible, ce serait une mauvaise chose à faire, car l’envoi de raccourcis clavier déclencherait toutes sortes d’activités potentiellement indésirables de la part de divers programmes.

Cela n’a rien de critique, mais j’ai souvent été confronté à de telles fonctionnalités, et j’ai moi-même été victime d’applications qui enregistrent des raccourcis clavier sans même les divulguer dans l’interface utilisateur ou la documentation.

(Travaillant à Delphi et pas plus qu’un apprenti chez WinAPI, soyez gentil, s'il vous plaît.)

Était-ce utile?

La solution

Votre question a piqué mon intérêt, alors j’ai creusé un peu et bien que, malheureusement, je n’ai pas de réponse à vous donner, j’ai pensé partager ce que j’avais.

J'ai trouvé cet exemple de création d'un clavier accroché au clavier (en Delphi) écrit en 1998, mais compilable dans Delphi 2007 avec quelques modifications.

C’est une DLL avec un appel à SetWindowsHookEx qui passe par une fonction de rappel, qui peut alors intercepter les frappes de touche: dans ce cas, bricoler avec elles pour le plaisir, changer le curseur de gauche à droite, etc. Une application simple appelle ensuite la DLL et rend compte de ses résultats en fonction d'un événement TTimer. Si cela vous intéresse, je peux publier le code basé sur Delphi 2007.

Il est bien documenté et commenté, et vous pourriez éventuellement l’utiliser comme base de travail pour déterminer le sens de la frappe. Si vous pouviez obtenir le descripteur de l'application qui a envoyé les touches, vous pouvez le suivre de cette façon. Avec cette poignée, vous pourrez obtenir assez facilement les informations dont vous avez besoin.

D'autres applications ont essayé de déterminer les touches de raccourci en passant par leurs raccourcis puisqu'elles peuvent contenir une touche de raccourci, qui est simplement un autre terme pour les touches de raccourci. Cependant, la plupart des applications n’ont pas tendance à définir cette propriété, elle risque donc de ne pas retourner beaucoup. Si cette route vous intéresse, Delphi a accès à l'interface COM IShellLink à partir de laquelle vous pouvez utiliser pour charger un raccourci et obtenir son raccourci clavier:

uses ShlObj, ComObj, ShellAPI, ActiveX, CommCtrl;

procedure GetShellLinkHotKey;
var
  LinkFile : WideString;
  SL: IShellLink;
  PF: IPersistFile;

  HotKey : Word;
  HotKeyMod: Byte;
  HotKeyText : string;
begin
  LinkFile := 'C:\Temp\Temp.lnk';

  OleCheck(CoCreateInstance(CLSID_ShellLink, nil, CLSCTX_INPROC_SERVER, IShellLink, SL));

  // The IShellLink implementer must also support the IPersistFile
  // interface. Get an interface pointer to it.
  PF := SL as IPersistFile;

  // Load file into IPersistFile object
  OleCheck(PF.Load(PWideChar(LinkFile), STGM_READ));

  // Resolve the link by calling the Resolve interface function.
  OleCheck(SL.Resolve(0, SLR_ANY_MATCH or SLR_NO_UI));

  // Get hotkey info
  OleCheck(SL.GetHotKey(HotKey));

  // Extract the HotKey and Modifier properties.
  HotKeyText := '';
  HotKeyMod := Hi(HotKey);

  if (HotKeyMod and HOTKEYF_ALT) = HOTKEYF_ALT then
    HotKeyText := 'ALT+';
  if (HotKeyMod and HOTKEYF_CONTROL) = HOTKEYF_CONTROL then
    HotKeyText := HotKeyText + 'CTRL+';
  if (HotKeyMod and HOTKEYF_SHIFT) = HOTKEYF_SHIFT then
    HotKeyText := HotKeyText + 'SHIFT+';
  if (HotKeyMod and HOTKEYF_EXT) = HOTKEYF_EXT then
    HotKeyText := HotKeyText + 'Extended+';

  HotKeyText := HotKeyText + Char(Lo(HotKey));

  if (HotKeyText = '') or (HotKeyText = #0) then
    HotKeyText := 'None';

  ShowMessage('Shortcut Key - ' + HotKeyText);
end;

Si vous avez accès à Safari Books Online , il existe un bonne section sur l'utilisation des liens de raccourci / shell dans le Guide du développeur de Borland Delphi 6 par Steve Teixeira et Xavier Pacheco. Mon exemple ci-dessus est une version bouchée de cet endroit et ce site .

J'espère que ça aide!

Autres conseils

Une solution possible consiste à utiliser le Outil Visual Studio Spy ++ .

Essayez ceci:

  1. Exécutez l'outil (pour moi, il se trouve dans C: \ Program Files (x86) \ Microsoft Visual Studio \ 2017 \ Communauté \ Common7 \ Tools \ spyxx_amd64.exe )
  2. Dans la barre de menus, sélectionnez Espion - > Journaliser les messages ... (ou appuyer sur Ctrl + M )
  3. Cochez Toutes les fenêtres du système dans le cadre Fenêtres supplémentaires
  4. Passez à l'onglet Messages
  5. Cliquez sur le bouton Tout effacer
  6. Sélectionnez WM_HOTKEY dans la liste, ou cochez Clavier dans Groupes de messages (si vous êtes d'accord avec davantage de bruit potentiel)
  7. Cliquez sur le bouton OK
  8. Appuyez sur la touche de raccourci en question ( Win + R , par exemple)
  9. Sélectionnez la ligne WM_HOTKEY dans la fenêtre Messages (toutes les fenêtres) , cliquez avec le bouton droit de la souris et sélectionnez Propriétés ... dans le menu contextuel.
  10. Dans la boîte de dialogue Propriétés du message , cliquez sur le lien Poignée de la fenêtre (il s'agira de la poignée de la fenêtre ayant reçu le message)
  11. Cliquez sur le bouton Synchroniser dans la boîte de dialogue Propriétés de la fenêtre . Ceci affichera la fenêtre dans l'arborescence principale de la fenêtre de Spy ++.
  12. Dans la boîte de dialogue Propriétés de la fenêtre , sélectionnez l'onglet Process
  13. .
  14. Cliquez sur le lien ID de processus . Cela vous montrera le processus (Dans mon Win + R : EXPLORER )

Après quelques recherches, il semble que vous deviez avoir accès à la structure interne utilisée par MS pour stocker les raccourcis clavier. ReactOS a une implémentation de salle blanche qui implémente l'appel GetHotKey en itérant une liste interne et en extrayant le raccourci clavier correspondant aux paramètres de l'appel.

En fonction de la proximité entre l'implémentation de ReactOS et celle de MS, vous pourrez peut-être fouiller dans la mémoire pour trouver la structure, mais c'est au-dessus de ma tête ...

BOOL FASTCALL
GetHotKey (UINT fsModifiers,
           UINT vk,
           struct _ETHREAD **Thread,
           HWND *hWnd,
           int *id)
{
   PHOT_KEY_ITEM HotKeyItem;

   LIST_FOR_EACH(HotKeyItem, &gHotkeyList, HOT_KEY_ITEM, ListEntry)
   {
      if (HotKeyItem->fsModifiers == fsModifiers &&
            HotKeyItem->vk == vk)
      {
         if (Thread != NULL)
            *Thread = HotKeyItem->Thread;

         if (hWnd != NULL)
            *hWnd = HotKeyItem->hWnd;

         if (id != NULL)
            *id = HotKeyItem->id;

         return TRUE;
      }
   }

   return FALSE;
}

Je suppose que ce fil sur sysinternals a été demandé par un proche de cette question question, mais je pensais que je lierais quand même pour garder les deux ensemble. Le fil semble très intriguant, mais je soupçonne qu’il faudrait une certaine spéléologie en plongée profonde pour résoudre ce problème sans avoir accès aux ressources internes de la SEP.

De mémoire, vous pouvez essayer d’énumérer toutes les fenêtres avec EnumWindows, puis, dans le rappel, envoyer WM_GETHOTKEY à chaque fenêtre.

Edit: Apparemment, je me suis trompé à ce sujet. MSDN contient davantage d'informations:

  

WM_HOTKEY n'a aucun lien avec les touches d'activation WM_GETHOTKEY et WM_SETHOTKEY. Le message WM_HOTKEY est envoyé pour les raccourcis clavier génériques, tandis que les messages WM_SETHOTKEY et WM_GETHOTKEY se rapportent aux raccourcis clavier d’activation de la fenêtre.

Remarque: Voici un programme censé avoir la fonctionnalité Tu recherches. Vous pouvez essayer de le décompiler.

Cela semble vous en dire beaucoup: http://hkcmdr.anymania.com/help.html

Un autre thread mentionne un raccordement de clavier global au niveau NT:

Réattribution / remplacement du raccourci clavier (Win + L) verrouiller les fenêtres

peut-être que vous pouvez obtenir le descriptif du processus qui appelle le hook de cette façon, que vous pouvez ensuite résoudre en nom de processus

(disclaimer: je l'avais dans mes favoris, je n'ai pas vraiment essayé / testé)

Je sais que vous pouvez intercepter le flux de messages dans n’importe quelle fenêtre de votre propre processus - ce que nous appelions sous-classement dans VB6. (Bien que je ne me souvienne pas de la fonction, peut-être SetWindowLong?) Je ne sais pas si vous pouvez le faire pour les fenêtres en dehors de votre propre processus. Mais pour le bien de cet article, supposons que vous trouviez un moyen de le faire. Ensuite, vous pouvez simplement intercepter les messages pour toutes les fenêtres de niveau supérieur, surveiller le message WM_HOTKEY. Vous ne pourrez pas connaître toutes les touches dès le départ, mais comme elles sont enfoncées, vous pouvez facilement déterminer quelle application les utilise. Si vous persistiez sur le disque et que vous rechargiez vos résultats à chaque exécution de votre application de surveillance, vous pourriez augmenter les performances de celle-ci au fil du temps.

Cela ne répond pas exactement à la partie de la question relative à l'API Windows, mais à la partie de la question relative à une liste de raccourcis clavier globaux et aux applications qui "possèdent" les "propres". leur.

L’explorateur de raccourcis gratuit sur http://hkcmdr.anymania.com/ affiche la liste de tous les événements mondiaux. raccourcis clavier et les applications qui les possèdent. Cela m'a aidé à comprendre pourquoi une touche de raccourci spécifique à une application a cessé de fonctionner et comment la réparer (en reconfigurant le raccourci clavier global enregistré dans l'application qui l'a enregistrée), en quelques secondes.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top