Hypercell ein ] Hypercell aus ] Zeige Navigation ] Verstecke Navigation ]
c++.net  
   

Die mobilen Seiten von c++.net:
https://m.c-plusplus.net

  
C++ Forum :: WinAPI ::  GetKeyboardState() Taste gedrückt, aber wird nicht erkannt     Zeige alle Beiträge auf einer Seite Auf Beitrag antworten
Autor Nachricht
HarteWare
Mitglied

Benutzerprofil
Anmeldungsdatum: 16.02.2013
Beiträge: 401
Beitrag HarteWare Mitglied 21:43:48 26.12.2016   Titel:   GetKeyboardState() Taste gedrückt, aber wird nicht erkannt            Zitieren

Hallo,

laut Dokumentation setzt die Funktion GetKeyboardState() bei allen BYTES das MSB, bei denen der entsprechende VKCode als gedrückt registriert wurde (Als Keyboard Message). Folgendes Beispiel:
C++:
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
#include <iostream>
#include <Windows.h>
 
void print_key(PKBDLLHOOKSTRUCT kb)
{
    std::cout << "Key pressed" << std::endl;
 
    BYTE keystate[256]{};
    if (!GetKeyboardState(keystate))
        std::cerr << "GetKeyboardState failed\n";
 
    if (keystate[VK_RETURN] & 0x80)  // highest order bit set
        std::cout << "You pressed RETURN!" << std::endl;
}
 
LRESULT CALLBACK keyproc(int code, WPARAM wParam, LPARAM lParam)
{  
    if (code == HC_ACTION && wParam == WM_KEYDOWN)
        print_key(PKBDLLHOOKSTRUCT(lParam));
    return CallNextHookEx(nullptr, code, wParam, lParam);
}
 
int main()
{
    if (HHOOK hook = SetWindowsHookEx(WH_KEYBOARD_LL, keyproc, nullptr, 0))
    {
        for (MSG msg; GetMessage(&msg, nullptr, 0, 0); )
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        UnhookWindowsHookEx(hook);
    }
}


OK. Ich habe zwar eine Message-Loop, aber vielleicht mache ich trotzdem etwas falsch, habe mal wieder etwas in der Dokumentation übersehen. Wieso sagt mir das nächste Beispiel trotzdem nicht, dass ich Eingabe gedrückt habe, obwohl die Taste doch offensichtlich zum Zeitpunkt des callbacks gedrückt ist (muss sie ja, sonst gäbe es keinen callback!).
C++:
    if (GetAsyncKeyState(VK_RETURN) < 0)
        std::cout << "You pressed RETURN!" << std::endl;

Das bringt gerade etwas meine Weltansichten durcheinander, und falls mir jemand auch nur den kleinsten Hinweis geben könnte, welche meiner Annahmen hier falsch sind, ich wäre sehr dankbar!

Ich freue mich auf Eure zahlreichen Antworten!

LG
HarteWare

P.S.: Ich habe schon eine "Lösung" gefunden (Natürlich sollte man keine globale Variable verwenden, sondern das Ganze in eine Klasse kapseln). Das ist für mich trotzdem nicht zufriedenstellend. Ich möchte verstehen, weshalb die obigen Programme sich nicht so verhalten, wie ich es mir vorstelle.
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
static BYTE global_keystate[256]{};
 
void press_key(int vkCode)
{    // falsch für toggle-keys, aber hier gehts ums Prinzip
    if (vkCode > 0 && vkCode < 256)
        global_keystate[vkCode] |= 0x80;
}
 
void release_key(int vkCode)
{
    if (vkCode > 0 && vkCode < 256)
        global_keystate[vkCode] = 0;
}


Die Funktionen werden entsprechend bei WM_KEYDOWN/KEYUP aufgerufen.


Zuletzt bearbeitet von HarteWare am 23:43:40 26.12.2016, insgesamt 3-mal bearbeitet
floorball
Mitglied

Benutzerprofil
Anmeldungsdatum: 18.04.2012
Beiträge: 199
Beitrag floorball Mitglied 15:59:29 28.12.2016   Titel:              Zitieren

MSDN schrieb:
An application can call this function to retrieve the current status of all the virtual keys.

In dem Moment in dem deine Callback Funktion aufgerufen wird ist die Taste schon nicht mehr gedrückt. Deswegen gibt es auch noch so Funktionen wie GetAsyncKexState.
Beide Funktionen sind für dein Problem aber irrelevant.
Schau mal hier nach:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms644967(v=vs.85).aspx
HarteWare
Mitglied

Benutzerprofil
Anmeldungsdatum: 16.02.2013
Beiträge: 401
Beitrag HarteWare Mitglied 16:33:40 28.12.2016   Titel:              Zitieren

floorball schrieb:
MSDN schrieb:
An application can call this function to retrieve the current status of all the virtual keys.

In dem Moment in dem deine Callback Funktion aufgerufen wird ist die Taste schon nicht mehr gedrückt. Deswegen gibt es auch noch so Funktionen wie GetAsyncKexState.

