Jump to content
Sign in to follow this  
RedSyphon

_IsPressed Not and/or over recognizing key strokes

Recommended Posts

RedSyphon

Hi All, Hope this is the right location for my question....

I have the following section in my code that tries to detect a code (konami code) and display a text message after it's been entered:

;Show the splash screen
SplashImageOn(<splash code here, it works so not including>)

Dim $dll = DllOpen("user32.dll");Open the dll for input
Dim $code = "" ;Holds the users entered code if any
Dim $i = 0 ;Main loop counter while splash screen is shown

;Goal is to loop for ~5seconds, Using a counter to 50 and a sleep(100) roughly = sleep(5000)
While $i < 50
   ;Loop that will exit if the code has been entered, user has run out of time, and/or a code letter is pressed
   While 1
      ;If the code string has the max code letters in it then check for a valid code
      If StringLen($test) >= 10 Then
         ;If the counter has less than 1 second left, or the code variable has a valid code
         If $i > 40 OR $test = "^^DOWNDOWN<><>BA" Then
            ;exit the main loop
            $i = 51
            ;exit this loop
        ExitLoop
     EndIf
     
         ;Code variable had no valid code but user has time to enter
         $TEST = ""
         ;restart this loop
         ExitLoop
      EndIf

      ;Sleep for a 10th of a second
      Sleep ( 100 )

      ;If a code key is pressed then record it
      If _IsPressed("26", $dll) Then
         $test = $test  & "^"
         ExitLoop
      ElseIf _IsPressed("28", $dll) Then
         $test = $test  & "DOWN"
         ExitLoop
      ElseIf _IsPressed("25", $dll) Then
         $test = $test  & "<"
         ExitLoop
      ElseIf _IsPressed("27", $dll) Then
         $test = $test  & ">"
         ExitLoop
      ElseIf _IsPressed("42", $dll) Then
         $test = $test  & "B"
         ExitLoop
      ElseIf _IsPressed("41", $dll) Then
         $test = $test  & "A"
         ExitLoop
      EndIf

      ;Increse the main loop counter to show a 10th of a second has gone by
      $i = $i + 1
   WEnd
WEnd

;Close out the dll file
DllClose($dll)

;Test if the code was entered!
IF $test = "^^DOWNDOWN<><>BA" Then
   MsgBox(0,"_IsPressed", "KONAMI CODE!")
Else
   MsgBox(0, $test, "FAIL!")
EndIf

SplashOff()

This is more of a easter egg proof of concept... The goal is while the splash page is displayed the user can enter in the code and if done right i'll run further operations accordingly...

The reason I am using two while loops is the following:

1) I need to allow the user to enter a code and if entered in correctly i want to exit the splash screen right away. The inner while loop exits after a valid keystroke. And it will also set the main loop to exit upon a valid code entry, otherwise the program will just display the splash for 5seconds.

2) I also have found that sleeping for more than 1/4second, sleep(250) causes the program to not catch all the key strokes. Likewise anything under 1/10second, sleep(100), causes too multiple key strokes to be recoded!

3) I want to allow the user to type the code sequence as many times as possible within the 5 seconds until the program sees it.. That is why the $test = "", is there at within the inner loop if the user still has more than 1second left.

Note: I receive no errors however entering at a fairly normal typing speed with the above code will result in the second message box displaying after 5seconds with a value that could be anywhere from "^^DOWNAB" to "^B", this is with me entering the code correctly each time..

I realize the code above isn't the nicest to look at however it's just test code at the moment.. My goal is to be able to record the user key strokes in real time...

If anyone has suggestions, alternate methods, etc, etc, your input will be greatly appreciated!!!!

Share this post


Link to post
Share on other sites
Melba23

RedSyphon,

First, welcome to the Autoit forums. :)

Using _Ispressed to capture multiple keystrokes is not the best way to go - as you have discovered. And keyloggers (which do exactly what you want) are persona non grata here because of the obvious possibility of malicious use.

So, why not try an invisible input to capture the keystrokes? The only disadvantage that I can see is that you cannot use any of the cursor movement keys - you are limited to those keys which will display in an Input control. But that still leaves you a lot of scope. ;) Look at this:

; Create invisible GUI
$hGUI = GUICreate("Test", 500, 500)
$hInput = GUICtrlCreateInput("", 10, 10, 100, 20)
WinSetTrans($hGUI, "", 0)
GUISetState(@SW_SHOW)

