Autor Beitrag
antonflohr
Hält's aus hier
Beiträge: 10



BeitragVerfasst: 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:
ausblenden volle Höhe Delphi-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:
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
//es ist ebenfalls moeglich die Bearbeitung an eine Bedingung zu knuepfen
//it's possible to call CallNextHookEx conditional only.
  Result := CallNextHookEx(HookHandle, nCode, wParam, lParam);
  case nCode < 0 of 
    TRUE: exit; //wenn code kleiner 0 wird nix gemacht
                //if code smaller 0 nothing has to be done 
    FALSE:
      begin

   ShowMessage('test');   //nur zum testen
     unit1.k:=10;
     form1.timer3.enabled:=true;



//Hier kann jetzt alles bearbeitet werden
//Here one can work with the parameters

      end;
  end;

end; 

function InstallHook(Hwnd: Cardinal): Boolean; stdcall; export;
begin 
  Result := False; 
  if HookHandle = 0 then begin
//Erstmal Hook installieren 
//First install the hook 
    HookHandle := SetWindowsHookEx(WH_KEYBOARD, @KeyboardHookProc, HInstance, 0);
//Uebergebenes Fensterhandle sichern 
//Save the given window handle
    WindowHandle := Hwnd; 
    Result := TRUE;
  end;
end;

function UninstallHook: Boolean; stdcall;   export;
begin
//Hook aus der Hookchain entfernen
//Uninstall hook from hook chain
  Result := UnhookWindowsHookEx(HookHandle);
  HookHandle := 0;
end;

exports
//Installations- und Deinstallationsroutine exportieren
//Export the installation and deinstallation routine
  InstallHook,
  UninstallHook,
  KeyboardHookProc;
end.

Der Aufruf in der Unit:
ausblenden 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 user profile iconTino: Code- durch Delphi-Tags ersetzt.
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: So 09.11.03 21:17 
woher soll die DLL dein Objekt Form1 kennen?
antonflohr Threadstarter
Hält's aus hier
Beiträge: 10



BeitragVerfasst: 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



BeitragVerfasst: 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 Threadstarter
Hält's aus hier
Beiträge: 10



BeitragVerfasst: 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 Threadstarter
Hält's aus hier
Beiträge: 10



BeitragVerfasst: 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



BeitragVerfasst: Di 11.11.03 18:21 
Die kannst du dir selber bestimmen:
ausblenden 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 Threadstarter
Hält's aus hier
Beiträge: 10



BeitragVerfasst: 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



BeitragVerfasst: 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 Threadstarter
Hält's aus hier
Beiträge: 10



BeitragVerfasst: 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 Threadstarter
Hält's aus hier
Beiträge: 10



BeitragVerfasst: 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:
ausblenden volle Höhe Delphi-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:
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
//es ist ebenfalls moeglich die Bearbeitung an eine Bedingung zu knuepfen
//it's possible to call CallNextHookEx conditional only.
  Result := CallNextHookEx(HookHandle, nCode, wParam, lParam);

  case nCode < 0 of
    TRUE: exit; //wenn code kleiner 0 wird nix gemacht
                //if code smaller 0 nothing has to be done
    FALSE:
      begin

      wie:=true;


     // showmessage('uu');


//Hier kann jetzt alles bearbeitet werden
//Here one can iwork with the parameters

      end; 
  end;

end; 

function InstallHook(Hwnd: Cardinal): Boolean; stdcall; export;
begin 
  Result := False; 
  if HookHandle = 0 then begin 
//Erstmal Hook installieren 
//First install the hook 
    HookHandle := SetWindowsHookEx(WH_KEYBOARD, @KeyboardHookProc, HInstance, 0); 
//Uebergebenes Fensterhandle sichern 
//Save the given window handle 
    WindowHandle := Hwnd; 
    Result := TRUE; 
  end; 
end; 

function UninstallHook: Boolean; stdcall;   export;
begin 
//Hook aus der Hookchain entfernen 
//Uninstall hook from hook chain 
  Result := UnhookWindowsHookEx(HookHandle); 
  HookHandle := 0; 
end; 

exports 
//Installations- und Deinstallationsroutine exportieren 
//Export the installation and deinstallation routine 
  InstallHook,
  UninstallHook,
  Taste,
  KeyboardHookProc;
end.

Programm:
ausblenden volle Höhe Delphi-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:
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
    { Public declarations }
    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 user profile iconTino: Code- durch Delphi-Tags ersetzt.
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Fr 14.11.03 02:06 
wird eigentlich alles in dem Tutorial erklärt. Bei liegt sogar noch ein funktionierender Tastatur Hook.
antonflohr Threadstarter
Hält's aus hier
Beiträge: 10



BeitragVerfasst: Fr 14.11.03 16:56 
So ich weis jetzt genau an welcher Stelle der Fehler liegt:

Funktion: A
ausblenden 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
ausblenden 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! :idea:
antonflohr Threadstarter
Hält's aus hier
Beiträge: 10



BeitragVerfasst: 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??
ausblenden 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:
ausblenden 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



BeitragVerfasst: 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 Threadstarter
Hält's aus hier
Beiträge: 10



BeitragVerfasst: Sa 15.11.03 21:10 
danke Luckie es funzt!!!

jetzt nur noch eine letzte Frage.

Also es sieht jetzt so aus:
ausblenden 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()?