Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Сервис и RegisterHotKey [D7, WinXP]


Angel[Saint] ©   (2005-10-06 07:52:00) 

Доброго времени суток!
Пишу сервис и нужно чтобы он отлавливал определенные сочетания клавиш.
Проблема такая - не хочет региться ХотКей. Делаю так:

procedure TService.ServiceStart(Sender: TService; var Started: Boolean);
begin
if RegisterHotKey(ServiceThread.Handle, MOD_SHIFT+MOD_CONTROL+VK_F6, MOD_SHIFT+MOD_CONTROL, VK_F6)
  then Service.LogMessage('Reg OK',EVENTLOG_INFORMATION_TYPE)
  else Service.LogMessage('Reg NOT OK',EVENTLOG_INFORMATION_TYPE)
end;


и на остановку сервиса Унрегю хоткей. Пробовал данный код на обычной форме - все работает прекрасно, а вот в сервисе ни в какую... На каком-то форуме встречал упоминание что такое делалось и работало... что делаю не так? и как нужно делать?


Leonid Troyanovsky   (2005-10-07 13:11:00) [1]


> Angel[Saint]   (07.10.05 13:07) [19]
> я читал, но хотелось чтобы у процедуры параметр был TWMHotKey,
>  а не TMessage... ладно, сойдет...


case Message.Msg of
 WM_HOTKEY: ProcessHotKeyMessage(TWMHotKey(Message));

--
Regards, LVT.


Angel[Saint]   (2005-10-07 13:07:00) [2]

я читал, но хотелось чтобы у процедуры параметр был TWMHotKey, а не TMessage... ладно, сойдет...

спасибо за помощь Digitman :)


Digitman   (2005-10-07 10:12:00) [3]


> Angel[Saint]   (07.10.05 08:49) [17]


ты справку когда-нибудь будешь читать ?)
или так и будешь гадать на кофейной гуще ?)
там ведь даже ПРИМЕР есть использования ф-ции AllocateHWnd() !

TMyService = class(TService)
..
 procedure WndProc(var Message: TMessage);
..
end;

procedure TMyService.WndProc(var Message: TMessage);
begin
 case Message.Msg of
  WM_HOTKEY: ProcessHotKeyMessage(..);
 end;
end;

..

procedure TMyService.MyServiceStart(..);
begin
 WndHandle:=AllocateHWnd(WndProc);
 Started := (WndHandle <> 0) and RegisterHorKey(WndHandle, ..);
end;

procedure TMyService.MyServiceExecute(..);
var
 Msg: TMsg;
begin
 while not Terminated do
   ServiceThread.ProcessRequests(True);  
end;


Angel[Saint]   (2005-10-07 08:49:00) [4]

когда я описан TMessageHook и там определил метож обработки сообщения (procedure WMHotKey), то это мне понятно...
а с помощью AllocateHWnd()? посмотрел пример с таймером и что-то не врубаюсь... мне же нужно выполнить RegisterHorKey и передать ей хэндл...
а если объявить:
1. procedure WMHotKey(var Mess:TWMHotKey);message WM_HOTKEY;
2. Handle: HWND;
то Handle:=AllocateHWnd(WMHotKey); не проходит
[Error] Unit1.pas(48): Incompatible types: 'TMessage' and 'TWMHotKey'


Digitman   (2005-10-07 08:03:00) [5]


> мне то как раз и не нужна сама форма, а только хэндл


да тебе и хэндл даже не нужен ..вчитайся в  [1] ..

а если таки нужен, то для этого совершенно необязательно создавать какие-то формы и городить прочий огород) ... достаточно вызвать AllocateHWnd() - одним махом получишь и окно и его хэндл ..


Angel[Saint]   (2005-10-07 07:33:00) [6]

CreateNew() создает класс фармы без чтения DFM зашитого в экзешник (а мне то как раз и не нужна сама форма, а только хэндл)... я глюканул и создавал форму с помощью Create().... поэтому была ошибка EResNotFound... после использования CreateNew() EResNotFound исчезла... но вот врорая осталась, т.е. к форме по прежнемиу нельзя обратиться - выдается Access violation


Digitman   (2005-10-06 15:53:00) [7]


> может она и не создавалась


судя по "EResNotFound Resource TMessHook not found" не создавалась.

а ты понимаешь принципиальные различия между CreateNew()  и Create() ?

или от балды констр.метод выбрал ?)


Angel[Saint]   (2005-10-06 14:22:00) [8]

procedure TService1.ServiceCreate(Sender: TObject);
begin
LogMessage('-==!!!CREATE FORM',EVENTLOG_INFORMATION_TYPE);
try
 MessHook:=TMessHook.CreateNew(Self);
 LogMessage('-==!!!CREATION FORM COMPLETE',EVENTLOG_INFORMATION_TYPE);
except
 on e:exception do
  LogMessage('Вот такая беда приключилась при констуировании формы : ' + e.Classname + ' ' + e.Message, EVENTLOG_INFORMATION_TYPE);
end;

try
 if RegisterHotKey(MessHook.Handle, 700, MOD_SHIFT, VK_F6)
  then Service1.LogMessage('-==!!!KEY REG',EVENTLOG_INFORMATION_TYPE)
  else Service1.LogMessage('-==!!!KEY NOT REG',EVENTLOG_INFORMATION_TYPE);
except
 on e:exception do
  LogMessage('Вот такая беда приключилась при регистрации сочетания клавиш : ' + e.Classname + ' ' + e.Message, EVENTLOG_INFORMATION_TYPE);
end;

end;


вот если сделать так, то в лог пишет
Вот такая беда приключилась при констуировании формы : EResNotFound Resource TMessHook not found.
и
Вот такая беда приключилась при регистрации сочетания клавиш : EAccessViolation Access violation at address 0043978B in module 'Service.exe'. Read of address 00000180.

теперь и форма не создается... может она и не создавалась


Digitman   (2005-10-06 14:08:00) [9]


> -==!!!CREATION FORM COMPLETE в лог попадает (значить форма
> создается?),


ну, надо понимать,  так и есть  ...


> при попытке обратиться к MessHook возникает Access violation


а где в приведенном тобой коде есть такое обращение ? я не вижу ...

или ты, успешно создав форму в осн.потоке, тут же ринулся управлять ей в дополнительном ?

с этим надо быть крайне осторожным - не всякое обращение к объекту формы потокобезопасно ..


Angel[Saint]   (2005-10-06 14:02:00) [10]

-==!!!CREATION FORM COMPLETE в лог попадает (значить форма создается?), но при попытке обратиться к MessHook возникает Access violation....


Digitman   (2005-10-06 13:31:00) [11]

procedure TService1.ServiceCreate(Sender: TObject);
begin
LogMessage('-==!!!CREATE FORM',EVENTLOG_INFORMATION_TYPE);
try
  MessHook:=TMessHook.CreateNew(Self);
  LogMessage('-==!!!CREATION FORM COMPLETE',EVENTLOG_INFORMATION_TYPE);
 except
  on e:exception do
   LogMessage('Вот такая беда приключилась при констуировании формы : ' + e.Classname + ' ' + e.Message, EVENTLOG_INFORMATION_TYPE);
 end;
end;


Angel[Saint]   (2005-10-06 13:14:00) [12]

опс, ошибочка...
строчка MessHook:=TMessHook.CreateNew(Self); в коде не закоменчена...


Angel[Saint]   (2005-10-06 13:10:00) [13]

блин, при создании формы сервис виснет намертво. спасает только снятие его из диспетчера процессов..

вот как делаю....


 TMessHook = class (TCustomForm)
 private
   { Private declarations }
 public
   { Public declarations }
   constructor Create(AOwner: TComponent); override;
   destructor Destroy; override;
   procedure WMHotKey(var Mess:TWMHotKey);message WM_HOTKEY;
 end;

 TService1 = class(TService)
   procedure ServiceCreate(Sender: TObject);
   procedure ServiceDestroy(Sender: TObject);
   procedure ServiceExecute(Sender: TService);
 private
   { Private declarations }
 public
   function GetServiceController: TServiceController; override;
   { Public declarations }
 end;

