1

Тема: AHK: Не перехватывает глобальные клавиши если текущее окно зависло

Заметил, что скрипт (v1.1) перестает перехватывать глобальные клавиши (из раздела #IfWinActive, т.е., не относящиеся ни к какому окну или приложению), если текущее окно - зависшее (т.е., в заголовке текст "... (Не отвечает)"). Возможно ли это исправить и как?

Если негде взять зависшее окно для проверки, приложил исходник на FPC+WinApi (должно скомпилиться и на Delphi) - пустое не отвечающее окно (сделать такое на AHK не получилось).

2 (изменено: delpher, 2025-05-09 19:31:15)

Re: AHK: Не перехватывает глобальные клавиши если текущее окно зависло

Что-то файлик не приложился.

program Hang_App;

{$mode Delphi}
{$H+}

uses
  Windows, Messages;

const
  WinClassName = 'MainWindow';
  WinCaption = 'Hang App';

var
  hWndMain: HWND;

// Процедура обработки сообщений
function WndProc(hWnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
  Result := DefWindowProc(hWnd, Msg, wParam, lParam);
end;


function RegisterWindowClass: Boolean;
var
  wc: WNDCLASSEX;
begin
  wc.cbSize := SizeOf(WNDCLASSEX);
  wc.style := CS_HREDRAW or CS_VREDRAW;
  wc.lpfnWndProc := @WndProc;
  wc.cbClsExtra := 0;
  wc.cbWndExtra := 0;
  wc.hInstance := hInstance;
  wc.hIcon := LoadIcon(0, IDI_APPLICATION);
  wc.hCursor := LoadCursor(0, IDC_ARROW);
  wc.hbrBackground := COLOR_BTNFACE + 1;
  wc.lpszMenuName := nil;
  wc.lpszClassName := WinClassName;
  wc.hIconSm := LoadIcon(0, IDI_APPLICATION);

  Result := RegisterClassEx(@wc) <> 0;
end;


var
  hWndClass: WNDCLASSEX;
  nMsg: MSG;
  Rect: TRect;

begin
  if not RegisterWindowClass then
  begin
    MessageBox(0, 'Ошибка регистрации класса окна!', 'Ошибка', MB_ICONERROR);
    Exit;
  end;

  // Создание главного окна
  hWndMain := CreateWindowEx(0, WinClassName, PChar(WinCaption), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 400, 200, 0, 0, hInstance, nil);
  if hWndMain = 0 then
  begin
    MessageBox(0, 'Не удалось создать окно', 'Ошибка', MB_ICONERROR);
    Exit;
  end;

  // Центрирование окна
  GetWindowRect(hWndMain, Rect);
  SetWindowPos(hWndMain, 0, (GetSystemMetrics(SM_CXSCREEN) - Rect.Width) div 2, (GetSystemMetrics(SM_CYSCREEN) - Rect.Height) div 2, 0, 0, SWP_NOZORDER or SWP_NOSIZE);

  ShowWindow(hWndMain, SW_SHOW);
  UpdateWindow(hWndMain);

  while GetMessage(nMsg, 0, 0, 0) do
  begin
    if not IsDialogMessage(hWndMain, nMsg) then
    begin
      TranslateMessage(nMsg);
      DispatchMessage(nMsg);
      Sleep(24*60*60*1000);
    end;
  end;
end.

3

Re: AHK: Не перехватывает глобальные клавиши если текущее окно зависло

Не тестировал, но первое, что приходит в голову, попробовать #UseHook.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

4

Re: AHK: Не перехватывает глобальные клавиши если текущее окно зависло

teadrinker
Скрипт изначально был в режиме #UseHook On, поменял на Off - не помогло.

5

Re: AHK: Не перехватывает глобальные клавиши если текущее окно зависло

Я протестировал на таком окне:

Gui, Show, w300 h300
DllCall("SuspendThread", "Ptr", DllCall("GetCurrentThread"))

Горячая клавиша в другом скипте

#IfWinActive
^1:: MsgBox test

работает.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

6

Re: AHK: Не перехватывает глобальные клавиши если текущее окно зависло

Хм. Не ожидал, что результат будет зависеть от того, какая комбинация перехватывается. У меня используется комбинация Win+Space. В режиме #UseHook On никакая комбинация при зависшем окне не срабатывает, но при #UseHook Off в зависшем окне срабатывает Ctrl+1, но все равно не срабатывает Win+Space.

#Requires AutoHotkey v1.1
#SingleInstance Force
#UseHook Off

#IfWinActive
#Space::Msgbox, Win+Space
^1::Msgbox, Ctrl+1

Похоже, это по причине, что существуют "hotkeys not supported by RegisterHotkey (which is a function built into the operating system)" - они всегда перехватываются через hook. Win+Space как раз встроенная комбинация OS.


И есть второй момент - если комбинация в секции #IfWinNotActive, то в зависшем окне перестает срабатывать и Ctrl+1 тоже.

#Requires AutoHotkey v1.1
#SingleInstance Force
#UseHook Off

#IfWinNotActive ahk_class TscShellContainerClass
#Space::Msgbox, Win+Space
^1::Msgbox, Ctrl+1

7 (изменено: delpher, 2025-05-11 01:49:42)

Re: AHK: Не перехватывает глобальные клавиши если текущее окно зависло

Любопытно. Стоило запустить скрипт из-под аккаунта System (командой psexec -s -i -d), как все комбинации начали перехватываться без проблем. Даже в секции #IfWinNotActive. Похоже, просто из-под администратора ему не хватало прав на системные комбинации, но вот почему была разница между секциями #IfWinNotActive и #IfWinActive, это непонятно.