Как подключиться к WH_KEYBOARD для PopupList.Window?

Мне нужно знать, нажата ли F11, когда PopupMenu TrayIcon открыт и завершает программу. Не хочу RegisterHotKey. В документации указано, что «PopupList.Window предоставляет доступ к дескриптору окна скрытого окна, которое обрабатывает сообщения всплывающего меню». Итак, мой план состоит в том, чтобы перехватывать сообщения клавиатуры в этом окне, но вместо этого происходит следующее:

Project Project2.exe поднял класс исключений $C0000005 с сообщением «нарушение доступа по адресу 0x00020003: запись адреса 0x2014fd38».
unit Unit2;

interface

uses
    Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
    Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ImgList, Vcl.Menus, Vcl.ExtCtrls;

type
    TForm2 = class(TForm)
        TrayIcon1: TTrayIcon;
        PopupMenu1: TPopupMenu;
        N11: TMenuItem;
        N21: TMenuItem;
        ImageList1: TImageList;
        procedure PopupMenu1Popup(Sender: TObject);
private
    function hook(code: Integer; w: WPARAM; p : LPARAM): Lresult stdcall;
public
    { Public declarations }
end;

var
    Form2: TForm2;
    HookID: hhook;
implementation

{$R *.dfm}
function TForm2.hook(code: Integer; w: WPARAM; p: LPARAM): Lresult stdcall;
begin
    if code < 0 then
    begin
        Result := CallNextHookEx(0, code, w, p);
        Exit;
    end;

    Result := CallNextHookEx(0, code, w, p);
end;

procedure TForm2.PopupMenu1Popup(Sender: TObject);
begin
    HookID := SetWindowsHookEx(WH_KEYBOARD, @TForm2.hook, 0,
        GetWindowThreadProcessId(PopupList.Window, nil));
end;

end.

Тело вашего крючка можно упростить до Result := CallNextHookEx(0, code, w, p);

Andreas Rejbrand 20.02.2023 11:15
SetWindowsHookEx() — не лучший способ перехватывать сообщения клавиатуры, отправляемые во всплывающее меню. Просто создайте подкласс самого PopupList.Window, используя SetWindowSubclass() или SetWindowLongPtr(). Или лучше просто замените объект PopupList на пользовательский объект, который переопределяет метод TPopupList.WndProc().
Remy Lebeau 20.02.2023 19:34
Запуск PHP на IIS без использования программы установки веб-платформы
Запуск PHP на IIS без использования программы установки веб-платформы
Установщик веб-платформы, предлагаемый компанией Microsoft, перестанет работать 31 декабря 2022 года. Его закрытие привело к тому, что мы не можем...
Оптимизация React Context шаг за шагом в 4 примерах
Оптимизация React Context шаг за шагом в 4 примерах
При использовании компонентов React в сочетании с Context вы можете оптимизировать рендеринг, обернув ваш компонент React в React.memo сразу после...
Библиотека для работы с мороженым
Библиотека для работы с мороженым
Лично я попрощался с операторами print() в python. Без шуток.
Настройка шаблона Metronic с помощью Webpack и Gulp
Настройка шаблона Metronic с помощью Webpack и Gulp
Я пишу эту статью, чтобы поделиться тем, как настроить макет Metronic с помощью Sass, поскольку Metronic предоставляет так много документации, и они...
Уроки CSS 6
Уроки CSS 6
Здравствуйте дорогие читатели, я Ферди Сефа Дюзгюн, сегодня мы продолжим с вами уроки css. Сегодня мы снова продолжим с так называемых классов.
Что такое Css? Для чего он используется?
Что такое Css? Для чего он используется?
CSS, или "Каскадные таблицы стилей", - это язык стилей, используемый в веб-страницах. CSS является одним из основных инструментов веб-разработки...
0
2
77
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ваша функция ловушки является методом TForm2 и поэтому имеет дополнительный (скрытый) параметр self. Вы должны разместить функцию вне TForm2:

    TForm2 = class(TForm)
        TrayIcon1: TTrayIcon;
        PopupMenu1: TPopupMenu;
        N11: TMenuItem;
        N21: TMenuItem;
        ImageList1: TImageList;
        procedure PopupMenu1Popup(Sender: TObject);
    private
    public
        { Public declarations }
    end;

    function hook(code: Integer; w: WPARAM; p : LPARAM): Lresult stdcall;

implementation

function hook(code: Integer; w: WPARAM; p: LPARAM): Lresult stdcall;
begin
    if code < 0 then
    begin
        Result := CallNextHookEx(0, code, w, p);
        Exit;
    end;

    Result := CallNextHookEx(0, code, w, p);
end;

Или вы можете превратить его в статическую функцию класса: private class function hook(code: Integer; w: WPARAM; p : LPARAM): Lresult stdcall; static;

Andreas Rejbrand 20.02.2023 10:24

А также удалите лишние строки кода: просто всегда вызывайте CallNextHookEx().

AmigoJack 20.02.2023 11:26

Другие вопросы по теме