Forum: PC-Programmierung Access/VBA: Feststellen wenn eine Taste gedrückt ist


von Jypama (Gast)


Lesenswert?

Ich suche eine Möglichkeit, um festzustellen, ob eine (beliebige) Taste 
gedrückt ist.

Access ist mit Funktionen wie KeyDown/KeyUp bestückt, die aber leider 
nicht zuverlässig sind - der KeyUp-Event wird zuweilen verschluckt. 
Nämlich dann, wenn man bei gedrückt gehaltener Taste aus Access in eine 
andere anwendung wechselt. Wenn man dort dann die Taste loslässt, kann 
Access das natürlich nicht registrieren, und im Access gilt die Taste 
weiterhin als "gedrückt gehalten"

Daher suche ich eine API, die feststellen kann, ob immer noch ein 
Tastendruck vorliegt. Welche Taste gerade gedrückt wird, ist egal. Ich 
kenne nur APIs, die eine bestimmte Taste prüfen können. Es ist natürlich 
unsinnig, jede einzelne Taste abzufragen, ob sie noch gedrückt ist. Eine 
"KeyPressed Funktion" hatte mein Homecomputer in früheren Zeiten schon. 
Die lieferte TRUE, wenn "irgendeine Taste" gedrückt war. Und das gibts 
in der Access/VBA/API Welt nicht mehr ??

von Georg (Gast)


Lesenswert?

Jypama schrieb:
> Eine
> "KeyPressed Funktion" hatte mein Homecomputer in früheren Zeiten schon.

Auf dem liefen aber auch nicht viele Programme gleichzeitig.

Was wäre dir denn lieber: nur das Programm, das den Tastatur-Fokus hat, 
erfährt ob eine Taste gedrückt oder losgelassen wird, das ist die 
normale Windows-Version.

Oder alle laufenden Programme reagieren auf jeden Tastendruck. Muss ich 
wirklich erklären, dass das unsinnig ist?

Jypama schrieb:
> wenn man bei gedrückt gehaltener Taste aus Access in eine
> andere anwendung wechselt. Wenn man dort dann die Taste loslässt, kann
> Access das natürlich nicht registrieren

Genau, das ist ja auch die einzig brauchbare Alternative.

Georg

von Heinz B. (Firma: Privat) (hbrill)


Lesenswert?

Das bekommt man bspw. mit einem systemweiten lowlevel Keyboardhook
hin.

Vielleicht auch noch interessant :

https://activevb.de/tutorials/tut_keylogger/keylogger.html

: Bearbeitet durch User
von Jypama (Gast)


Lesenswert?

Georg schrieb:
> Genau, das ist ja auch die einzig brauchbare Alternative.
Nein, das ist völliger Quatsch, weil es in dem beschriebenen Fall zu 
keiner Lösung führt.

Heinz B. schrieb:
> https://activevb.de/tutorials/tut_keylogger/keylogger.html
Ja, sowas in der Richtung. Die APIs GetKeyState und GetAsyncKeyState 
verwende ich anderweitig bereits. Leider muss man bei beiden Funktionen 
wissen, WELCHE Taste man abfragen will. Die Frage, on eine beliebige 
Taste gedrückt ist, lässt sich damit nicht bzw. nur sehr umständlich 
lösen, z.B. indem man ALLE Tasten der Reihe nach abfragt.

Weiß keiner eine Lösung für das Problem?

von Heinz B. (Firma: Privat) (hbrill)


Lesenswert?

Ist, wie ich oben schon sagte, am einfachsten mit einem
Tastaturhook. Für mein XProfan gibt es sowas :

https://xprofan.net/intl/de/dlls/keyboardhook-dll/

Ob man sowas für Access verwenden kann, weiß ich nicht.
Man braucht auf jeden Fall das Instanzhandle vom laufenden
Access und auch das Fensterhandle, damit die DLL weiß, wohin
sie die Message schicken soll. Der Tastenwert steht dann in
wParam (siehe auch SendMessage, wparam, lparam).

Da Access keine UserMessages bereitstellt, müßte man das
Access eigene Fenster subclassen (wm_command usw.), um
diese spezielle Message (4444) herauszufischen und wparam
auszulesen.

Schau auch mal bei der API RegisterWindowMessageA zum
Registrieren einer solchen Message.


Ist, wie gesagt nicht ganz einfach und ob Access das mit
denke mal mit VBA das kann ? Die Messageverwaltung muß
man dann selber übernehmen (GetWindowProc und SetWindowProc),
indem man die Windowproc überschreibt bzw. erweitert.

Da müßtest du dich mal in dieser Richtung schlau machen.

: Bearbeitet durch User
von Heinz B. (Firma: Privat) (hbrill)


Lesenswert?

Nachtrag :
Was das Instanzhandle und Fensterhandle betrifft, sind die Funktionen
~GetWindowLong(%hWnd, ~GWL_HINSTANCE)
~FindWindow(lpClassName, lpWindowName)
die Anlaufstellen.

von c-hater (Gast)


Lesenswert?

Jypama schrieb:

> Daher suche ich eine API, die feststellen kann, ob immer noch ein
> Tastendruck vorliegt. Welche Taste gerade gedrückt wird, ist egal. Ich
> kenne nur APIs, die eine bestimmte Taste prüfen können.

GetKeyboardState() aus winuser tut, was du glaubst zu brauchen. Naja, 
zumindest mit ein wenig obertrivialer Nacharbeit.

Wirklich brauchen tut man das aber eigentlich nie, nur dann, wenn man 
schon ringsrum Scheiße programmiert hat, glaubt man sowas zu brauchen...

von Jens G. (jensig)


Lesenswert?

Jypama schrieb:
> Nämlich dann, wenn man bei gedrückt gehaltener Taste aus Access in eine
> andere anwendung wechselt. Wenn man dort dann die Taste loslässt, kann
> Access das natürlich nicht registrieren, und im Access gilt die Taste
> weiterhin als "gedrückt gehalten"

Dann betrachte es einfach als "Taste nicht mehr gedrückt", wenn das 
Access den Focus verliert (weil jetzt ein anderes Programm den Focus 
hat), bzw. mache die Aktionen rückgängig, die bei Key_down gemacht 
wurden (falls das relevant sein sollte)

c-hater schrieb:
> Wirklich brauchen tut man das aber eigentlich nie, nur dann, wenn man
> schon ringsrum Scheiße programmiert hat, glaubt man sowas zu brauchen...

Ja, so denke ich auch ...

: Bearbeitet durch User
von Georg (Gast)


Lesenswert?

Jens G. schrieb:
> Ja, so denke ich auch ...

Die Idee, dass eine Anwendung, die nicht den Focus hat, Tasten auswerten 
soll, ist von vornherein völlig irre.

Eine Taste gedrückt zu halten, während man das laufende Programm 
wechselt kann auch nur einem kranken Gehirn entspringen.

Irgendwann fährt man dann mit solchen Ideen gegen eine Wand.

Georg

von Jypama (Gast)


Lesenswert?

c-hater schrieb:
> Wirklich brauchen tut man das aber eigentlich nie, nur dann, wenn man
> schon ringsrum Scheiße programmiert hat, glaubt man sowas zu brauchen...

Schon klar. Ich weiß bescheid :-)

Georg schrieb:
> Eine Taste gedrückt zu halten, während man das laufende Programm
> wechselt kann auch nur einem kranken Gehirn entspringen.

Du weißt auch, was man wissen muss. Aber keinen Fitzel mehr gell ;-)

Gut Georg, ich erklär halt, wofür ich das will. Wenn die Shift-Taste 
gehalten wird, soll sich beim Klick auf einen Button der Explorer 
öffnen. Der Text des Button soll rot sein, solange die Shift-Taste 
gedrückt ist. Funktioniert ja alles, der Explorer öffnet sich. Nur den 
roten Text setzt Access nicht zurück, weil das Loslassen der Shift-Taste 
im Explorer geschieht, und Access daher keinen Key-Up-Event mehr 
auslösen kann. Na gut, wenn das einem kranken Hirn entsprungen sein 
soll, dann ist es halt so.

Ich habe das mit einem Timer gefixt. Der prüft halt, ob die Shift-Taste 
noch gedrückt ist und holt dann den Key-Up-Event "von Hand" nach. Ich 
dachte, es wäre nett, wenn man eine allgemeine Funktion hätte, die nicht 
nur auf eine bestimmte Taste prüft, hier die Shift-Taste. Aber so 
wichtig ist das nun auch nicht.

