Seite 1 von 2

GetAsyncKeyState_() zu langsam?

Verfasst: 28.07.2010 15:40
von Tombi
Liebe Community,
habe bisher eine nervige Erfahrung gemacht und bisher keine Lösung gefunden.

Code:

Code: Alles auswählen

Global hWindow,hook

Global Dim Array.b(256)

Structure KBDLLHOOKSTRUCT
  vkCode.l
  scanCode.l
  flags.l
  time.l
  dwExtraInfo.l
EndStructure

Global HWND = 0

Procedure.l myKeyboardHook(nCode, wParam, *p.KBDLLHOOKSTRUCT)
  Char.s  = Space(1)
  If nCode = #HC_ACTION
   
    If wParam = #WM_KEYUP Or wParam = #WM_SYSKEYUP Or wParam = #WM_KEYDOWN Or wParam = #WM_SYSKEYDOWN
     
      If GetAsyncKeyState_(#VK_ESCAPE)                                                ;Escape pressed
          UnhookWindowsHookEx_(hook)
          End
      EndIf
     
     
       GetKeyboardState_(@Array())

      If GetAsyncKeyState_(#VK_SHIFT) Or GetKeyState_($14) > 0
         Check.i=ToAsciiEx_(*p\vkCode,*p\scanCode.l,@dummy, @Char.s,0,GetKeyboardLayout_(0));
      Else
         Check.i=ToAsciiEx_(*p\vkCode,*p\scanCode.l,@array(), @Char.s,0,GetKeyboardLayout_(0));
      EndIf
         
      If Check.i And wParam = #WM_KEYUP
        
        Debug Char.s
        
      EndIf
       

    EndIf
   
  EndIf
  ProcedureReturn CallNextHookEx_(hook, nCode, wParam, *p)
EndProcedure 


  #WH_KEYBOARD_LL = 13
  hook = SetWindowsHookEx_(#WH_KEYBOARD_LL,@myKeyboardHook(),GetModuleHandle_(0),0)
  If hook = 0: End: EndIf
  
  hWindow     = OpenWindow(1,0,0,0,0,"k8D h00K",#PB_Window_Invisible)
  
  Repeat
    WaitWindowEvent()
  ForEver

Probiert es selber aus..
Bei der schnellen(!) Eingabe von "Test" erfolgt des öfteren der Text "test" statt "Test".
Ist ja noch in Ordnung. Nur bei Zeichen wie "ß" statt "?" ist es einfach nervig.

Bei langsamer Eingabe bzw längerem drücken der SHIFT-Taste passiert das nicht,
dann funktioniert immer alles. Aber ich bin einer der schnelleren Sorte :mrgreen:

Jemand ne Idee, das besser zu lösen?

Code stammt hier aus dem Forum, um es eben mal zu zeigen, was ich meine ;-)

MFG,
Tombi

Re: GetAsyncKeyState_() zu langsam?

Verfasst: 28.07.2010 16:18
von alter Mann
probier mal das hier

Code: Alles auswählen

Global hWindow,hook

Global Dim bArray.b(256)

Structure KBDLLHOOKSTRUCT
  vkCode.l
  scanCode.l
  flags.l
  time.l
  dwExtraInfo.l
EndStructure

Global HWND = 0
Global Layout.i

Procedure.l myKeyboardHook(nCode, wParam, *p.KBDLLHOOKSTRUCT)
  Char.s  = Space(1)
  If nCode = #HC_ACTION
   
    If wParam = #WM_KEYUP Or wParam = #WM_SYSKEYUP Or wParam = #WM_KEYDOWN Or wParam = #WM_SYSKEYDOWN
     
      GetKeyboardState_(@bArray())
      
      If *p\vkCode = #VK_ESCAPE                                                ;Escape pressed
          UnhookWindowsHookEx_(hook)
          End
      EndIf

      If bArray(#VK_SHIFT)
         Check.i=ToAsciiEx_(*p\vkCode,*p\scanCode.l,@dummy, @Char.s,0,Layout);
      Else
         Check.i=ToAsciiEx_(*p\vkCode,*p\scanCode.l,@bArray(), @Char.s,0,Layout);
      EndIf
         
      If Check.i And wParam = #WM_KEYUP
       
        Debug Char.s
        Debug *p\scanCode
               
      EndIf
       

    EndIf
   
  EndIf
  ProcedureReturn CallNextHookEx_(hook, nCode, wParam, *p)
EndProcedure

  Layout = GetKeyboardLayout_(0)

  #WH_KEYBOARD_LL = 13
  hook = SetWindowsHookEx_(#WH_KEYBOARD_LL,@myKeyboardHook(),GetModuleHandle_(0),0)
  If hook = 0: End: EndIf
 
  hWindow     = OpenWindow(1,0,0,0,0,"k8D h00K",#PB_Window_Invisible)
 
  Repeat
    WaitWindowEvent()
  ForEver

Re: GetAsyncKeyState_() zu langsam?

Verfasst: 28.07.2010 16:21
von Tombi
Alles Großbuchstaben.

Wenn ich diese Zeile entferne aus deinem Code:

Code: Alles auswählen

Debug *p\scanCode
Alles Kleinbuchstaben :D

MFG,
Tombi

Re: GetAsyncKeyState_() zu langsam?

Verfasst: 28.07.2010 20:42
von alter Mann
ich habe noch mal ein bisschen rumexperimentiert und bin jetzt etwas verwirrt

Code: Alles auswählen

Global hWindow,hook

Global Dim bArray.b(255)

Structure KBDLLHOOKSTRUCT
  vkCode.l
  scanCode.l
  flags.l
  time.l
  dwExtraInfo.l
EndStructure

Procedure.l myKeyboardHook(nCode, wParam, *p.KBDLLHOOKSTRUCT)
  Char.s  = Space(1)
  If nCode = #HC_ACTION
   
    If wParam = #WM_KEYUP ;Or wParam = #WM_SYSKEYUP Or wParam = #WM_KEYDOWN Or wParam = #WM_SYSKEYDOWN
     
      
      If GetAsyncKeyState_(#VK_ESCAPE)                                                ;Escape pressed
          UnhookWindowsHookEx_(hook)
          End
      EndIf
         
      If GetAsyncKeyState_(#VK_SHIFT)
        Check = ToAscii_(*p\vkCode,*p\scanCode.l,@dummy, @Char.s,0)
      Else
         Check.i=ToAscii_(*p\vkCode,*p\scanCode.l,@bArray(), @Char.s,0);
      EndIf
         
      If Check.i
       
        SetGadgetText(1, "Buchstabe : "+Char.s)
        Debug Char       
      EndIf
       

    EndIf
   
  EndIf
  ProcedureReturn CallNextHookEx_(hook, nCode, wParam, *p)
EndProcedure


  #WH_KEYBOARD_LL = 13
  hook = SetWindowsHookEx_(#WH_KEYBOARD_LL,@myKeyboardHook(),GetModuleHandle_(0),0)
  If hook = 0: End: EndIf
 
  hWindow     = OpenWindow(1,0,0,200,50,"k8D h00K",#PB_Window_BorderLess|#PB_Window_ScreenCentered)
 
  TextGadget(1,5,5,150,30,"Buchstabe : ")
   
  Repeat
    WaitWindowEvent()
  ForEver
Hiermit geht es bei mir erstmal. Allerdings gibt es ein paar Merkwürdigkeiten:
- wenn man dummy mit einem Wert belegt kommen nur Kleinbuchstaben
- bArray() muss nicht vorbelegt werden (GetKeyboardState_ brauch nicht aufgerufen werden)

Re: GetAsyncKeyState_() zu langsam?

Verfasst: 28.07.2010 22:00
von Tombi
Keine Änderung:
Bei schnellen Eingaben werden großgeschriebene Zeichen (genutzte SHIFT-Taste) automatisch klein.
Der Befehl zu langsam? Wo ist das Problem?

Getestet auf WinXP Pro SP3 mit PB 4.40 x86

Re: GetAsyncKeyState_() zu langsam?

Verfasst: 28.07.2010 22:55
von alter Mann
kann ich nicht bestätigen (vielleich bin ich auch zu langsam :lol: ), mach mal 'ne exe draus, vielleicht ist der Debugger schuld

Re: GetAsyncKeyState_() zu langsam?

Verfasst: 29.07.2010 00:23
von freak
Das Mischen von GetAsyncKeyState_() und GetKeyState_() ist der Fehler. Der erste Befehl gibt den aktuellen Zustand der Hardware wieder und der zweite gibt den aktuellen Zustand in der Input-Queue des Prozesses wieder. Die Queue ist dem tatsächlichen Zustand hinterher wenn das Programm viel zu tun hat. In diesem Fall (mit hook) macht die asynchrone Version überhaupt keinen Sinn. Also nur GetKeyState_() verwenden und es sollte gehen.

Auserdem sind die Aufrufe falsch:

Code: Alles auswählen

If GetAsyncKeyState_(#VK_ESCAPE) ; Escape pressed
Das ist falsch. Es muss heißen:

Code: Alles auswählen

If GetAsyncKeyState_(#VK_ESCAPE) & $8000 ; Escape pressed
Die Funktion gibt eine (16bit) Bitmaske zurück bei der nur das höchste bit bedeutet "die Taste ist gedrückt". Das niedrigste bit bedeutet "Taste gedrückt seit letztem Aufruf", auf was man sich aber nicht verlassen kann (siehe: http://msdn.microsoft.com/en-us/library/ms646293.aspx)
Das gleiche gilt für GetKeyState_().

Re: GetAsyncKeyState_() zu langsam?

Verfasst: 29.07.2010 12:33
von Tombi
Naja... hab ich was vergessen was du meinst?

Weiterhin habe ich das Problem:
Wenn ich schnell tippe (naja, meine 600 Anschläge pro Minute sind eben doch zu schnell /:-> ),
wird die SHIFT-Taste nicht registriert und dadurch der Text klein statt groß erfasst...

Aus "Ich teste diese Programm!" wird bei schnellem tippen eben dann schnell mal "Ich teste dieses programm1".
Wenn ich langsamer tippe, wird es richtig erfasst.

Wo liegt das Problem? :?
Wir brauchen Speed ... keine Drogen :D

MFG,
Tombi


Edit: Ups, Code vergessen. Hier:

Code: Alles auswählen

;- PureBasic 4.50 (x86)
;

Global hWindow,hook

Global Dim Array.b(256)

Structure KBDLLHOOKSTRUCT
  vkCode.l
  scanCode.l
  flags.l
  time.l
  dwExtraInfo.l
EndStructure

Global HWND = 0

Procedure.l myKeyboardHook(nCode, wParam, *p.KBDLLHOOKSTRUCT)
  Char.s  = Space(1)
  If nCode = #HC_ACTION
   
    If wParam = #WM_KEYUP Or wParam = #WM_SYSKEYUP Or wParam = #WM_KEYDOWN Or wParam = #WM_SYSKEYDOWN
     
      If GetAsyncKeyState_(#VK_ESCAPE) & $8000               ;Escape pressed
          UnhookWindowsHookEx_(hook)
          End
      EndIf
     
     
       GetKeyboardState_(@Array())

      If GetKeyState_($14) > 0
         Check.i=ToAsciiEx_(*p\vkCode,*p\scanCode.l,@dummy, @Char.s,0,GetKeyboardLayout_(0));
      Else
         Check.i=ToAsciiEx_(*p\vkCode,*p\scanCode.l,@array(), @Char.s,0,GetKeyboardLayout_(0));
      EndIf
         
      If Check.i And wParam = #WM_KEYUP
        
        Debug Char.s

      EndIf
       

    EndIf
   
  EndIf
  ProcedureReturn CallNextHookEx_(hook, nCode, wParam, *p)
EndProcedure


  #WH_KEYBOARD_LL = 13
  hook = SetWindowsHookEx_(#WH_KEYBOARD_LL,@myKeyboardHook(),GetModuleHandle_(0),0)
  If hook = 0: End: EndIf
  
  hWindow = OpenWindow(1,0,0,0,0,"k8D h00K",#PB_Window_Invisible)
  
  Repeat
    WaitWindowEvent()
  ForEver

Re: GetAsyncKeyState_() zu langsam?

Verfasst: 29.07.2010 12:45
von Tombi
Sorry wegen Doppelpost, möchte aber nicht den vorherigen Beitrag so lang ziehen...
Hoffe das geht in Ordnung :D


Habe hier mal ein kleines Fenster gebastelt. Bitte mal selber austesten.
Bei schnellen Eingaben wird der Großbuchstabe schnell mal zum Kleinbuchstaben...

Code: Alles auswählen

; PureBasic 4.50 x86


;- Window Constants
;
Enumeration
  #Window_0
EndEnumeration

;- Gadget Constants
;
Enumeration
  #text
EndEnumeration

Global hWindow,hook

Global Dim Array.b(256)

Structure KBDLLHOOKSTRUCT
  vkCode.l
  scanCode.l
  flags.l
  time.l
  dwExtraInfo.l
EndStructure


  If OpenWindow(#Window_0, 255, 175, 600, 300, "Test",  #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_TitleBar )
      TextGadget(#text, 50, 30, 490, 220, "")
  EndIf

Procedure.l myKeyboardHook(nCode, wParam, *p.KBDLLHOOKSTRUCT)
  Char.s  = Space(1)
  If nCode = #HC_ACTION
   
    If wParam = #WM_KEYUP Or wParam = #WM_SYSKEYUP Or wParam = #WM_KEYDOWN Or wParam = #WM_SYSKEYDOWN
     
     
       GetKeyboardState_(@Array())

      If GetKeyState_($14) > 0
         Check.i=ToAsciiEx_(*p\vkCode,*p\scanCode.l,@dummy, @Char.s,0,GetKeyboardLayout_(0));
      Else
         Check.i=ToAsciiEx_(*p\vkCode,*p\scanCode.l,@array(), @Char.s,0,GetKeyboardLayout_(0));
      EndIf
         
      If Check.i And wParam = #WM_KEYUP
        
          SetGadgetText(#text, GetGadgetText(#text)+char.s)
          
      EndIf
      
       
    EndIf
   
  EndIf
  ProcedureReturn CallNextHookEx_(hook, nCode, wParam, *p)
EndProcedure




  #WH_KEYBOARD_LL = 13
  hook = SetWindowsHookEx_(#WH_KEYBOARD_LL,@myKeyboardHook(),GetModuleHandle_(0),0)
  If hook = 0: End: EndIf



Repeat
  
  Event = WaitWindowEvent()
  
  If Event = #PB_Event_CloseWindow
    Quit = 1
  EndIf
  
Until Quit = 1
(Sry, war nur schnell zusammengeflickt. Kein besonderst schöner Code :D )

Re: GetAsyncKeyState_() zu langsam?

Verfasst: 29.07.2010 15:40
von alter Mann
Wahrscheinlich nur ein Verständnisproblem. Du reagierst auf KEY_UP, die meisten Editoren aber auf KEY_DOWN.