Узнайте, какой процесс зарегистрировал глобальную горячую клавишу? (Windows API)

В настоящее время нет никаких генериков в go http://golang.org/doc/faq#generics .

Предполагается, что он выйдет в версии 2.0, отзывы о дженериках в черновой версии можно посмотреть здесь: https://github.com/golang/go/wiki/Go2GenericsFeedback

105
задан Marek Jedliński 6 May 2009 в 20:27
поделиться

5 ответов

Ваш вопрос вызвал у меня интерес, поэтому я немного покопался и, хотя, к сожалению, у меня нет для вас правильного ответа, я решил поделиться тем, что у меня есть.

Я нашел этот пример создания клавиатуры (в Delphi) , написанный в 1998 году, но его можно скомпилировать в Delphi 2007 с парой настроек.

Это DLL с вызовом SetWindowsHookEx , которая проходит через функцию обратного вызова, которая затем может перехватывать нажатия клавиш: в этом случае она возится с ними для развлечения, меняет левый курсор вправо и т. Д. Затем простое приложение вызывает DLL и сообщает о своих результатах на основе события TTimer. Если вам интересно, я могу опубликовать код на основе Delphi 2007.

It ' он хорошо задокументирован и прокомментирован, и вы потенциально можете использовать его как основу для определения того, где происходит нажатие клавиши. Если бы вы могли получить дескриптор приложения, отправляющего нажатия клавиш, вы могли бы отследить его таким образом. С этим дескриптором вы сможете довольно легко получить необходимую информацию.

Другие приложения пытались определять горячие клавиши, просматривая свои ярлыки, поскольку они могут содержать горячую клавишу, что является просто другим термином для горячих клавиш. Однако большинство приложений не склонны устанавливать это свойство, поэтому оно может не возвращать много. Если вас интересует этот маршрут, Delphi имеет доступ к IShellLink COM-интерфейсу, который вы можете использовать для загрузки ярлыка и получения его горячей клавиши:

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;

Если у вас есть доступ к Safari Книги в Интернете , в Руководстве разработчика Borland Delphi 6 Стива Тейшейры и Ксавьера Пачеко есть хороший раздел о работе с ярлыками / ссылками на оболочку . Мой пример выше - это забитая версия оттуда и этот сайт .

Надеюсь, что это поможет!

19
ответ дан 24 November 2019 в 04:02
поделиться

Другой поток упоминает глобальный хук клавиатуры уровня NT:

Переназначить / переопределить горячую клавишу (Win + L) для блокировки окон

, возможно, вы можете получить дескриптор процесса, который назвал этот метод «ловушкой», который затем можно преобразовать в имя процесса

(заявление об отказе: оно было в моих закладках, на самом деле не пробовал / не проверял)

1
ответ дан 24 November 2019 в 04:02
поделиться

После некоторого исследования выяснилось, что вам понадобится доступ к внутренней структуре, которую MS использует для хранения горячих клавиш. ReactOS имеет реализацию «чистой комнаты», которая реализует вызов GetHotKey путем повторения внутреннего списка и извлечения горячей клавиши, которая соответствует параметрам вызова.

В зависимости от того, насколько реализация ReactOS близка к реализации MS, вы можете покопаться в памяти, чтобы найти структуру, но это выше моей головы ...

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

Я полагаю, эта ветка на sysinternals была задана кем-то, имеющим отношение к этому вопросу, но я думал, что я ' d, чтобы сохранить их вместе. Тема выглядит очень интригующе, но я подозреваю, что потребуется некоторое глубокое исследование, чтобы понять это без доступа к внутренним компонентам MS.

9
ответ дан 24 November 2019 в 04:02
поделиться

Я знаю, что вы можете перехватить поток сообщений в любом окне вашего собственного процесса - то, что мы использовали для вызова подклассов в VB6. (Хотя я не помню эту функцию, возможно, SetWindowLong?) Я не уверен, что вы можете сделать это для окон вне вашего собственного процесса. Но ради этого поста предположим, что вы найдете способ сделать это. Затем вы можете просто перехватить сообщения для всех окон верхнего уровня, отслеживать сообщение WM_HOTKEY. Вы не сможете узнать все клавиши сразу, но по мере их нажатия можно легко определить, какое приложение их использует. Если вы сохраняете результаты на диске и перезагружаете их каждый раз при запуске приложения монитора, вы можете со временем повысить производительность своего приложения.

0
ответ дан 24 November 2019 в 04:02
поделиться

Вне всяких сомнений, вы можете попробовать перечислить все окна с помощью EnumWindows, а затем в обратном вызове отправить WM_GETHOTKEY каждому окну.

Редактировать: Очевидно, я ошибался в этом. MSDN содержит дополнительную информацию:

WM_HOTKEY не имеет отношения к горячим клавишам WM_GETHOTKEY и WM_SETHOTKEY. Сообщение WM_HOTKEY отправляется для общих горячих клавиш, в то время как сообщения WM_SETHOTKEY и WM_GETHOTKEY относятся к горячим клавишам активации окна.

Примечание: Здесь - программа, претендующая на функциональность, которую вы ищете. Вы можете попробовать его декомпилировать.

3
ответ дан 24 November 2019 в 04:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: