Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 22.07.2010, 23:57   #1
Impuls1989
Форумчанин
 
Аватар для Impuls1989
 
Регистрация: 16.08.2008
Сообщений: 276
По умолчанию Локальные хуки внутри класса

Доброго времени суток. Недавно товарищ: ZaRDaK посоветовал мне использовать локальные хуки в программе (за что ему огромное спасибо).
Его решение моей проблемы работало прекрасно до тех пор, пока я не начал переносить код в класс.
В общем суть проблемы такова:
В качестве тестового примера делаю так:
Код:
   TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    CurrentHook: HHook;
  public
    function SetupLocalHook: boolean;
    function RemoveLocalHook: boolean;
    function KeyBoardHook(code: integer; wParam: word; lParam: longword): longword; stdcall;

    { Public declarations }
  end;
Реализовал все функции, но при компиляции функция:
Код:
function TForm1.SetupLocalHook: boolean;
begin
CurrentHook:=setwindowshookex(WH_KEYBOARD,@KeyBoardHook,0,GetCurrentThreadID());
    if CurrentHook<>0  then SetupLocalHook:=true else SetupLocalHook:=false;
end;
Вылетает с ошибкой:
[Error] Unit1.pas(39): Variable required
с указанием на @KeyBoardHook
Причем эта же самая функция вне класса работает превосходно...
Собственно вопрос очевиден: можно ли это исправить?
З.Ы. В архиве лежит тестовый исходник
Заранее спасибо.
Вложения
Тип файла: rar ХУКИ.rar (7.6 Кб, 9 просмотров)
Искусственный интеллект - фигня по сравнению с естественной глупостью
Impuls1989 вне форума Ответить с цитированием
Старый 23.07.2010, 00:07   #2
ZaRDaK
Форумчанин
 
Регистрация: 01.09.2009
Сообщений: 197
По умолчанию

--------
А если подумать?
Код:
function TForm1.SetupLocalHook: boolean;
begin
    CurrentHook:=setwindowshookex(WH_KEYBOARD,@TForm1.KeyBoardHook,0,GetCurrentThreadID());
    if CurrentHook<>0  then SetupLocalHook:=true else SetupLocalHook:=false;
end;
--------

Заносиш в класс
function KeyBoardHook(code: integer; wParam: word; lParam: longword): longword; stdcall;

пишешь обработчик как

function <имя_класса>.KeyBoardHook(code: integer; wParam: word; lParam: longword): longword;
begin
...
end;

CurrentHook:=setwindowshookex(WH_KE YBOARD,@,0,GetCurrentThreadID());
меняешь на
CurrentHook:=setwindowshookex(WH_KE YBOARD,@<имя_класса>.KeyBoardHook,0 ,GetCurrentThreadID());

Последний раз редактировалось ZaRDaK; 23.07.2010 в 00:10.
ZaRDaK вне форума Ответить с цитированием
Старый 23.07.2010, 13:20   #3
Impuls1989
Форумчанин
 
Аватар для Impuls1989
 
Регистрация: 16.08.2008
Сообщений: 276
По умолчанию

Да в том-то и весь прикол, что я так пробовал делать... Ошибка не пропадает...
Искусственный интеллект - фигня по сравнению с естественной глупостью
Impuls1989 вне форума Ответить с цитированием
Старый 23.07.2010, 13:26   #4
VintProg
not
Участник клуба
 
Аватар для VintProg
 
Регистрация: 27.06.2009
Сообщений: 1,399
По умолчанию

CurrentHook:=setwindowshookex(WH_KE YBOARD,Pointer(<имя_класса>.KeyBoar dHook),0 ,GetCurrentThreadID());

Последний раз редактировалось VintProg; 23.07.2010 в 13:34.
VintProg вне форума Ответить с цитированием
Старый 23.07.2010, 13:37   #5
Impuls1989
Форумчанин
 
Аватар для Impuls1989
 
Регистрация: 16.08.2008
Сообщений: 276
По умолчанию

Цитата:
Сообщение от VintProg Посмотреть сообщение
а имя сменить? "KeyBoardHook"
Код скомпилировался, но работать отказывается.
Код:
  TForm1 = class(TForm)
    Button1: TButton;
    Label1: TLabel;
    Label2: TLabel;

    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    FCurrentHook: HHook;
    FhotKey:boolean;
  public
    function SetupMyLocalHook: boolean;
    function RemoveMyLocalHook: boolean;
    function MyKeyBoardHook(code: integer; wParam: word; lParam: longword): longword; stdcall;

    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function TForm1.MyKeyBoardHook(code: integer; wParam: word; lParam: longword): longword; stdcall;