Ich danke für die Hilfe, sind ja ein paar gute Anregungen gekommen :-)

von Schlaumaier (Gast)


Lesenswert?

Jypama schrieb:
> Nur den
> roten Text setzt Access nicht zurück, weil das Loslassen der Shift-Taste
> im Explorer geschieht, und Access daher keinen Key-Up-Event mehr
> auslösen kann.

Wenn du ein KEY-Ereignis auslöst, startet du eine Sub-Routine wie jede 
andere auch. Am Ende der Sub-Routine wird die Taste automatisch 
losgelassen.

ABER. WO löst du das KEY-Ereignis aus. ??

In einen Eingabe-Feld oder in der Form. Es gibt das übergeordnete 
KEY-Ereignis der Form. Wenn das aktiviert ist, wird es VOR jeden anderen 
KEY-Ereignis ausgelöst.

So viel dazu.

Was den Rest angeht kann man auch tricksen.

Man legt eine globale Variable an, Status Boolean. Wenn das KEY-Ereignis 
ausgelöst wird ändert man den Status. Fertig ist.

Ob der Mist in VBA funktioniert weiß ich nicht.

In VB mache ich ähnliches dauernd.  Ach und wenn man etwas auslösen will 
reicht auch ein .performclick . Finde ich schöner als die Ereignis-sub 
aufzurufen. ;)

von Schlaumaier (Gast)


Lesenswert?

Nachtrag:

Beschäftige dich mit INTEROP. Dann machst du das alles in VB und gibst 
die Befehle normal an Access weiter.

Ist viel angenehmer. ;)

von Jypama (Gast)


Lesenswert?

Meine Frage wurde ja beantwortet. Nochmals vielen Dank :-)
Ich lese aber trotzdem noch. Kommen ja immer mal interessante Tipps.
z.B. das hier :-D
Schlaumaier schrieb:
> Wenn du ein KEY-Ereignis auslöst, startet du eine Sub-Routine wie jede
> andere auch. Am Ende der Sub-Routine wird die Taste automatisch
> losgelassen.
Ich weiß gerade nicht, welche Tastatur eine Taste automatisch loslässt, 
wenn sie nicht mehr gebraucht wird? Bitte mehr Info, so eine Tastatur 
will ich auch :-)

Schlaumaier schrieb:
> Ob der Mist in VBA funktioniert weiß ich nicht.
VBA gilt als Kinderkram. Meiner Ansicht nach ist das ungerechtfertigt, 
denn VBA kann eine ganze Menge. Mit APIs gibts eigentlich keine 
unlösbaren Aufgaben. Und JA, es funktioniert mit der Variablen. Tue ich 
ja auch. Was aber, wenn der Event ausbleibt, der die Variable 
zurücksetzt? Darum ging es mir.

von Schlaumaier (Gast)


Lesenswert?

Jypama schrieb:
> Ich weiß gerade nicht, welche Tastatur eine Taste automatisch loslässt,
> wenn sie nicht mehr gebraucht wird? Bitte mehr Info, so eine Tastatur
> will ich auch :-)

gar keine.

Ich meinte das das Ereignis mehrfach ausgelöst wird. Der 
Tastatur-Prozessor senden die Information das die Taste drückt und 
GEHALTEN wird, mehrfach als Gedrückt. Diese Eigenschaft kann man unter 
Windows sogar einstellen.

JEDES Ereignis löst das Key_* Ereignis aus.

Was mir gerade einfällt und ich testen würde ist. Wenn du das 
key_down_Ereignis auslöst und dann via shell die App anhältst würde sie 
vielleicht das KEY_UP ereignis auslösen wenn sie weiter läuft. Ist aber 
nur Theorie. Kein Bock zu Testen.

Jypama schrieb:
> Was aber, wenn der Event ausbleibt, der die Variable
> zurücksetzt? Darum ging es mir.

Sollte durch das KEY_UP ereignis nicht passieren.

Das ganze ist für spielprogrammierung interessant.

Key_down = Männchen läuft los solange Taste gehalten. Dank 
Tastenwiederholung wird das Ereignis widerholt ausgelöst. Da aber KEIN 
Key_up_Ereignis ausgelöst wird, bleibt das Männchen nicht steht bzw. 
stolpert daher :)

von Jypama (Gast)


Lesenswert?

