![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Сервис и 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.
а ты вместо хэндла окна почему-то подставляешь хэндл трэда, который не имеет ничего общего ни с какими окнами ..