Toon posts:

[C#] GetAsyncKeyState problemen met barcode scanner

Pagina: 1
Acties:
  • 160 views sinds 30-01-2008
  • Reageer

Verwijderd

Topicstarter
Ik ben hier in het bezit van een barcode pen scan (Champ BS3215 voor de geïnteresseerde). Deze scanner is via USB aangesloten en gedraagt zich verder als een keyboard. Zover alles prima. Als ik een barcode scan in bijvoorbeeld notepad verschijnt deze netjes in beeld.

Nu is het de bedoeling dat er een applicatie op de achtergrond komt te draaien welke zodra er een barcode gescand wordt een aantal acties onderneemt. Het moet dus niet uit maken welk programma er op dat moment actief is. Zodra er een barcode gescand wordt moet dit door deze applicatie worden opgevangen.

Het probleem
Het scannen van een barcode is een klein onderdeel van een veel grotere applicatie. Tijdens het wachten op het leveren van de barcode scanner heb ik een keylogger in de applicatie ingebouwd welke alle toetsaanslagen registreerde. Zo kon ik mbv. 13 getallen intikken het scannen van een barcode simuleren. Mij verwachting was dat deze techniek ook zou moeten werken bij een daadwerkelijke barcode scanner. Dit werkt echter niet. Ik krijg meestal maar de helft van alle gescande getallen binnen of juist veelte veel getallen, en vaak ook gewoon helemaal niks. Terwijl ik in notepad keurig 13 cijfers in beeld krijg. Het lijkt wel of de GetAsyncKeyState() functie te traag is om alle cijfers af te vangen. Het omlaag zetten van de BAUD Rate (snelheid waarmee er over de lijn verstuurd wordt) en het toevoegen van een timeout tussen het sturen van de getallen geeft echter geen ander resultaat.

Het afvangen van de toetsaanslagen doe ik op de volgende manier:
C#:
1
2
3
4
5
6
7
8
9
10
11
while (run) {
    foreach (int i in Enum.GetValues(typeof(Keys))) {
        if (GetAsyncKeyState(i) != 0) {
            keybuffer += Enum.GetName(typeof(Keys), i);  // add the pressed key to the keybuffer
        }
    }

    if (containsBarcode(keybuffer)) {
        doeHeleGafeDingenMetDeBarcode()
    }
}


Deze code werkt prima met toetsen die ik op mijn muis indruk en/of toetsenbord. Met de barcode scanner dus alleen niet. Ook het proberen om de thread even te laten slapen alvorens deze opnieuw de aanslagen te laten checken, alsmede het implementeren van een timer die na een vast interval alle toetsaanslagen ophaalde werken niet naar behoren.

Doe ik iets structureels fout? Of is de GetAsyncKeyState() functie niet bedoeld voor mijn toepassing. Zo ja is er een andere manier waarmee ik toetsaanslagen kan afvangen?

  • BasieP
  • Registratie: Oktober 2000
  • Laatst online: 19-10 08:18
heeft het er misschien mee te maken dat je scanner op de USB poort zit? dit is niet 'zomaar' een keyboard. Dat hangt een beetje af van de driver. Ik heb ook wel eens gezien dat er drivers geinstalleerd werden die zelf alles afhandelen, en vervolgens een keypress simuleren (dwz, de actieve applicatie opzoeken en daar tekst naartoe gooien)
in dat geval worden er misschien een aantal dingen overgeslagen, kan je het apparaat niet tussen je keyboard en je pc zetten? of heeft hij daar geen stekkers voor?

het zou kunnen dat dit bij jouw ook zo is.

[ Voor 10% gewijzigd door BasieP op 07-05-2007 14:03 ]

This message was sent on 100% recyclable electrons.


Verwijderd

Topicstarter
Het toetsenbord waarvan hij wel alle aanslagen registreerd is ook via USB aangelosten, verder heb ik ook geen drivers voor de scanner geïnstalleerd. Hij werkte out-of-the-box.

edit:
Even gekeken en de scanner gebruikt dezelfde drivers als mijn toestenbord (de standaard Microsoft drivers). Verder zijn er ook geen drivers/api's oid beschikbaar op de website van de fabrikant. Dat zou trouwens ook niet gewenst zijn want de applicatie zou moeten blijven werken ook als er ooit van barcode scanner gewisseld mocht worden.

[ Voor 51% gewijzigd door Verwijderd op 07-05-2007 14:11 ]


  • .oisyn
  • Registratie: September 2000
  • Nu online

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op maandag 07 mei 2007 @ 13:57:
Het lijkt wel of de GetAsyncKeyState() functie te traag is om alle cijfers af te vangen.
Duh! GetAsyncKeyState geeft een snapshot van de state van een bepaalde toets. De scanner stuurt waarschijnlijk een key-down onmiddelijk gevolgd door een key-up. Precies daartussen moet jij de GetAsyncKeyState doen om de juiste toetsen op te vangen. Je kan ook wel uitlezen of ie is ingedrukt sinds de vorige aanroep, maar dan weet je alsnog niet hoe vaak hij is ingedrukt of in welke volgorde de verschillende getallen zijn ingevoerd. Dit is dan ook de verkeerde methode, je moet gewoon naar de WM_KEYDOWN en WM_KEYUP berichten luisteren (of simpelweg de WM_CHAR berichten, die per WM_KEYDOWN worden verstuurd, aangezien je toch niet geinteresseerd bent in het daadwerkelijk indrukken en loslaten van de toets)

[ Voor 13% gewijzigd door .oisyn op 07-05-2007 14:25 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Topicstarter
.oisyn schreef op maandag 07 mei 2007 @ 14:23:
[...]

Duh! GetAsyncKeyState geeft een snapshot van de state. De scanner stuurt waarschijnlijk een key-down onmiddelijk gevolgd door een key-up. Precies daartussen moet jij de GetAsyncKeyState doen om de juiste toetsen op te vangen. Dit is dan ook de verkeerde methode, je moet gewoon naar de WM_KEYDOWN en WM_KEYUP berichten luisteren (of simpelweg de WM_CHAR berichten, die per WM_KEYDOWN worden verstuurd, aangezien je toch niet geinteresseerd bent in het daadwerkelijk indrukken en loslaten van de toets)
GetAsyncKeyState geeft ook terug welke keys er ingedrukt zijn sinds de laatste keer dat je GetAsyncKeyState aanriep. Zie http://msdn2.microsoft.com/en-us/library/ms646293.aspx
The GetAsyncKeyState function determines whether a key is up or down at the time the function is called, and whether the key was pressed after a previous call to GetAsyncKeyState.
Ook als ik hem alle aanslagen laat printen en de thread even 10 seconde stil leg na 1 keer de while loop doorlopen te hebben, krijg ik netjes alle in de tussentijd ingedrukte toetsen te zien.

Edit:
Grapje, je post niet helemaal goed doorgelezen. Inderdaad krijg je dan wel een rommelmoesje van alle keys, en niet de juiste volgorde. Dit loste ik destijds op door hem met tussenpauze's van enkele miliseconden op te vragen. Dit werkt dus niet met een barcode scanner.

Ik ga even kijken naar WM_CHAR berichten, thnx

[ Voor 11% gewijzigd door Verwijderd op 07-05-2007 14:31 ]


  • Shezzie
  • Registratie: Januari 2005
  • Laatst online: 01-12 11:21

Shezzie

Lekker hoor!

Als je hardware op een usb-poort hebt zitten, zit hij intern op een com-poort(COM10 oid). Het makkelijste wat je kunt doen is denk ik "klassiek" de poort openen, peeken of er data is en die verwerken, dit alles in een timer die elke 100ms afgaat.

Je checkt nu alle mogelijke toetsen af per character op de poort, dit duurt (relatief) lang en lijkt me niet geheel en al bedoeld voor een barcode lezer: dat ze hetzelfde stekkertje hebben wil niet zeggen dat ze hetzelfde werken :+

  • .oisyn
  • Registratie: September 2000
  • Nu online

.oisyn

Moderator Devschuur®

Demotivational Speaker

Shezzie schreef op maandag 07 mei 2007 @ 14:38:
Je checkt nu alle mogelijke toetsen af per character op de poort, dit duurt (relatief) lang en lijkt me niet geheel en al bedoeld voor een barcode lezer: dat ze hetzelfde stekkertje hebben wil niet zeggen dat ze hetzelfde werken :+
De tijd heeft er niets mee te maken, bovendien check je niet op de poort maar query je gewoon de driver. Alle informatie voor die functie staat namelijk al op de PC, het is niet zo dat het apparaat bij gaat houden welke toetsen er zijn ingedrukt oid. :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Topicstarter
Oplossing voor mensen die geintereseerd zijn:

Ik heb op The Code Project een artikel gevonden over het gebruik van keyhooks. Na wat testen blijkt dit ook voor ons een goede oplossing te zijn. Deze gaan we dus implementeren.

http://www.codeproject.com/csharp/GlobalSystemHook.asp
Pagina: 1