var tmp:longword;
begin
    if code<0 then begin
       Result:=CallNextHookEx(FCurrentHook,code,wParam,lparam);
       Exit;
    end;
      tmp:=lParam shr 30;
      if ((tmp and 1)=0) then
      begin
          Form1.Label1.Caption:=IntToStr(wParam);
        case wParam of
          VK_UP:   begin
                    if (FhotKey) then
                    begin
                      Form1.Label2.Caption:='CTRL+UP';
                    end;
                   end;
          VK_DOWN: begin
                    if (FhotKey) then
                    begin
                      Form1.Label2.Caption:='CTRL+DOWN';
                    end
                   end;
          VK_LEFT: begin
                    if (FhotKey) then
                    begin
                      Form1.Label2.Caption:='CTRL+LEFT';
                    end;
                   end;
          VK_RIGHT:begin
                    if (FhotKey) then
                    begin
                      Form1.Label2.Caption:='CTRL+RIGHT';
                    end;
                   end;
          end;
          if (wParam = VK_CONTROL) then
          begin
            FhotKey:=true;
          end;
      end else
      begin
        Form1.Label2.Caption:='';
        if (wParam = VK_CONTROL) then
        begin
          FhotKey:=false;
        end;
      end;
    CallNextHookEx(FCurrentHook,code,wParam,lparam);
    Result:=0;
    Exit;
end;

function TForm1.SetupMyLocalHook: boolean;
begin
    FCurrentHook:=SetWindowsHookEX(WH_KEYBOARD,@TForm1.MyKeyBoardHook,0,GetCurrentThreadID());
    if FCurrentHook<>0  then Result:=true else Result:=false;
end;

function TForm1.RemoveMyLocalHook: boolean;
begin
    Resul
t:=UnhookWindowsHookEx(FCurrentHook);
end;


procedure TForm1.FormCreate(Sender: TObject);
begin
SetupMyLocalHook;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
RemoveMyLocalHook;
end;
Вылетает с Access Violation на CallNextHookEx(FCurrentHook,code,wP aram,lparam);
процедуры MeKeyBoardHook
Искусственный интеллект - фигня по сравнению с естественной глупостью
Impuls1989 вне форума Ответить с цитированием
Старый 23.07.2010, 13:39   #6
VintProg
not
Участник клуба
 
Аватар для VintProg
 
Регистрация: 27.06.2009
Сообщений: 1,399
По умолчанию

CurrentHook:=setwindowshookex(WH_KE YBOARD,Pointer(<имя_класса>.KeyBoar dHook),0 ,GetCurrentThreadID());

Последний раз редактировалось VintProg; 23.07.2010 в 13:50.
VintProg вне форума Ответить с цитированием
Старый 23.07.2010, 13:51   #7
Impuls1989
Форумчанин
 
Аватар для Impuls1989
 
Регистрация: 16.08.2008
Сообщений: 276
По умолчанию

FCurrentHook:=SetWindowsHookEX(WH_K EYBOARD,Pointer(@TForm1.MyKeyBoardH ook),0,GetCurrentThreadID());
Картина не поменялась
А так:
FCurrentHook:=SetWindowsHookEX(WH_K EYBOARD,Pointer(TForm1.MyKeyBoardHo ok),0,GetCurrentThreadID());
[Error] Unit1.pas(97): Not enough actual parameters
Искусственный интеллект - фигня по сравнению с естественной глупостью
Impuls1989 вне форума Ответить с цитированием
Старый 23.07.2010, 14:02   #8
VintProg
not
Участник клуба
 
Аватар для VintProg
 
Регистрация: 27.06.2009
Сообщений: 1,399
По умолчанию

Цитата:
.MyKeyBoardHook
Тебе что надо адрес этой функции загнать???
VintProg вне форума Ответить с цитированием
Старый 23.07.2010, 18:26   #9
Impuls1989
Форумчанин
 
Аватар для Impuls1989
 
Регистрация: 16.08.2008
Сообщений: 276
По умолчанию

Цитата:
Сообщение от VintProg Посмотреть сообщение
Тебе что надо адрес этой функции загнать???
Ну да. SetWindowsHookEX требует указатель на процедуру фильтра (hook)
Искусственный интеллект - фигня по сравнению с естественной глупостью
Impuls1989 вне форума Ответить с цитированием
Старый 26.07.2010, 23:48   #10
Impuls1989
Форумчанин
 
Аватар для Impuls1989
 
Регистрация: 16.08.2008
Сообщений: 276
По умолчанию

