| Autor |
Beitrag |
antonflohr
Hält's aus hier
Beiträge: 10
|
Verfasst: So 09.11.03 21:09
Hallo,
ich bin dabei ein Programm zu schreiben, welches per TastaturHook jeden Tastenanschlag registriert. Ist dies geschehen, soll ein Timer gestartet werden der nicht in der DLL ist sondern im Hauptprogramm.
Der Hook sieht so aus:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67:
| library dll;
uses Windows, unit1, Messages, SysUtils, Classes, Dialogs;
var HookHandle: Cardinal = 0; WindowHandle: Cardinal = 0;
function KeyboardHookProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall; export; begin Result := CallNextHookEx(HookHandle, nCode, wParam, lParam); case nCode < 0 of TRUE: exit; FALSE: begin
ShowMessage('test'); unit1.k:=10; form1.timer3.enabled:=true;
end; end;
end;
function InstallHook(Hwnd: Cardinal): Boolean; stdcall; export; begin Result := False; if HookHandle = 0 then begin HookHandle := SetWindowsHookEx(WH_KEYBOARD, @KeyboardHookProc, HInstance, 0); WindowHandle := Hwnd; Result := TRUE; end; end;
function UninstallHook: Boolean; stdcall; export; begin Result := UnhookWindowsHookEx(HookHandle); HookHandle := 0; end;
exports InstallHook, UninstallHook, KeyboardHookProc; end. |
Der Aufruf in der Unit:
Delphi-Quelltext 1: 2: 3: 4:
| procedure TForm1.Button3Click(Sender: TObject); begin InstallHook(1); end; |
Es funzt auch ganz gut, außer dass der Timer nie gestartet wird. Es gibt auch keine Fehlermeldung. Ich vermute, dass es etwas mit dem Aufruf InstallHook(1)
zu tun hat. Denn ich weis nicht warum es mit einer 1 aufgerufen wird.
Ich habe auch schon andere Zahlen versucht, macht aber keinen Unterschied. Aber ohne geht es nicht.
Also kann mir jemand helfen??
Moderiert von Tino: Code- durch Delphi-Tags ersetzt.
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: So 09.11.03 21:17
woher soll die DLL dein Objekt Form1 kennen?
|
|
antonflohr 
Hält's aus hier
Beiträge: 10
|
Verfasst: So 09.11.03 23:03
Ich habe in der DLL unter
uses ..., ..., unit1;
eingetragen. Oder reicht das etwa nicht? Es gibt ja auch keinen Fehler der sagt, dass die dll keine form1 kennt. Es passiert halt einfach nichts.
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: So 09.11.03 23:05
Und der Code der DLL liegt im Adressraum des Zielprozesses. Form1 liegt aber in deinem Prozessraum. Jetzt klar?
Lass die aus der DLL eine Nachricht schicken, die in deinem Programm den Timer anstößt.
|
|
antonflohr 
Hält's aus hier
Beiträge: 10
|
Verfasst: Mo 10.11.03 00:33
wo kann ich denn nachschauen wie man solche Nachrichten schickt/empfängt.
Danke schon mal!! (Jetzt weis ich dass es nicht so geht wie ich dachte.)
|
|
antonflohr 
Hält's aus hier
Beiträge: 10
|
Verfasst: Di 11.11.03 14:01
Ich habe versucht Nachrichten mittels WM_COPYDATA zu übermitteln. Das funzt net! Ich glaube das es daran liegt das WM_COPYDATA eine Form braucht (hab ich irgendwo in irgendeinem Forum gelesen).
Dann hatte ich versucht einfach die Form (mit den Komponenten) in die DLL einzubinden. Das ging garnicht.
Hilfe!!
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Di 11.11.03 18:21
Die kannst du dir selber bestimmen:
Delphi-Quelltext 1:
| DLLM_MESSAGE := WM_USER + 1234 |
Die schickst du an dein Fenster, dessen Handle du ja kennst. Dort überschreibst du die WndProc und fängst deine Nachricht ab.
Oder mach es mit Memory Mapped Files. Ein Beispiel findest du dazu in der OpenSource-Sparte: KeyLogger.
|
|
antonflohr 
Hält's aus hier
Beiträge: 10
|
Verfasst: Mi 12.11.03 00:35
| Zitat: |
Die kannst du dir selber bestimmen:
Sourcecode:
DLLM_MESSAGE := WM_USER + 1234
Die schickst du an dein Fenster, dessen Handle du ja kennst. Dort überschreibst du die WndProc und fängst deine Nachricht ab.
|
Wo muss ich den diese Message deklarieren? Und was bedeutet denn die '+1234' ?
Und wie kann ich das Handle herausbekommen? Gib's da ne Funktion wie zB.
GetWindowHandle(FindWindow('Empfänger')); ?
| Zitat: |
Oder mach es mit Memory Mapped Files. Ein Beispiel findest du dazu in der OpenSource-Sparte: KeyLogger.
|
Damit konnte ich leider garnichts anfangen, da der Code sehr komplex war und er nicht kommentiert ist.
Am besten wäre wenn mir jemand es an einem billigen Beispiel erklären könnte. Z.B.
Das Programm A hat einen Button und ein Editfeld auf seiner Form.
Des weiteren hat es eine Prozedur aus der DLL 'B.dll' importiert. Diese wird ausgeführt wenn ich auf denn den Button von A klicke. Dann soll mittels dieser Prozedure per 'Edit.text:=' der Text im Editfeld von A geändert werden.
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Do 13.11.03 23:46
Was hat das jetzt mit dem ursprungs problem zu tun? Du rufst einfach aus der DLL eine Funktion auf die einen String zurück gibt.
ein DLL Tutorial gibt es hier: www.luckie-online.de/tutorials/assarbad/
|
|
antonflohr 
Hält's aus hier
Beiträge: 10
|
Verfasst: Fr 14.11.03 00:06
Ist es denn gesund für das system, wenn ich ca. 10 mal pro sekunde die DLL frage ob eine Taste gedrückt wurde?? Sollte man es nicht mit Messages machen? (Aber leider verstehe ich diese nicht!)
|
|
antonflohr 
Hält's aus hier
Beiträge: 10
|
Verfasst: Fr 14.11.03 01:23
Danke Luckie!!
Jetzt ist das Prog. soweit, dass solange das Fenstar aktiv (im Vordergrund) ist, die Impulse des Keyboards registriert werden. Doch (leider) sobald es inaktiv wird geht es nicht mehr.
dll:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78:
| library dll;
uses Windows, unit1, Messages, SysUtils, Classes, Dialogs;
var HookHandle: Cardinal = 0; WindowHandle: Cardinal = 0; wie:boolean;
function Taste:boolean; export; begin Taste:=wie; wie:=false;
end;
function KeyboardHookProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall; export; begin Result := CallNextHookEx(HookHandle, nCode, wParam, lParam);
case nCode < 0 of TRUE: exit; FALSE: begin
wie:=true;
end; end;
end;
function InstallHook(Hwnd: Cardinal): Boolean; stdcall; export; begin Result := False; if HookHandle = 0 then begin HookHandle := SetWindowsHookEx(WH_KEYBOARD, @KeyboardHookProc, HInstance, 0); WindowHandle := Hwnd; Result := TRUE; end; end;
function UninstallHook: Boolean; stdcall; export; begin Result := UnhookWindowsHookEx(HookHandle); HookHandle := 0; end;
exports InstallHook, UninstallHook, Taste, KeyboardHookProc; end. |
Programm:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143:
| unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, SerialNG, StdCtrls, ExtCtrls, adCpuUsage;
type TForm1 = class(TForm) CheckBox1: TCheckBox; CheckBox2: TCheckBox; SerialPortNG1: TSerialPortNG; Timer1: TTimer; Button1: TButton; Button2: TButton; Timer2: TTimer; Edit1: TEdit; Button3: TButton; Button4: TButton; Timer3: TTimer; Timer4: TTimer; Edit2: TEdit; procedure CheckBox1Click(Sender: TObject); procedure CheckBox2Click(Sender: TObject); procedure Timer1Timer(Sender: TObject); procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Timer2Timer(Sender: TObject); procedure Button3Click(Sender: TObject); procedure Button4Click(Sender: TObject); procedure Timer3Timer(Sender: TObject); procedure Timer4Timer(Sender: TObject);
private
public procedure test; end;
var Form1: TForm1; i,k:integer; j:real;
function InstallHook(Hwnd: Cardinal): Boolean; stdcall; external 'dll.dll'; function UninstallHook: Boolean; stdcall; external 'dll.dll'; function Taste: Boolean; stdcall; external 'dll.dll';
implementation
{$R *.dfm}
procedure TForm1.CheckBox1Click(Sender: TObject); begin test; end;
procedure TForm1.CheckBox2Click(Sender: TObject); begin test; end;
procedure TForm1.test; begin serialportng1.Active:=false;
serialportng1.Active:=true; serialportng1.DTRState:=checkbox1.Checked; serialportng1.RTSState:=checkbox2.Checked; end;
procedure TForm1.Timer1Timer(Sender: TObject); begin checkbox1.Checked:= not checkbox1.Checked; checkbox2.Checked:= not checkbox2.Checked;
test;
dec(i); if i=0 then timer1.Enabled:=false; end;
procedure TForm1.Button1Click(Sender: TObject); begin i:=100; timer1.Enabled:=true; end;
procedure TForm1.Button2Click(Sender: TObject); begin timer2.Enabled:=true; end;
procedure TForm1.Timer2Timer(Sender: TObject); begin CollectCpuData; j:=getcpuusage(1); edit1.Text:=Format(' %5.0f%',[GetCPUUsage(i)*100]); if strtoint(edit1.Text) > 30 then checkbox1.Checked:=true else checkbox1.Checked:=false; if strtoint(edit1.Text) > 70 then checkbox2.Checked:=true else checkbox2.Checked:=false; test; end;
procedure TForm1.Button3Click(Sender: TObject); begin InstallHook(1); timer4.Enabled:=true; end;
procedure TForm1.Button4Click(Sender: TObject); begin UninstallHook; end;
procedure TForm1.Timer3Timer(Sender: TObject); begin dec(k); checkbox1.Checked:=true; if k < 0 then begin timer3.Enabled:=false; checkbox1.Checked:=false; end; end;
procedure TForm1.Timer4Timer(Sender: TObject); begin if taste = true then begin
k:=1; timer3.enabled:=true; end; end;
end. |
Moderiert von Tino: Code- durch Delphi-Tags ersetzt.
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Fr 14.11.03 02:06
wird eigentlich alles in dem Tutorial erklärt. Bei liegt sogar noch ein funktionierender Tastatur Hook.
|
|
antonflohr 
Hält's aus hier
Beiträge: 10
|
Verfasst: Fr 14.11.03 16:56
So ich weis jetzt genau an welcher Stelle der Fehler liegt:
Funktion: A
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| var function Taste: Boolean; stdcall; external 'dll.dll';
procedure TForm1.Timer4Timer(Sender: TObject); begin //Showmessage('vor IF');
if taste = true then // <------------------------Hier ist das Problem!! begin //Showmessage('nach IF'); k:=1; timer3.enabled:=true; end; end; |
Funktionen/Prozeduren in DLL
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27:
| function Taste:boolean; export; begin Taste:=wie; wie:=false;
end;
function KeyboardHookProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall; export; begin Result := CallNextHookEx(HookHandle, nCode, wParam, lParam);
case nCode < 0 of TRUE: exit; //wenn code kleiner 0 wird nix gemacht FALSE: begin
wie:=true;
//Hier kann jetzt alles bearbeitet werden
end; end;
end; |
Und zwar liegt das Problem genau an dem Punkt der gekennzeichnet ist. Sobald das Fenster nicht mehr aktiv ist ist der Wert der function taste:boolean immer FALSE. Doch wenn das Fenster wieder aktiv ist geht es ohne Probleme.
Mit Hilfe von Showmessage() habe ich herausgefunden dass das Problem an dieser Stelle liegt.
Hoffe jemand hat ne Idee! 
|
|
antonflohr 
Hält's aus hier
Beiträge: 10
|
Verfasst: Sa 15.11.03 19:44
Hallo?
Hat noch nie jemand das beschriebene Problem gehabt
Habs auch nochmal mit Messages versucht:
Weis jemand warum da nichts passiert??
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| public { Public declarations } procedure wmuser(var WM_KEYBOARD_HOOK : hwnd); message 5201; . . . implementation
procedure Tform1.wmuser(var WM_KEYBOARD_HOOK : hwnd); begin form1.CheckBox1.Checked:=true; end; |
in DLL:
Quelltext 1: 2: 3: 4: 5: 6: 7:
| const WM_KEYBOARD_HOOK = WM_USER + 5201;
prozedur x; begin sendmessage(WM_KEYBOARD_HOOK,1,0,0); end; |
Weis jemand warum die Message nicht ankommt??
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Sa 15.11.03 20:27
Deine Message ist 5201 + WM_USER. Un bei deinem SendMessage fehtl der erste Paramter, das Fenster an welches die Nachricht geschickt werden soll.
|
|
antonflohr 
Hält's aus hier
Beiträge: 10
|
Verfasst: Sa 15.11.03 21:10
danke Luckie es funzt!!!
jetzt nur noch eine letzte Frage.
Also es sieht jetzt so aus:
Delphi-Quelltext 1:
| sendmessage(findwindow(nil,Pchar('Form1')),WM_KEYBOARD_HOOK,1,0); |
Sobald ich form1.hide mache geht es aber nicht mehr. Liegt das am find window()?
Ich habe auch schon versucht den Handle zu speichern bevor ich form1.hide mache. Gibt es eine Alterntive zu findwindow()?
|
|