Pergunta

Tanto quanto eu tenho sido capaz de descobrir, o Windows não oferece uma função de API para dizer o aplicativo registrou uma tecla de atalho global (via RegisterHotKey). Eu só pode descobrir que uma tecla de atalho foi registada se RegisterHotKey retorna false, mas não quem "possui" a tecla de atalho.

Na ausência de uma API direta, poderia haver uma forma indireta? Windows mantém o identificador associado a cada atalho registred -. É um pouco irritante que não deve haver nenhuma maneira de começar a esta informação

Exemplo de algo que provavelmente não trabalho: send (simular) um atalho registrado, em seguida, interceptar a mensagem de atalho do Windows irá enviar para o processo que registrou. Primeiro, eu não acho que interceptar a mensagem iria revelar o identificador de janela de destino. Em segundo lugar, mesmo se fosse possível, seria uma coisa má a fazer, já que hotkeys envio provocaria todos os tipos de atividade potencialmente indesejados de vários programas.

Não é nada crítico, mas eu vi frequentes pedidos para tal funcionalidade, e assim me foi vítima de aplicativos que registram as teclas de atalho, mesmo sem divulgá-las em qualquer lugar na interface do usuário ou docs.

(Trabalho em Delphi, e não mais de um aprendiz em WinAPI, por favor, ser gentil.)

Foi útil?

Solução

A sua questão despertou meu interesse, então eu fiz um pouco de escavação e ao mesmo tempo, infelizmente, eu não tenho uma resposta adequada para você, eu pensei que iria partilhar o que tenho.

Eu encontrei este exemplo de criação de gancho de teclado (em Delphi) escrito em 1998, mas é compilable em Delphi 2007 com um par de ajustes.

É uma DLL com uma chamada para SetWindowsHookEx que passa através de uma função de chamada de retorno, que pode então interceptar cursos chaves: Neste caso, é mexer com eles para se divertir, mudando cursor esquerda para a direita, etc. Um aplicativo simples, em seguida, chama o DLL e reporta seus resultados com base em um evento TTimer. Se você estiver interessado eu posso postar o código baseado Delphi 2007.

É bem documentado e comentado e você potencialmente poderia usá-lo como base de trabalhar fora, onde uma tecla está indo. Se você pudesse obter o identificador do aplicativo que enviou os cursos chaves, você pode segui-lo de volta dessa maneira. Com isso pega você seria capaz de obter as informações necessárias com bastante facilidade.

Outros aplicativos têm tentado determinar hotkeys, passando por seus atalhos uma vez que podem conter uma tecla de atalho, que é apenas um outro termo para atalho. No entanto a maioria das aplicações não tendem a definir essa propriedade para que ele possa não voltar muito. Se você está interessado em que a rota, Delphi tem acesso a IShellLink COM interface de que você poderia usar para carregar um atalho a partir e obter a sua tecla de atalho:

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;

Se você tem acesso a Safari Books Online , há um boa seção sobre como trabalhar com atalhos / links de shell no Guia do Borland Delphi 6 do desenvolvedor por Steve Teixeira e Xavier Pacheco. Meu exemplo acima é uma versão massacrado de lá e neste site .

Espero que ajude!

Outras dicas

Uma forma possível é usar o Visual Studio ferramenta Spy ++ .

Tentar dar um presente:

  1. Execute a ferramenta (para mim, é a C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\Tools\spyxx_amd64.exe)
  2. Na barra de menu, selecione Spy -> Mensagens Entrar ... (ou hit Ctrl + M )
  3. Verifique todas as janelas no sistema na adicional do Windows quadro
  4. Alterne para a Mensagens
  5. Clique no Limpar Tudo botão
  6. Selecionar WM_HOTKEY na caixa de listagem, ou cheque Teclado em Grupos Mensagem (se você estiver OK com mais potencial de ruído)
  7. Clique no OK botão
  8. Pressione a tecla de atalho em questão ( Win + R , por exemplo)
  9. Selecione a linha WM_HOTKEY Mensagens (All Windows) janela, clique direito e selecione Propriedades ... no menu de contexto
  10. No Propriedades Mensagem de diálogo, clique no Handle Janela link (este será o identificador para a janela que recebeu a mensagem)
  11. Clique no Sincronizar na Propriedades da Janela de diálogo. Isto irá mostrar a janela na principal Spy ++ treeview janela.
  12. No Propriedades da Janela de diálogo, selecione o Processo
  13. Clique no processo ID link. Isto irá mostrar o processo (Na minha Win + R caso: EXPLORER)

