Einzelnen Beitrag anzeigen

hesch21

Registriert seit: 31. Aug 2004
Ort: Basel
114 Beiträge
 
Delphi XE2 Enterprise
 
#1

Start eines Keyboard-Hooks aus einem Thread

  Alt 7. Sep 2012, 15:36
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?
Heinz Schneider

Geändert von hesch21 ( 7. Sep 2012 um 15:48 Uhr)
  Mit Zitat antworten Zitat