Ich widerspreche: Ich drücke die Taste und lass' sie nicht mehr los. Währenddessen erscheint in meiner Konsole der Text "Key pressed". Damit diese Ausgabe stattfinden kann, muss die Callback-Funktion aufgerufen worden sein. Ergo ist die Taste zum Zeitpunkt des Callback-Funktionaufrufs gedrückt.

Zum Thema GetAsyncKeyState: Ich meine ich hätte im ursprünglichen Post angesprochen, dass diese Funktion ebenfalls nicht wie erwartet funktioniert. Ich werde aber nochmals deinen Link nachlesen, eventuell finde ich dort nützliche Hinweise. EDIT: Habe nichts gefunden.

Vielen Dank

LG
HarteWare


Zuletzt bearbeitet von HarteWare am 16:35:56 28.12.2016, insgesamt 1-mal bearbeitet
sedd
Unregistrierter




Beitrag sedd Unregistrierter 19:51:23 28.12.2016   Titel:              Zitieren

HarteWare schrieb:
EDIT: Habe nichts gefunden.

Vielen Dank


???
Die passende Funktionssignatur hast du doch, floorball hat nur auf die entsprechende Doku verlinkt.
C++:
if(kb->vkCode==VK_RETURN)
...
rudi994
Mitglied

Benutzerprofil
Anmeldungsdatum: 27.10.2016
Beiträge: 7
Beitrag rudi994 Mitglied 12:19:21 30.12.2016   Titel:              Zitieren

Bei mir funktioniert es bislang, habe aber auch keine Erwartungen mehr, die dann nicht erfüllt werden. Hier mal nach meinem Kenntnisstand:

Statusänderung einer Taste tritt für GetAsyncKeyState() erst ein, wenn eine gesendete (korrespondierende?) Tastaturbotschaft aus der Nachrichtenschleife des aufrufenden Thread entfernt wird.

GetAsyncKeyState() und Aufruf einer Tastenstatus-Printfunktion habe ich in KeyProc() innerhalb der Abfrage "if ((code == HC_ACTION) && (wParam == WM_...))". GetAsyncKeyState() liefert 0x8001, wenn in der Abfrage (wParam == WM_KEYUP) eingesetzt wird. Bei (wParam == WM_KEYDOWN) wird auch 0x8001 geliefert, solange dieselbe Taste gedrückt gehalten wird. Sonst wird 0x0000 beim Niederdrücken einer Taste zurückgegeben oder auch dann, wenn die betätigte Taste nicht dem Argument in GetAsyncKeyState() entspricht.

Auffällig ist (bei mir im Test), daß GetAsyncKeyState(), sofern es nicht 0x0000 zurückgibt, immer 0x8001 liefert, aber nie 0x8000 oder 0x0001. Eine betätigte Taste gilt hier immer gleichzeitig als gedrückt und getoggelt, aber nie nur das Eine oder nur das Andere.

Übrigends ist auf MSDN auch folgendes zu lesen:
- Benutzer sollten sich nicht auf Rückgaben von GetAsyncKeyState() verlassen.
- Eine Nachricht für einen Hook wird bei Ablauf eines Zeitlimit stillschweigend aus der Nachrichtenschleife gelöscht, wenn also z.B. eine Prozedur zuviel Zeit vertrödelt.

Das kann wohl bedeuten, daß GetAsyncKeyState() nur in unkritischen Fällen und nur zur groben Detektierung von Tastenbetätigungen verwendet werden soll und daß
Tastaturnachrichten (und die Statusänderungen?) verloren gehen können.

LG
C++ Forum :: WinAPI ::  GetKeyboardState() Taste gedrückt, aber wird nicht erkannt   Auf Beitrag antworten

Zeige alle Beiträge auf einer Seite




Nächstes Thema anzeigen
Vorheriges Thema anzeigen
Sie können Beiträge in dieses Forum schreiben.
Sie können auf Beiträge in diesem Forum antworten.
Sie können Ihre Beiträge in diesem Forum nicht bearbeiten.
Sie können Ihre Beiträge in diesem Forum nicht löschen.
Sie können an Umfragen in diesem Forum nicht mitmachen.

Powered by phpBB © 2001, 2002 phpBB Group :: FI Theme

c++.net ist Teilnehmer des Partnerprogramms von Amazon Europe S.à.r.l. und Partner des Werbeprogramms, das zur Bereitstellung eines Mediums für Websites konzipiert wurde, mittels dessen durch die Platzierung von Werbeanzeigen und Links zu amazon.de Werbekostenerstattung verdient werden kann.

Die Vervielfältigung der auf den Seiten www.c-plusplus.de, www.c-plusplus.info und www.c-plusplus.net enthaltenen Informationen ohne eine schriftliche Genehmigung des Seitenbetreibers ist untersagt (vgl. §4 Urheberrechtsgesetz). Die Nutzung und Änderung der vorgestellten Strukturen und Verfahren in privaten und kommerziellen Softwareanwendungen ist ausdrücklich erlaubt, soweit keine Rechte Dritter verletzt werden. Der Seitenbetreiber übernimmt keine Gewähr für die Funktion einzelner Beiträge oder Programmfragmente, insbesondere übernimmt er keine Haftung für eventuelle aus dem Gebrauch entstehenden Folgeschäden.