;Show the splash screen^^
;SplashImageOn("<splash code here, it works so not including>"9^^DD<><>AB

; Loop for exactly 5 seconds
$iBegin = TimerInit()
While TimerDiff($iBegin) < 5000
    ;If the code string has the max code letters in it then check for a valid code
    If StringLen(GUICtrlRead($hInput)) = 10 Then
        ;If the counter has less than 1 second left, or the code variable has a valid code
        If TimerDiff($iBegin) > 4000 Or GUICtrlRead($hInput) = "^^DD<><>BA" Then ExitLoop
    EndIf
    Sleep(10) ; needed to prevent 100% CPU usage
WEnd

;Test if the code was entered!
If GUICtrlRead($hInput) = "^^DD<><>BA" Then
    MsgBox(0, "Success", "KONAMI CODE!")
Else
    MsgBox(0, GUICtrlRead($hInput), "FAIL!")
EndIf

GUIDelete($hGUI)

;SplashOff()

Note that using TimerInit and TimerDiff you can get exact timings without using long Sleeps - you still need a small Sleep in there to prevent the CPU burning up in a tight loop.

If you think this is along the right lines, we could work on it a bit more.

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites
RedSyphon

Thanks for the reply!

I haven't really considered a hidden field to capture the input... I'll play some tonight with this and see how it goes... I'm not too worried about the arrow keys as it's a "easter egg" type of thing anyhow.. All be it was requested :)

I'll be sure to update the post.

Thanks again!

Share this post


Link to post
Share on other sites
RedSyphon

I tried adapting your method above and everything worked great save using the arrow keys.... I decided to merge the two ideas and came up with what I have copied below! It works flawlessly, I appreciate your help and the incite into using TimerInit() + TimerDiff() was killer!

Now that the proof of concept is done I can clean up the code a bit (I hate long if statements), etc.

Thanks Agian!

Copied the code snippet below in the hopes someone else with a similar issue might benefit:

Dim $dll = DllOpen("user32.dll");Open the dll for input
Dim $code = "" ;Holds the users entered code if any

;SpashImage features: Title=Yes, Always On Top, Windows can be moved
SplashImageOn("Skydive Palatka Videoit Media Automation Program",@ScriptDir & "\skydive_palatka.jpg","1024","768","-1","-1",16)

; Loop for exactly 5 seconds
dim $iBegin = TimerInit()
While TimerDiff($iBegin) < 5000
    ;If the code string has the max code letters in it then check for a valid code
    If StringLen($code) = 10 Then
        ;If the counter has less than 2.5 second left, or the code variable has a valid code
        If TimerDiff($iBegin) > 2500 Or $code = "^^dd<><>ba" Then
            ExitLoop
        Else
            $code = ""
        EndIf
    EndIf

    ;If a code key is pressed then record it
     If _IsPressed("26", $dll) Then
        $code = $code  & "^"
        While _IsPressed("26", $dll)
            Sleep(10)
        WEnd
     ElseIf _IsPressed("28", $dll) Then
        $code = $code  & "d"
        While _IsPressed("28", $dll)
            Sleep(10)
        WEnd
    ElseIf _IsPressed("25", $dll) Then
        $code = $code  & "<"
        While _IsPressed("25", $dll)
            Sleep(10)
        WEnd
    ElseIf _IsPressed("27", $dll) Then
        $code = $code  & ">"
        While _IsPressed("27", $dll)
            Sleep(10)
        WEnd
     ElseIf _IsPressed("42", $dll) Then
        $code = $code  & "b"
        While _IsPressed("42", $dll)
            Sleep(10)
        WEnd
    ElseIf _IsPressed("41", $dll) Then
        $code = $code  & "a"
        While _IsPressed("41", $dll)
            Sleep(10)
        WEnd
    EndIf

    Sleep(10) ; needed to prevent 100% CPU usage
WEnd

;Close out the dll file
DllClose($dll)

;Remove the Splash Image and continue running the program
SplashOff()

;Test if the code was entered!
If $code = "^^dd<><>ba" Then
    MsgBox(0, "Success", "KONAMI CODE!")
Else
    MsgBox(0, $code, "FAIL!")
EndIf

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.