Hallo
Ich habe einen LowLevel-Keyboard-Hook ohne
DLL, der an sich prächtig funktioniert. Nun sollte das Ding aber auf allen Desktops funktionieren (Default, Winlogon und Screen-Saver). Auch das tut es eigentlich. Auf XP generell, aber unter W-7 spinnen die meisten 3-D-Screen-Saver. Da ich bereits mal Mühe hatte, diese Dinger aus meinem Programm zu beenden und Microsoft bemühen musste (man muss für's Senden einer Message einen separaten Thread eröffnen), bin ich auf die Idee gekommen, das könnte auch beim KeyboardHook helfen. Faul wie ich bin, habe ich in meinem Testprogramm mal schnell eine TJvThread-Komponente auf's Formular geschmissen. Und nun habe ich zwei Varianten:
Code:
procedure TFAMMonitor.FormCreate(Sender: TObject);
begin
Pfad := ExtractFilePath(ParamStr(0));
TCode1 := 34;
TCode2 := 33;
Zwei := 0;
FTDT := CheckDesktopIsActive();
IniDT := copy(FTDT, 1, 2);
AssignFile(filno,Pfad + 'AMTest.log');
if FileExists(Pfad + 'AMTest.log') then
DeleteFile(Pfad + 'AMTest.log');
Rewrite(filno);
Writeln(filno, TimeToStr(Now) + ' ' + FTDT);
CloseFile(filno);
Durch := False;
JvThread1.Execute(Self);
{ HookTastatur := SetWindowsHookEx(WH_KEYBOARD_LL, @CallBackDelHook, HInstance , 0);
Durch := True; }
while not Durch do
sleep(100);
AssignFile(filno,Pfad + 'AMTest.log');
Append(filno);
if HookTastatur <> 0 then
Writeln(filno, TimeToStr(Now) + ' Hook gesetzt')
else
Writeln(filno, TimeToStr(Now) + ' Hook nicht gesetzt');
CloseFile(filno);
if not ((IniDT = 'Sc') and (CompInfo.OS.OSVersion = wvWin7)) then
begin
ShowWindow(Application.handle, SW_HIDE);
SetWindowLong(Application.handle, GWL_EXSTYLE,
GetWindowLong(application.handle, GWL_EXSTYLE) and
not WS_EX_APPWINDOW or WS_EX_TOOLWINDOW);
end;
Timer1.Enabled := True;
Timer2.Enabled := true;
end;
Das ganze ist ziemlich hässlich programmiert, dessen bin ich mir bewusst (z.B. die Ausbremserei bis der Thread durch ist). Ist ein Testprogramm! Wenn ich das Programm so laufen lassen wie hier, funktioniert der Hook nicht, wenn ich aber die Klammern um JvThread1.Execute(Self); setze und unten wegnehme, funktionierts. So, und hier der Thread:
Code:
procedure TFAMMonitor.JvThread1Execute(Sender: TObject; Params: Pointer);
var hDeskWnd : HDESK;
var hifil : Textfile;
begin
hDeskWnd := OpenDesktop('Default', 0, false, MAXIMUM_ALLOWED);
if hDeskWnd <> 0 then
begin
if SetThreadDesktop(hDeskWnd) then
begin
AssignFile(hifil, Pfad + 'AMTest.log');
Append(hifil);
Writeln(hifil, TimeToStr(Now) + ' DesktopThread gesetzt');
CloseFile(hifil);
HookTastatur := SetWindowsHookEx(WH_KEYBOARD_LL, @CallBackDelHook, HInstance, 0);
end;
CloseDesktop(hDeskWnd);
end;
Durch := True;
end;
Die Ausbremserei oben übrigens wegen der Textdatei. An sich läuft der Thread richtig durch und der Hook wird 'eigentlich' gesetzt, nur reagiert er nicht. Und anstelle von HInstance habe ich schon alle erdenklichen Varianten versucht. 0 geht nicht, mit FindHInstance(@FAMMonitor) oder FindHInstance(@TFAMMonitor.JvThread1Execute) läuft er zwar ebenfalls durch und liefert einen Wert HookTastatur <> 0, aber er kommt mir nie auf die CallBack-Funktion.
Die SetWindowsHookEx ist an beiden Orten identisch. Und das OpenDesktop auf 'Default' ist natürlich nur für Testzwecke. Da käme dann 'Screen-Saver' rein. Aber wenn der Hook schon auf 'Default' nicht geht ...
Und anzumerken wäre auch noch, dass ich es auch schon erfolglos mit einer
DLL versucht habe. Und für's ganze warum und wieso gibt's bereits einen anderen Thread. Deshalb hier nur noch kurz: Mein Alarmierungssystem muss eine Tastenkombination in jedem Zustand des Rechners abfangen können.
Hat jemand eine Idee, warum ich den Hook nicht aus einem Thread laden kann?