Normalerweise kann die eigene Anwendung nur solche Ereignisse empfangen, die für sie bestimmt sind. Ein Mausklick auf dem Desktop beispielsweise führt nicht dazu, dass die Anwendung reagiert.
Um dies zu erreichen, ist ein Systemhook einzurichten. Dieser wird über die WIN 32 API Funktion SetWindowsHookEx gesetzt und mit UnhookWindowsHookEx wieder gelöscht. Dabei kann dann angegeben werden, welche Ereignistypen beachtet werden sollen, welcher Funktion aufgerufen werden sollen. Hookfunktionen sind grundsätzlich in einer DLL bereitzustellen.
Diese DLL stellt nun einfache Funktionen zur Verfügung um bestimmte systemweite Tastaturereignisse and die eigene Anwendung zu senden.
Die DLL hat für den Anwender zwei Funktionen für die Tastaturereignisse:
Die erste Funktion startet den Hook für die Tastatur, die zweite beendet ihn wieder.
| HWND handle | Das Handle des Fensters, an den die Nachricht über das Tastaturereignis geschickt wird. Die DLL sendet ein KEYDOWN Ereignis an das Fenster | ||||||||
| WORD key | Der
virtuelle Keycode der Taste.
(Achtung die Sondertasten haben zwar einen virtuellen Keycode. aber dieser wird
nicht über WM_KEYDOWN erfasst. Wird 0 als Parameter übergeben, werden alle Tastendrücke gesandt. |
||||||||
| sKeys s | Hier kann die Sondertaste angegeben
werden:
|
Die zweite Funktion hat keine Parameter.
Hierzu ist die DLL entweder statisch oder dynamisch in das Programm aufzunehmem
Danach muss zunächst die Hookfunktion aktiviert werden. Die beste Möglichkeit ist im ONCREATE Ereignis des Fomulars:
void __fastcall TForm1::FormCreate(TObject *Sender)
{
StartTastaturHook(Form1->Handle,66,KEY_NONE);
}
//---------------------------------------------------------------------------
Im obigen Beispiel wird auf den Druck der Taste "B" gewartet. Eine Sondertaste ist nicht erwünscht. Das Handle des Fensters wir von der VCL bequem bereitgestellt.
void __fastcall TForm1::FormCreate(TObject *Sender)
{
StartTastaturHook(Form1->Handle,65,KEY_ALT);
}
//---------------------------------------------------------------------------
Obiges Beispiel zeigt, wie auf den Tastendruck "A+ALT" gewartet.
Nun soll ja etwas passieren, wenn die von uns gewünschte Taste
gedrückt wird. Da die DLL ein KEYDOWN Ereignis erzeugt, richten wir dieses
ein .
Das KEYDOWN Ereignis für die Taste "B"
void __fastcall TForm1::FormKeyDown(TObject *Sender, WORD &Key,TShiftState Shift)
{
if(Key==66)
{
ShowMessage("Tastatur");
}
}
//---------------------------------------------------------------------------
Das KEYDOWN Ereignis für die Tasten "A+ALT"
void __fastcall TForm1::FormKeyDown(TObject *Sender, WORD &Key,TShiftState Shift)
{
if(Key==65&&Shift.Contains(ssAlt))
{
ShowMessage("Tastatur");
}
}
//---------------------------------------------------------------------------
Wird der Hook nicht mehr benötigt, so ist dieser aus dem System zu entfernen. Das geschieht am Besten im CLOSE Ereignis des Formulars:
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
StopTastaturHook();
}
//---------------------------------------------------------------------------
Das ist natürlich nicht alles was man mit den Tastaturereignissen anstellen kann, aber für den Anfänger sollte das erst mal ausreichen. Bei Gelegenheit werde ich die DLL um weitere Ereignistypen (Maus, usw.) erweitern.
Die DLL hat für den Anwender zwei Funktionen für die Tastaturereignisse:
Die erste Funktion startet den Hook für die Maus, die zweite beendet ihn wieder.
| HWND handle | Das Handle des Fensters, an den die Nachricht über das Tastaturereignis geschickt wird. Die DLL sendet ein KEYDOWN Ereignis an das Fenster |
| int mess | Nummer der Nachricht, an die die Ereignisse gesandt werden |
| bool move=false | Hier kann die Sondertaste angegeben werden, ob auch "nur" Mausbewegungen gemeldet werden, In der Voreinstellung werden keine "nur" Mausbewegungen gemeldet. |
Die zweite Funktion hat keine Parameter.
Hierzu ist die DLL entweder statisch oder dynamisch in das Programm aufzunehmem
Danach muss zunächst die Hookfunktion aktiviert werden. Die beste Möglichkeit ist im ONCREATE Ereignis des Fomulars:
void __fastcall TForm1::FormCreate(TObject *Sender)
{
StartMausHook(Form1->Handle,10);
}
//---------------------------------------------------------------------------
Hier ist die 10 als Nachrichtennummer angegeben worden. Es macht keinen Sinn, die Mausereignisse des ganzen System als Mausereignis an die eigene Anwendung weiterzuleiten. Hier muss eine "eigene" Botschaft her. Im folgenden wird beschrieben, wie eine eigene Message im C++Builder erstellt wird. Eigene Botschaften haben immer einen Wert. Dieser wir gebildet aus WM_USER+Wert. Dieser Wert ist die Nachrichtennummer, die im Aufruf "StartMausHook" angegeben wird. Eine eigene Message wird in der HEADER Datei des Formulars definiert. Im folgenden die Headerdatei (die roten Zeilen sind einzufügen):
//---------------------------------------------------------------------------
#ifndef UnitMainH
#define UnitMainH
//---------------------------------------------------------------------------
#include
#include
#include
#include
#define MYMESSAGE WM_USER + 10 //neu
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // Von der IDE verwaltete Komponenten
TButton *Button1;
TButton *Button2;
void __fastcall FormClose(TObject *Sender, TCloseAction &Action);
void __fastcall FormKeyDown(TObject *Sender, WORD &Key,
TShiftState Shift);
void __fastcall Button1Click(TObject *Sender);
void __fastcall Button2Click(TObject *Sender);
private: // Anwender-Deklarationen
void __fastcall OnMyMessage(TMessage& Message); //neu
public: // Anwender-Deklarationen
__fastcall TForm1(TComponent* Owner);
BEGIN_MESSAGE_MAP //neu
MESSAGE_HANDLER(MYMESSAGE, TMessage, OnMyMessage) //neu
END_MESSAGE_MAP(TForm) //neu
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
Mit diesen Einstellungen in der Headerdatei wird eine neue Message mit dem Namen MYMESSAGE definiert. Alle eingehenden Nachrichten werden an die Funktion OnMyMessage der Klasse weitergeleitet werden.
Diese Funktion OnMyMessage existiert noch nicht. Diese wird in die CPP-Datei geschrieben:
void __fastcall TForm1::OnMyMessage(TMessage& Message)
{
int x,y;
String ausgabe;
switch(Message.WParam)
{
case WM_MOUSEWHEEL:
if(Message.LParam==1)
ausgabe="Rad vorwärts";
else if(Message.LParam==-1)
ausgabe="Rad rückwärts";
break;
case WM_LBUTTONDOWN:
x=Message.LParamLo; //Maus X
y=Message.LParamHi; //Maus Y
ausgabe=IntToStr(x)+":"+IntToStr(y)+" Linke Taste";
break;
case WM_RBUTTONDOWN:
x=Message.LParamLo; //Maus X
y=Message.LParamHi; //Maus Y
ausgabe=IntToStr(x)+":"+IntToStr(y)+" Rechte Taste";
break;
}
ShowMessage(ausgabe);
} //neu
Obiges Beispiel zeigt, wie die X und Y Koordinaten gelesen werden. Der Parameter Message.WParam enthält die Botschaft. Hier werden nur 2 Botschaften (WM_LBUTTONDOWN und WM_RBUTTONDOWN) gesucht. Es gibt noch viele andere die gesandt werden.
Wird der Hook nicht mehr benötigt, so ist dieser aus dem System zu entfernen. Das geschieht am Besten im CLOSE Ereignis des Formulars:
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
StopMausHook();
}
//---------------------------------------------------------------------------
Download |
||
| chhook.dll | 67 KB | |
| 1.7.0.74 | WM_MOUSEWHEEL berücksichtigt |
| 1.7.0.62 | Migration auf C++ Builder 2006 |