KeyHook - Keine Fehler, aber tut nix
-
Hallo, ich habe aus der FAQ dieses KeyHook mal probiert, ich hab's soweit hinbekommen, habe auch alles beachtet und so, nur wenn ich das Programm starte und ein paar Tasten drücke, macht die Funktion, die die Tasten abfangen sollte nichts. Was mache ich falsch? Habe ich etwas vergessen? - Hier die Codes, die ich verwende:
KeyHook.dll:
#include <vcl.h> #include <windows.h> #pragma hdrstop #define WM_KEYHOOK WM_USER+100 HHOOK ghhookKB; HINSTANCE ghInst; #pragma argsused int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved) { ghInst = hinst; return (1); } extern "C" __declspec(dllexport) __stdcall void SetHook(void); extern "C" __declspec(dllexport) __stdcall void RemoveHook(void); extern "C" __declspec(dllexport) __stdcall DWORD CheckKey(int, WORD,LONG); void __stdcall SetHook(void) { HOOKPROC lpfnHookProc = GetProcAddress(GetModuleHandle("KeyHook.dll"),"CheckKey"); ghhookKB = SetWindowsHookEx(WH_KEYBOARD, lpfnHookProc, ghInst, NULL); } void __stdcall RemoveHook(void) { UnhookWindowsHookEx(ghhookKB); } DWORD __stdcall CheckKey(int nCode, WORD wParam, LONG lParam) { HWND ghAppWnd = FindWindow("TKeyHookForm", 0); if((nCode < 0) || nCode == HC_NOREMOVE) return CallNextHookEx(ghhookKB, nCode, wParam, lParam); // Skip if it's a repeat if(lParam & 0x40000000) return CallNextHookEx(ghhookKB, nCode, wParam, lParam); // Send key information to the main window SendMessage(ghAppWnd, WM_KEYHOOK, 0, lParam); return CallNextHookEx(ghhookKB, nCode, wParam, lParam); }form.h:
#ifndef formH #define formH #define WM_KEYHOOK WM_USER+100 #include <Classes.hpp> #include <Controls.hpp> #include <StdCtrls.hpp> #include <Forms.hpp> class TForm2 : public TForm{ __published: // IDE-managed Components TListBox *ListBox1; void __fastcall FormCreate(TObject *Sender); void __fastcall FormCloseQuery(TObject *Sender, bool &CanClose); private: // User declarations MESSAGE void __fastcall KeyHook(TMessage &Message); BEGIN_MESSAGE_MAP MESSAGE_HANDLER(WM_KEYHOOK, TMessage, KeyHook); END_MESSAGE_MAP(TForm); public: __fastcall TForm2(TComponent* Owner); }; extern PACKAGE TForm2 *Form2; #endifform.cpp:
#include <vcl.h> #pragma hdrstop #include "form.h" #pragma package(smart_init) #pragma resource "*.dfm" extern "C" __declspec(dllexport) __stdcall void SetHook(void); extern "C" __declspec(dllexport) __stdcall void RemoveHook(void); extern "C" __declspec(dllexport) __stdcall DWORD CheckKey(int, WORD,LONG); TForm2 *Form2; __fastcall TForm2::TForm2(TComponent* Owner) : TForm(Owner) { } void __fastcall TForm2::FormCreate(TObject *Sender) { SetHook(); } void __fastcall TForm2::KeyHook(TMessage &Message) { char Key[80]; GetKeyNameText(Message.LParam,Key,80); ShowMessage("lol"); delete Key; } void __fastcall TForm2::FormCloseQuery(TObject *Sender, bool &CanClose) { RemoveHook(); }
-
Naja, man sollte den aus der FAQ kopierten Code hald doch an und ab auch mal analysieren.
Folgende zwei Fragen an dich:
a) hat nichts mit dem eigentlichen Problem zu tun, aber trotzdem ein interessanter und vor Allem wichtiger Punkt: Wieso "delete Key"?
b) Überleg dir mal wie die DLL wohl deinem Formular mitteilt, das eine Taste gedrückt wurde.-junix
-
junix schrieb:
a) hat nichts mit dem eigentlichen Problem zu tun, aber trotzdem ein interessanter und vor Allem wichtiger Punkt: Wieso "delete Key"?
Speicherfreigabe
b) Überleg dir mal wie die DLL wohl deinem Formular mitteilt, das eine Taste gedrückt wurde.
Wenn das so einfach für mich wäre, würde ich das hier nicht posten... also ich weiß, mit welcer Funktion das zusammenhängt, aber ich weiß nicht, wie ich sie aufrufen soll oder besser gesagt: Wann...
-
OK, jetzt habe ich das Formular umbenannt in KeyHookForm, damit klappt das, die Zeile sehe ich schon... jetzt benenne ich die Form um in fMain (wie sie eigentlich heißen soll) und ändere die Zeile in der DLL entsprechend um, aber es läuft wieder nicht... was nun?
EDIT: OK, sorry, danke für die Hilfe, ich habs... shit... DLL muss ja noch compiliert werden xD - Naja, bin schon etwas müde ^^
- Windoof
-
Windoof schrieb:
junix schrieb:
a) hat nichts mit dem eigentlichen Problem zu tun, aber trotzdem ein interessanter und vor Allem wichtiger Punkt: Wieso "delete Key"?
Speicherfreigabe
Dir sollte man die Finger abhacken und das Programmieren verbieten!
-
Key ist nicht dynamisch, also brauchst du auch kein delete.
-
@Windoof: Ist es nicht ein herrliches Gefühl, nach 10min Arbeit seinen Fehler selber gefunden und dabei sogar verstanden zu haben wies funktioniert?
Bezüglich dem delete
a) zu jedem "new" gehört ein "delete"
b) zu jedem "new []" gehört ein "delete []"
c) Von allem was nicht mit new selbst erstellt wurde oder in einer DOkumentation gesagt wurde, man müsse es löschen: Keep your hands off!
d) Für Stackobjekte gilt c).
-
Und wie gebe ich den Speicher eines char-Arrays sonst wieder frei...? bei normalem char geht das ja mi .~char(); (Destruktor) und bei Char-Arrays...? Mit .~char()[]; oder wie...? - Hab jetzt keinen BCB zur hand, aber einfach mal so als verständnisfrage.
-
Wenn das mit ~char geht, dann zahl ich dir ne kiste bier! Nur Klassen haben Destruktoren...
Stackobjekte werden ungültig nach Verlassen des Scopes.
Also durch eine "}"
-junix
-
Es sei denn der char wurde mit new erzeugt, dann gilt wieder (siehe junix vorletztes Posting) delete (für ein eizelnens char) oder delete[] (für ein char-Array).
Verständnisfragen solcher Art werden in jedem C / C++ Grundlagenbuch, meist äußerst erschöpfend, behandelt. Leg Dir mal eins zu.
-
junix schrieb:
Wenn das mit ~char geht, dann zahl ich dir ne kiste bier! Nur Klassen haben Destruktoren...
Stackobjekte werden ungültig nach Verlassen des Scopes.
Also durch eine "}"
-junix
Gut, dann schick den Kasten an folgende Adresse: ... Nein mal im Ernst: Das geht. Auch mit int geht das. Nur mit bool nicht... aber auch nur im BCB nicht, mit Dev-C++ kann man alle freigeben, auch bool... muss man sogar.
-
Ein Destruktor wird implizit aufgerufen, wenn eine Variable ihren deklarierten Gültigkeitsbereich verläßt. Destruktoren für lokale Variablen werden aufgerufen, wenn der Block, in dem sie deklariert sind, nicht mehr aktiv ist. Bei globalen Variablen werden Destruktoren als Teil der Exit-Prozedur nach main aufgerufen.
Wenn Zeiger auf Objekte ungültig werden, wird nicht implizit ein Destruktor aufgerufen. Zum Löschen eines derartigen Objekts muß demnach der delete-Operator aufgerufen werden.
Destruktoren werden in genau der umgekehrten Reihenfolge wie die zugehörigen Konstruktoren aufgerufen (siehe Aufrufreihenfolge von Konstruktoren).
Aus der BCB-Hilfe. Das wichtige Wörtchen ist implizit. Somit ist also schon der Gedanke daran, dne Destruktor (oder auch den Kostruktor) manuell aufzurufen sträflicher Unsinn.