....

procedure TService1.ServiceCreate(Sender: TObject);
begin
 LogMessage('-==!!!CREATE FORM',EVENTLOG_INFORMATION_TYPE);
 //MessHook:=TMessHook.CreateNew(Self);
 Service1.LogMessage('-==!!!CREATION FORM COMPLETE',EVENTLOG_INFORMATION_TYPE);
//  MessHook.Visible:=false;
end;


Digitman   (2005-10-06 10:58:00) [14]


> Angel[Saint]   (06.10.05 10:23) [5]


чтой-то вдруг сразу "глобальный хук" ?

достаточно просто соблюсти условия, указанные в справке

форму можно создать только в осн.потоке сервис-процесса, там же следует и зарегистрировать хоткей ... для этого существуют события OnCreate/OnDestroy - их обработчики вызываются как раз в осн.код.потоке сервис-процесса ... любые прочие же события, в т.ч. OnStart, вызываются в отдельном (ассоциированном с конкретным данным сервисом) доп.код.потоке, поэтому визуальную форму там создать не удастся (невизуальную можно, но при этом теряется смысл затеи)

можно поступить иначе - прямо в OnCreate средствами WinAPI создать окно и передать его хендл в регистрирующую хоткей ф-цию ... или вообще никаких окон не создавать, а в регистрирующую хоткей ф-цию в кач-ве хэндла передать 0 ...но тогда в OnExecute в любом случае придется организовывать цикл ожидания/выборки/диспетчеризации/обработки сообщений для того чтобы можно было реагировать в т.ч. и на WM_HOTKEY


xShadow   (2005-10-06 10:35:00) [15]


> хуком отлавливается каждое нажатие клавиши, а как мне нужно
> определить что нажаты были к примеру Ctrl+Shift+F6


Кнопка имеет 2 состояния нажата и отжата.


Angel[Saint]   (2005-10-06 10:23:00) [16]

тогда остается только глобальный хук... но вот вопрос, хуком отлавливается каждое нажатие клавиши, а как мне нужно определить что нажаты были к примеру Ctrl+Shift+F6


Digitman   (2005-10-06 10:19:00) [17]


> Angel[Saint]   (06.10.05 09:16) [3]



> не помогло, регистрация хоткеев также не проходила


ты справку-то вообще читать собираешься ?
или так и будешь слепо экспериментировать ?
справка-то не для Пушкина писана Борландом, а для тебя)

ведь черным же по белому сказано там:

This function cannot associate a hot key with a window created by another thread

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


Angel[Saint]   (2005-10-06 09:16:00) [18]

я пробовал делать иначе... создавал свой класс на основе TForm, делал  у него процедуру обработки сообщения и передавал его хендл в процедуру регистрации... это не помогло, регистрация хоткеев также не проходила...


Leonid Troyanovsky   (2005-10-06 08:40:00) [19]


> Angel[Saint]   (06.10.05 07:52)  

> Пишу сервис и нужно чтобы он отлавливал определенные сочетания
> клавиш.


Сервису негоже взаимодействовать с десктопом юзера.
Ему нужен клиента, который будет запускаться, скажем,
в startup, и передавать уловленное.

--
Regards, LVT.


Digitman   (2005-10-06 08:19:00) [20]

Parameters

hWnd

Identifies the windowthat will receive WM_HOTKEY messages generated by the hot key. If this parameter is NULL, WM_HOTKEY messages are posted to the message queue of the calling thread and must be processed in the message loop.

а ты вместо хэндла окна почему-то подставляешь хэндл трэда, который не имеет ничего общего ни с какими окнами ..


Наверх

Титульная страница Поиск, карта сайта Написать письмо