Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: WinAPI и системное программирование > Hook на системную клавишу


Автор: Keeper89 30.3.2009, 21:51
Доброго времени суток!

На форме есть PopUp Menu. Необходимо установить хук на клавишу (или есть более рациональные способы?) вызова контекстного меню (та что правее пробела), при нажатии на которую меню будет закрываться.
Чем меньше кода и внешних библиотек, тем лучше.

Заранее спасибо.

Автор: Keeper89 31.3.2009, 19:27
Использую следующий код:
Код

...
var

  HookHandle: hHook;
  Form1: TForm1;

implementation

{$R *.dfm}

function HookProc(Code: integer; WParam: word; LParam: Longint): Longint; stdcall;
var
  msg: PEVENTMSG;
begin

  if Code >= 0 then
  begin

    result := 0;

    msg := Pointer(LParam);

    with Form1 do begin
        Caption := IntTostr(msg.message);
        case msg.message of
            WM_KEYDOWN: 
              // Здесь надо перехватить клавишу контекстного меню

        end;
    end;

  end

  else
        result := CallNextHookEx(HookHandle, code, WParam, LParam);

end; 

procedure TForm1.FormCreate(Sender: TObject);
begin
  HookHandle := SetWindowsHookEx(WH_JOURNALRECORD, @HookProc, HInstance, 0);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  if HookHandle <> 0 then UnhookWindowsHookEx(HookHandle);
end;

Как здесь обработать клавишу контекстного меню?

Автор: kami 31.3.2009, 19:45
http://msdn.microsoft.com/en-us/library/ms646293.aspx и http://msdn.microsoft.com/en-us/library/ms645540(VS.85).aspx
не помогут?

Автор: Keeper89 31.3.2009, 20:26
Цитата(kami @  31.3.2009,  19:45 Найти цитируемый пост)
GetAsyncKeyState и Virtual key codes
не помогут? 

Да, спасибо, нашел нужный код клавиши.
VK_APPS (0x5D)
    Applications key (Natural keyboard)

Автор: Keeper89 31.3.2009, 20:55
Дополнил код:
Код

function HookProc(Code: integer; WParam: word; LParam: Longint): Longint; stdcall;
var
  msg: PEventMsg;
  VirtCode : byte;
  s: Char;
begin
  if Code >= 0 then
  begin
    result := 0;
    msg := Pointer(LParam);
    with Form1 do begin
        case msg.message of
            WM_KEYDOWN:
            begin
              VirtCode := msg^.paramL and $FF;
              Caption := IntTostr(VirtCode);
              if VirtCode = VK_APPS then
              begin
                SendMessage(PopupList.Window, WM_CANCELMODE, 0, 0);
                DestroyHook();
              end;
            end;
        end;
    end;
  end
  else
    result := CallNextHookEx(HookHandle, code, WParam, LParam);
end;

Но меню не исчезает...

Автор: kami 1.4.2009, 00:28
В сам код не вникал - не компенентен в вопросах меню, но:
1. где вызов CallNextHookEx в случае, если nCode>=0 ?
2. Вы уверены, что нужно именно SendMessage, а не PostMessage? Все-таки рекомендуется завершить работу процедуры хука как можно быстрее, а SendMessage ждет, пока оконная процедура не обработает отправленное сообщение. (а может, оконная процедура вообще не в состоянии обработать сообщение именно из-за отсутствия CallNextHookEx) ?

Автор: Keeper89 1.4.2009, 00:47
Цитата(kami @  1.4.2009,  00:28 Найти цитируемый пост)
где вызов CallNextHookEx в случае, если nCode>=0

А зачем он, простите, нужен?
Цитата(kami @  1.4.2009,  00:28 Найти цитируемый пост)
Вы уверены, что нужно именно SendMessage, а не PostMessage? Все-таки рекомендуется завершить работу процедуры хука как можно быстрее, а SendMessage ждет, пока оконная процедура не обработает отправленное сообщение.

Ни одна, ни другая функция не приводят к результату.
Цитата(kami @  1.4.2009,  00:28 Найти цитируемый пост)
а может, оконная процедура вообще не в состоянии обработать сообщение именно из-за отсутствия CallNextHookEx

Поясните подробнее, ставил CallNextHookEx(...) до и после SendMessage - та же реакция.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)