Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.12.11;
Скачать: CL | DM;

Вниз

Сервис и RegisterHotKey   Найти похожие ветки 

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

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

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;


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


 
Digitman ©   (2005-10-06 08:19) [1]

Parameters

hWnd

Identifies the window that 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.

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


 
Leonid Troyanovsky ©   (2005-10-06 08:40) [2]


> Angel[Saint]   (06.10.05 07:52)  

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


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

--
Regards, LVT.


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

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


 
Digitman ©   (2005-10-06 10:19) [4]


> 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 10:23) [5]

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


 
xShadow ©   (2005-10-06 10:35) [6]


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


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


 
Digitman ©   (2005-10-06 10:58) [7]


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


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

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

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

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


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

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

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


 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;


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

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


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

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 14:02) [11]

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


 
Digitman ©   (2005-10-06 14:08) [12]


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


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


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


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

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

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


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

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 15:53) [14]


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


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

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

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


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

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


 
Digitman ©   (2005-10-07 08:03) [16]


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


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

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


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

когда я описан 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 10:12) [18]


> 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 13:07) [19]

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

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


 
Leonid Troyanovsky ©   (2005-10-07 13:11) [20]


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


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

--
Regards, LVT.



Страницы: 1 вся ветка

Текущий архив: 2005.12.11;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.042 c
4-1127541341
GrayFace
2005-09-24 09:55
2005.12.11
Нерастяжимое окно. WS_SIZEBOX vs WS_SYSMENU.


4-1128670772
Stanislav
2005-10-07 11:39
2005.12.11
как использовать CreateThread


1-1132052114
ANB
2005-11-15 13:55
2005.12.11
Каким способом проще всего вытянуть данные из ячеек Excel в Delph


11-1113549791
rOose
2005-04-15 11:23
2005.12.11
OpenSaveDialog


14-1132567081
futility
2005-11-21 12:58
2005.12.11
Delphi