132 votes

Savoir quel processus inscrit un hotkey global ? (API Windows)

Aussi loin que j'ai pu trouver, Windows n'offre pas une fonction de l'API de dire ce que l'application a enregistré une touche d'accès rapide (via RegisterHotkey). Je ne peux trouver qu'un raccourci est enregistré si RegisterHotkey retourne false, mais pas le "propriétaire" de la touche de raccourci.

En l'absence d'une relation directe de l'API, pourrait-il y être une façon détournée? Windows conserve la poignée associée à chaque inscrit de raccourci - c'est un peu affolant qu'il devrait y avoir aucun moyen d'obtenir cette information.

Exemple de quelque chose qui n'y aurait probablement pas de travail: envoyer (simuler) un régime enregistré d'raccourci, puis intercepter la touche message Windows envoie le processus qui l'a enregistré. Tout d'abord, je ne pense pas que intercepter le message pourrait révéler la destination la poignée de la fenêtre. Deuxièmement, même si c'était possible, ce serait une mauvaise chose à faire, depuis l'envoi de touches de raccourci pourrait déclencher toutes sortes de potentiellement indésirables de l'activité de divers programmes.

Il n'a rien de critique, mais j'ai vu souvent de demandes de fonctionnalités, et l'ai moi-même été victime d'une des applications de ce registre, les raccourcis sans même communiquer n'importe où dans l'INTERFACE utilisateur ou des documents.

(Travail en Delphi, et pas plus qu'un apprenti à la WinAPI, s'il vous plaît être gentil.)

21voto

Pauk Points 1815

Votre question a piqué mon intérêt, j'ai donc fait un peu de creuser et de tout, malheureusement je n'ai pas de bonne réponse pour vous, je pensais que je voudrais partager ce que j'ai.

J'ai trouvé cet exemple de création de hook clavier (en Delphi) écrit en 1998, mais il est compilable en Delphi 2007 avec un couple de réglages.

C'est une DLL avec un appel à l' SetWindowsHookEx qui passe à travers une fonction de rappel, qui peut alors intercepter les frappes de touche: Dans ce cas, c'est bricoler avec eux pour s'amuser, changer de curseur de gauche à droite, etc. Une application simple, puis appelle la DLL et rend compte de ses résultats sur la base d'un TTimer événement. Si vous êtes intéressé, je peux poster le Delphi 2007 en fonction du code.

Il est bien documenté et commenté et vous pourriez l'utiliser comme une base de travail où une touche est en cours. Si vous pouviez obtenir le descripteur de l'application qui a envoyé les frappes de touche, vous pouvez retrouver de cette façon. Avec cette poignée vous seriez en mesure d'obtenir les informations dont vous avez besoin assez facilement.

D'autres applications ont essayé de déterminer raccourcis en passant par leurs Raccourcis, car ils peuvent contenir une touche de Raccourci, qui est juste un autre terme pour la touche de raccourci. Cependant, la plupart des applications n'ont pas tendance à définir cette propriété de sorte qu'il pourrait ne pas revenir beaucoup. Si vous êtes intéressé par cette route, Delphi a accès à l' IShellLink COM interface qui vous pouvez utiliser pour charger un raccourci vers le haut et d'obtenir sa touche de raccourci:

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 Livres en Ligne, il y a un bon article sur le travail avec les raccourcis / liens shell dans le Borland Delphi 6 Guide du Développeur par Steve Teixeira et Xavier Pacheco. Mon exemple ci-dessus est une boucherie version à partir de là et de ce site.

Espérons que ça aide!

11voto

John Weldon Points 19132

Après quelques recherches, il semble que vous auriez besoin pour obtenir l'accès à la structure interne que MS utilise pour stocker les touches de raccourci. ReactOS a un nettoyage de la salle de mise en œuvre qui implémente l' GetHotKey appel par itération d'une liste interne et de l'extraction de la touche qui correspond aux paramètres de l'appel.

Selon ReactOS de mise en œuvre de la MS de la mise en œuvre, vous pourriez être en mesure de fouiller dans la mémoire de 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 présume que ce fil de discussion sur sysinternals a été demandé par une personne liée à cette question, mais je pensais le lien de toute façon à maintenir les deux ensemble. Le fil a l'air très intéressant, mais je soupçonne que certains de profondeur de plongée spéléo devra arriver à ce chiffre, sans accès à la MS internes.

3voto

David Points 2131

Sur le dessus de ma tête, vous pouvez essayer de les é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 a plus d'informations:

WM_HOTKEY est pas liée à l'WM_GETHOTKEY et WM_SETHOTKEY touches de raccourci. Le WM_HOTKEY message est envoyé pour le générique de touches de raccourci, tandis que le WM_SETHOTKEY et WM_GETHOTKEY messages se rapportent à la fenêtre d'activation de touches de raccourci.

Remarque: Ici est un programme visant à la fonctionnalité que vous recherchez. Vous pouvez essayer de décompilation.

2voto

Caveatrob Points 2504

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

1voto

Marco van de Voort Points 15378

Un autre thread mentionne un crochet de niveau clavier NT global :

http://StackOverflow.com/questions/301053/Re-assign-override-Hotkey-Win-l-to-Lock-Windows

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

(disclaimer : J’ai eu dans mes favoris, n’ont pas vraiment essayé/testé)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X