Depois de algumas pesquisas, parece que você precisa ter acesso à estrutura interna que MS usa para armazenar as hotkeys. ReactOS tem uma implementação de sala limpa que implementa a chamada GetHotKey por iteração uma lista interna e extrair a tecla de atalho que corresponde aos parâmetros para a chamada.

Dependendo de como a implementação 'ReactOS perto é a implementação MS, você pode ser capaz de fuçar na memória para encontrar a estrutura, mas isso é mais minha cabeça ...

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;
}

Presumo esta discussão sobre sysinternals foi perguntado por alguém relacionado com este pergunta, mas eu pensei que eu ia ligar para ele de qualquer maneira para manter os dois juntos. Os olhares de rosca muito intrigante, mas eu suspeito que alguns espeleologia mergulho profundo que precisa acontecer para descobrir isso sem acesso aos componentes internos do MS.

Em cima da minha cabeça, você pode tentar enumerar todas as janelas com EnumWindows, então no retorno de chamada, envio WM_GETHOTKEY a cada janela.

Edit: apparrently eu estava errado sobre isso. MSDN tem mais informações:

WM_HOTKEY não está relacionado com a teclas de atalho WM_SETHOTKEY WM_GETHOTKEY e. A mensagem WM_HOTKEY é enviado para as teclas de atalho genéricos enquanto as mensagens WM_SETHOTKEY e WM_GETHOTKEY relacionar com as teclas de atalho de ativação janela.

Nota: Aqui é um supostamente programa para ter a funcionalidade que você está procurando. Você poderia tentar Decompiling-lo.

Outro segmento menciona um NT gancho de teclado nível global:

Reatribuir / override atalho (Win + L) para janelas de bloqueio

talvez você pode obter o identificador do processo que chamou o gancho dessa forma, que você pode então resolver para o nome do processo

(disclaimer: Eu tive isso em meus favoritos, não têm realmente tentou / testado)

Eu sei que você pode interceptar o fluxo de mensagens em qualquer janela dentro de seu próprio processo - o que costumávamos chamar subclasse em VB6. (Embora eu não me lembro a função, talvez SetWindowLong?) Não tenho a certeza se você pode fazer isso por janelas fora do seu próprio processo. Mas por causa deste post vamos supor que você encontrar uma maneira de fazer isso. Então você pode simplesmente interceptar as mensagens para todas as janelas de nível superior, Monitor para a mensagem WM_HOTKEY. Você não seria capaz de conhecer todas as teclas direita fora do bastão, mas como eles foram pressionados você pode facilmente descobrir o que aplicação foi usá-los. Se você persistiu seus resultados em disco e recarregado cada vez que seu aplicativo de monitoramento foi executado você pode aumentar o desempenho de sua aplicação ao longo do tempo.

Isto não exatamente responder à parte da pergunta que está prestes a API do Windows, mas ele responde a parte da pergunta que é sobre uma lista de hotkeys globais e as aplicações que "próprios"-los.

A livre Hotkey Explorer em http://hkcmdr.anymania.com/ mostra uma lista de todas mundial hotkeys e as aplicações que os possuem. Isso só me ajudou a descobrir por que uma tecla de atalho específico do aplicativo parou de funcionar e como corrigi-lo (por reconfigurar a tecla de atalho mundial registrada no aplicativo que tinha registado), dentro de alguns segundos.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top