Klar, die Tastenwiederholung könnte man auch nutzen, und auf das Key-Up 
Ereignis vielleicht sogar ganz verzichten. Indem man einen Timer bei 
jedem Key-Down re-triggert, so dass er bei gedrückter Taste nie auslösen 
kann, und den Timer-Ablauf dann als Key-Up interpretiert. So ähnlich 
habe ich implementiert. Es funktioniert, aber ich fand das nicht so 
elegant. Ich werde mir dann die APIs noch mal ansehen, ob ich da was 
basteln kann, was schicker ist. Mir stört auch, dass Zusatztasten wie 
Shift oder CTRL Anschlagwiedrerholung haben. Sowas dürfte gar nicht sein 
und andere Systeme, wo ich noch programmiere, haben das auch nicht. Da 
ist SHIFT ein statischer Zustand, der entweder TRUE oder FALSE ist, 
punkt.

von Jypama (Gast)


Lesenswert?

Schlaumaier schrieb:
> Jypama schrieb:
>> Was aber, wenn der Event ausbleibt, der die Variable
>> zurücksetzt? Darum ging es mir.
>
> Sollte durch das KEY_UP ereignis nicht passieren.
Ja doch, genau DAS ist doch das Problem. Bei gedrückter Shift-Taste auf 
einen Button geklickt, öffnet sich der Explorer, und zwar im Vordergrund 
bei voller Größe. Access, nun im Hintergrund, empfängt dann das 
Loslassen der Shift-Taste nicht mehr.

von c-hater (Gast)


Lesenswert?

Jypama schrieb:

> Ja doch, genau DAS ist doch das Problem. Bei gedrückter Shift-Taste auf
> einen Button geklickt, öffnet sich der Explorer, und zwar im Vordergrund
> bei voller Größe. Access, nun im Hintergrund, empfängt dann das
> Loslassen der Shift-Taste nicht mehr.

Aber es empfangt auf jeden Fall die Nachricht über den Verlust des 
Focus. Die braucht man bloß auswerten und der Drops ist gelutscht. Wurde 
übrigens auch schon mehrfach im Thread drauf hingewiesen, möchte ich 
meinen...

von Schleimfasten (Gast)


Lesenswert?

"Wenn shifttaste gedrückt soll Explorer starten, text rot..."

UIs aus der Hölle. Access, VBA, da weiss man was man als Anwender für 
einen Müll erwarten darf.

von Wilhelm M. (wimalopaan)


Lesenswert?

Schleimfasten schrieb:
> "Wenn shifttaste gedrückt soll Explorer starten, text rot..."
>
> UIs aus der Hölle. Access, VBA, da weiss man was man als Anwender für
> einen Müll erwarten darf.

Chromium: <shift> + Bookmark. Macht genau das (statt text rot ist 
button/pressed)

von Jypama (Gast)


Lesenswert?

c-hater schrieb:
> Aber es empfangt auf jeden Fall die Nachricht über den Verlust des
> Focus. Die braucht man bloß auswerten und der Drops ist gelutscht. Wurde
> übrigens auch schon mehrfach im Thread drauf hingewiesen, möchte ich
> meinen...
Arroganz und große Töne haben in noch keinem Forum jemanden weiter 
gebracht. Vor allem dann nicht, wenn es Schnellschüsse sind, die 
überhaupt nicht funktionieren. Zum einen stellt Access keine Hausmittel 
zur Verfügung, um festzustellen, dass es den Fokus verloren hat. 
Formulare können das. Nur löst dieses Event z.B. auch dann aus, wenn in 
diesem Formular auf ein Unterformular gewechselt wird. Denn das 
Hauptformular wurde ja verlassen. Der Anwender muss eine Grenze zwischen 
Form und UFo übrigens nicht erkennen, das ist der Sinn eingebetteter 
Unterformulare. Daneben könnte man noch mindestens 10 weitere 
Situationen aufzählen, wo der Lost-Focus-Event auch nicht auslöst. Aber 
lassen wir das jetzt. Mir nur danach, festzustellen, dass Sprücheklopfer 
wie "c-hater" immer nur destruktiv daherkommen. Im übrigen frage ich 
mich gerade, wenn einer c "hatet" und von VBA auch keine Ahnung hat, 
wovon er überhaupt Ahnung hat ... ;-)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.