Тема все еще актуальна. Гугл скоро будет узнавать меня по запросам(((
Вот в чем суть:
Если я выношу функцию: KeyBoardHook за пределы класса - все работает превосходно, но я тогда не могу из нее работать с методами моего компонента (отпадает вся суть создания компонента)
Если я заношу функцию: KeyBoardHook в класс (см. пример ниже) то:
1. Компиляция проходит успешно
2. После помещения компонента на форму и нажатия любой клавиши вылетает не только мое приложение, но и вся среда delphi.
Вот тестовый код компонента:
Красным выделены проблемные места.
Код:
unit SelectControl;

interface

uses
  SysUtils, Classes, ActnList, Forms, Controls, Dialogs, Windows;

type
  TSelectControl = class(TComponent)
  private
    FSelectedComponent:TStrings;
    FI:integer;
    FOwner:TComponent;
    FHotKey:boolean;
    FCurrentHook: HHook;

    procedure SetSelectedComponent(Orders:TStrings);
  protected
  public
    function SetupLocalHook: boolean;
    function RemoveLocalHook: boolean;
    function KeyBoardHook(code: integer; wParam: word; lParam: longword): longword; stdcall;

  published
    constructor Create(AOwner:TComponent); override;
    property SelectedComponentOrder:TStrings read FSelectedComponent write SetSelectedComponent;
    destructor Destroy; override;

    procedure SelectNextControl;
    procedure KeyBoardDown(wParam: word; lParam: longword);

  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Standard', [TSelectControl]);
end;

//------------------------------------------------------------------------------
function TSelectControl.SetupLocalHook: boolean;
begin
  FCurrentHook:=SetWindowsHookEX(WH_KEYBOARD,@TSelectControl.KeyBoardHook,0,GetCurrentThreadID());
    if (FCurrentHook<>0)  then Result:=true else Result:=false;
end;

function TSelectControl.RemoveLocalHook: boolean;
begin
    Result:=UnhookWindowsHookEx(FCurrentHook);
end;

function TSelectControl.KeyBoardHook(code: integer; wParam: word; lParam: longword): longword; stdcall;
begin
    if code<0 then begin
       Result:=CallNextHookEx(FCurrentHook,code,wParam,lparam);
       Exit;
    end;
    KeyBoardDown(wParam,lParam);
    CallNextHookEx(FCurrentHook,code,wParam,lparam);
    KeyBoardHook:=0;
    Exit;
end;
//------------------------------------------------------------------------------
procedure TSelectControl.KeyBoardDown(wParam: word; lParam: longword);
begin
    if ((lParam shr 30) and 1)=0 then
    begin
      case wParam of
      VK_UP: begin
              if (FhotKey) then
              begin
                ShowMessage('CTRL+UP');
              end;
             end;
      VK_DOWN: begin
                if (FhotKey) then
                begin
                  ShowMessage('CTRL+DOWN');
                end
               end;
      VK_LEFT: begin
                if (FhotKey) then
                begin
                  ShowMessage('CTRL+LEFT');
                end;
               end;
      VK_RIGHT:begin
                if (FhotKey) then
                begin
                  ShowMessage('CTRL+RIGHT');
                end;
               end;
      end;
      if (wParam = VK_CONTROL) then FhotKey:=true;
    end else
    begin
      if (wParam = VK_CONTROL) then FhotKey:=false;
    end;
end;

constructor TSelectControl.Create(AOwner:TComponent);
begin
  inherited Create(AOwner);
  FSelectedComponent:=TStringList.Create;
  FOwner:=AOwner;
  (FOwner as TForm).KeyPreview:=true;
  FHotKey:=false;
  SetupLocalHook;
end;

destructor TSelectControl.Destroy;
begin
  RemoveLocalHook;
  inherited Destroy;
end;
procedure TSelectControl.SetSelectedComponent(Orders:TStrings);
var i:integer;
begin
  FSelectedComponent.Clear;
    for i:=0 to Orders.Count-1 do
      FSelectedComponent.Add(Orders.Strings[i]);
end;

procedure TSelectControl.SelectNextControl;
begin
  inc(FI);
  if (FI < FOwner.ComponentCount-1) then
  begin
    if (FOwner.Components[FI] is TWinControl) then
    begin
      (FOwner.Components[FI] as TWinControl).SetFocus;
    end else SelectNextControl;
  end else
  begin
    FI:=-1;
    SelectNextControl;
  end;
end;


end.
Искусственный интеллект - фигня по сравнению с естественной глупостью

Последний раз редактировалось Impuls1989; 26.07.2010 в 23:53.
Impuls1989 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Хуки, проблема взятия адреса qwerc1 Win Api 2 16.06.2010 00:33
Хуки в Windows JeyKip Win Api 11 09.05.2010 00:33
Программа, использующая хуки anGeee Win Api 1 11.12.2009 20:59
ListView и хуки 7KByte Win Api 0 10.07.2009 22:21
Глобальные хуки Zeraim Win Api 2 24.05.2008 16:00