הערה
הגישה לדף זה מחייבת הרשאה. באפשרותך לנסות להיכנס או לשנות מדריכי כתובות.
הגישה לדף זה מחייבת הרשאה. באפשרותך לנסות לשנות מדריכי כתובות.
Question
Thursday, July 30, 2009 6:03 PM
Hi all,
(Sorry, this should have gone to the VB General forum... - can a moderator move it there or do I need to repost?)
I want to have a one second pause after some code has run. During that pause, if a certain key is pressed, I want to do some action. Otherwise, I want the code to continue as normal.
IOW, what would I use to replace the comments in the following code?
myTestCode()
' Wait one second and see if a given key was pressed.
' If specific key is pressed, then show messagebox (or whatever) asking user if we should cancel (whatever)
NextMethodToRun()
Yes, I know there are a number of ways, which is why I am looking for something that is fast and simple to use. I do not want a console window, some other form, etc. to appear. Just want to check if a key was pressed. The key (if pressed) should be pulled off the keyboard buffer
Thanks,
FletcherJ
All replies (29)
Monday, August 3, 2009 9:25 PM ✅Answered | 1 vote
how about this or similar:
Class ErrorClass
public Sub Main
MyStep1()
if CheckDeveloperKey() = true then
DebugStep1()
DebugStep2()
Else
StandardStep1()
StandardStep2()
End If
End Sub
Private Function CheckDeveloperKey as Boolean
if CHKDEVKEY.ShowDialog() = DialogResult.Yes then
Return True
Else
Return False
End If
End Function
End Class
Class Frm_CheckDevKey Inherits Form
public Sub New()
InitializeComponet
'i think we can do this and it will hide the .showdialog form, but if not we just set the form size to 1,1 anyways
Me.Visible = False
me.formborderstyle = None
me.showintaskbar = false
me.size = new size(1,1)
me.location = new point(0,0)
'because i dont know how to return a dialogresult without a button, im doing this:
Dim B1 as new button
dim B2 as new button
b1.dialogresult = dialogresult.Yes
b2.dialogresult = dialogresult.no
me.controls.add(b1)
me.controls.add(b2)
Dim Timer1 as new Timer
me.controls.add(Timer1)
Timer1.Interval = 1100
Addhandler Timer1.tick, Addressof TimerTickPressesYESButton
Timer1.Start
Dim Timer2 as new Timer
Timer2.Interval = 1000
me.controls.add(Timer2)
Addhandler Timer2.tick, Addressof TimerTick2PressesNOButton
Timer2.Start
End Sub
Private Sub TimerTickPressesYESButton
DirectCast(Me.controls("b1"),Button).performClick
End Sub
Private Sub TimerTickPressesNOButton
DirectCast(Me.controls("b2"),Button).performClick
End Sub
Private Sub FormButtonClick("ButtonClickEventArgs Here") Handles me.keypress
if e.key = keys.Enter
DirectCast(me.controls(Timer2),Timer).Stop
End Sub
End Class
Any and All code is provided only as a guide. - learning visual basic
Thursday, August 6, 2009 5:53 AM ✅Answered | 1 vote
FletcherJ
Here is a simple keylogger form this thread:(http://social.msdn.microsoft.com/Forums/en-US/Vsexpressvb/thread/515ca67c-3201-4be1-a08e-72e686cb44cd)
All thats needed on the form is:(you could modified its display mode as console)
Textbox1 = Multiline and vertical scroll bar.
Timer1 set to interval 10 and Enabled
Public Class Keylog1
Dim result As Integer
Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer
Private Sub Keylog1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Timer1.Start()
End Sub
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
For i = 1 To 255
result = 0
result = GetAsyncKeyState(i)
If result = -32767 Then
TextBox1.Text = TextBox1.Text + Chr(i)
End If
Next i
End Sub
End Class
Best wishes
Xingwei Hu
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
Monday, August 10, 2009 3:32 PM ✅Answered
Xingwei,
This is much better than the forms kludge I used and much more in line with what I wanted. It doesn't catch the key I like to use as my "break-in" key, but that's not a major problem. Here is a revised version of your code that doesn't require a timer, etc.
Public Class MyGetKey
Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer
Public Shared Function getKey(ByVal seconds As Decimal) As Integer
Dim intEndTime As Date = Date.Now.AddSeconds(seconds)
Dim intResult As Integer = 0
' Now wait for the desired number of seconds
Do While Date.Now <= intEndTime
' Have they pressed the "End" key?
If GetAsyncKeyState(35) = -32767 Then
intResult = 35
Exit Do
End If
Loop
Return intResult
End Function
End Class
Thanks for pointing me in this direction.
FletcherJ
Thursday, July 30, 2009 8:36 PM | 1 vote
i tried with a button, textbox, and a timer..
timer interval was set to 1500, to give me extra time to press the Enter key in the textbox.
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
TextBox1.Text = "timer1.enabled"
Timer1.Enabled = True
End Sub
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Dim num As Integer = 0
Do Until num = 3
If num = 2 Then
Timer1.Enabled = False
TextBox1.Text = " Timer1.Enabled =False "
End If
num = num + 1
Loop
End Sub
Private Sub TextBox1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles TextBox1.KeyDown
If Timer1.Enabled = True Then
If e.KeyCode = Keys.Enter Then
Me.Text = "ok"
End If
Else
Me.Text = "not ok"
End If
End Sub
End Class
i think it is fairly simple, that i was even able to put the code together.. ;o)
trujade.i like**:** VB General google fast cars username password
Thursday, July 30, 2009 8:51 PM
Trujade,
This would work if I was using a form, but I am not. I am using a class that has a series of methods that execute, one after another. After each one, I wait a second for the user to press a key. If they don't, I just keep going. Otherwise, I ask the user what they want.
I could do this with threading, but that is more complicated than I need. All I want is a method that watches the keyboard for one second and either returns null (if no key pressed) or the key (ascii value or as a char) as soon as a key is pressed. I check the return value to figure out what to do next.
But thanks for the suggestion,
FletcherJ
Thursday, July 30, 2009 10:23 PM
if you are using a class where did you implement the class? Console or Windows Form Application
kaymafI hope this helps, if that is what you want, just mark it as answer so that we can move on
Monday, August 3, 2009 4:17 PM
Kaymaf,
I have a singleton class that is referenced when an error occures. I display a message to the user letting them know about the error and asking them what they want to do. After they click on the button, I then wait to see if a special key has been pressed. If it has, then I will go into a special debug mode (the mode depends on if I am running in debut mode or not) so that I can figure out what happened.
As the dialog may be a messagebox, after the user has responded to the messagebox, I will want to wait to see if the specific key has been pressed.
All I really need is a simple way to monitor the keyboard for one second, checking for some activity and, if there is any, see what key has been pressed. I had sort of thougth that there would be an existing function in VB that would do so.
Thanks,
FletcherJ
Monday, August 3, 2009 6:08 PM | 1 vote
1) the easiest way for your class to gets a key from the keyboard is to have access to a KeyPress event, so have it to inherits from something like Control that will give you this ability
- to pose your thread while staying responsive to the keyboard you can use a loop similar to this
(This give you a +-5 seconds waiting time, but if the key is pressed, the application will continue immediately)
Dim Key As String ' This is set by the KeyPress event
Dim counter As Integer = 0
Do
counter += 1
Threading.Thread.Sleep(100)
Application.DoEvents()
If Key = "5" Then ' Or whatever you want
Exit Do
End If
Loop Until counter = 50
Monday, August 3, 2009 6:19 PM
Crazypennie,
This certainly will work and I have used a approach like this in some other OOP languages. But doesn't VB.NET allow me to define a keypress event and add a handler to any class?
What I was really looking for was something like "if keypress( 1000 ) = 27 then " which would wait 1000 ms to see if an esc key was pressed.
But your response is the closest to an answer I have had so far, thank!
FletcherJ
Monday, August 3, 2009 7:08 PM | 1 vote
You can just do it like that
This will be do the same as above and will return Pressed key if the key was pressed and return "" if no key was pressed
Dim Key As String = "" ' This is set by the KeyPress event
Private Function KeyP(ByVal TimeOut As Integer) As String
Dim counter As Integer = 0
Do
counter += 1
Threading.Thread.Sleep(100)
Application.DoEvents()
If Key <> "" Then ' Or whatever you want
Return Key
End If
Loop Until counter > TimeOut / 100
Return ""
End Function
now, you can use
If KeyP(1000)="B" then
Monday, August 3, 2009 7:12 PM
Instead of using loop, you should use timer.
Its quite possible to achieve exactly like you want if you use your own form to display message than standard MsgBox.
and Flow of your code should be Like
Sub work()
'do work
ShowCustomFormAsMessageBox()
End Sub
Sub CustomFrom_formLoad()
aglobalBooleanInForm=True
Timer1.Start()
'Timer1 should have interval set to 1000ms
End Sub
Timer1_Tick()
Timer1.Stop
globalBooleanInForm=False
continueWork()
End Sub
keyPressEventOfCustomForm()
if GlobalBoolean=true then
check key using passed eventargs
Show Debug Window
Stop Timer1 etc..
End IF
End Sub
Sub ContinueWork()
'work to do if key wasnt pressed
end Sub
Thanks
-@omkarnath
May the force be with you
Monday, August 3, 2009 7:21 PM
Omie,
I appreciate your code, but the goal of the question is to find a way to just see if a key on the keyboard has been pressed, without having to use a form, console window, or control.
Apparently, it is much more difficult than I thought.
From what I have found, there is no way to just check the keyboard for a key unless some type of data entry element exists and is visible to the user.
Essentially, console.in.peek would do the job, if it worked without showing a console screen. But I can't even get that to work as desired.
And while your code works, the form needs to have focus for it to work. So I would have to somehow move it off the screen first (so the user couldn't see it) and then have the timer check it for a value.
Thanks,
Fletcher
Monday, August 3, 2009 7:26 PM
CrazyPennie,
Ok, I have a class based on UserControl. But I can't get it to have focus enough so that the keypress event will fire. I try to set focus to the control, added a textbox and set focus to it, etc. but just can't get the keypress event to fire. So your loop always returns a blank, no matter what keys I press.
Any ideas?
Thanks,
FletcherJ
Monday, August 3, 2009 7:27 PM
The goal of the question is to find a way to just see if a key on the keyboard has been pressed, without having to use a form, console window, or control.
if you are using a class where did you implement the class? Console or Windows Form Application
-kaymaf
I'm just wondering... your application works ? How ??
Thanks
-@omkarnath
May the force be with you
Monday, August 3, 2009 7:49 PM
Fletcher,
I need to know what kind of application you are using,
I First assume that you were using a Window form application, started in the Main method and that you were not showing any windows,
is this right?
Monday, August 3, 2009 7:49 PM
Omie,
This is a windows based application. It has forms.
One example:
There is a global error handler that catches unhandled exceptions. This can fire whereever there is a problem. I catch the error and have a series of steps that are performed. I may want to be able to (as a developer) break into any of the steps. So I want the ability to check the keyboard to see if a special key is pressed. If so, instead of doing anything further, the application will go into a special diagnostics mode that only a developer would find usefull. Otherwise, the user sees a standard interface. The decision needs to be made before the interface is shown as, in some cases, I don't want the interface shown.
There are other places where I could use this, but this gives you the basic idea of why I can't assume that there is a form available, etc.
So, back to my question. How do I, without displaying anything to the user, get the program to just look to the keyboard for one second, checking for a special key. Then, after the second, return either a 0 value or the value of the key pressed?
Thanks,
FletcherJ
Monday, August 3, 2009 7:49 PM | 1 vote
... I display a message to the user letting them know about the error and asking them what they want to do. After they click on the button, I then wait to see if a special key has been pressed. ...
How are you displaying that message? Where is that button? Are those on a form? If so, THAT form should be able to use the keypress handler somewhere, even if that form was constructed in code and not visually.
If you don't want the form hanging around there while the user has the key option, you can hide it instead of closing it. Then close it when you get the key to process, or right before you move on to the next item in your list of error processing. (eg, hide the form on the button click, close the form it as part of the timer tick.)
Monday, August 3, 2009 7:53 PM
Omie
If he has no console and no window, He has to sleep his thread, Otherwise, the thread will reach the end of the main method and the application will terminate
Monday, August 3, 2009 7:55 PM
CRB042,
Suppose I am using a Messagebox.show to display the message?
This is the problem with giving examples. Yes, I can use a form. But that approach has it's limitations for some purposes.
All I want is the ability to see if a key has been pressed in the keyboard - without a form or other visible interface being visible to the user. Is this possible? If so, if the special key is pressed, can I then remove it from the keyboard?
Thanks,
FletcherJ
Monday, August 3, 2009 8:10 PM
Some error occurred
You keep it secret for 1 sec and in this 1 sec you want to check if special key was pressed.
if yes then show Special Debug Window
Else So simple msgbox and continue
is it so ?
( if it is so, you know when will you get error and when program waits for listening to that special keystroke ? )
Thanks
-@omkarnath
May the force be with you
Monday, August 3, 2009 8:33 PM
Fletcher,
If you have no interface at all, WinProc will not receive any messages from Windows, So, No keys can be read
Usualy, to create an application with no user interface, you still create a window that you set "Visible=false"
Without that, as I said, you will not get any message for windows
Monday, August 3, 2009 8:35 PM
Suppose I am using a Messagebox.show to display the message?
Suppose you are. Change it to instancing a form with the keyboard trap code built in to it. The user won't know the difference. You can even have the form use a property of type DialogResult to pass a return value that looks like it came from a messagebox.
Tuesday, August 4, 2009 6:56 PM
Hi all,
Ok, I finally gave up and used what I consider to be a kludge. At some point, I will see what I can find out about writing a routine in C++ or some such that will allow me to look at the keyboard buffer for keys. But for now, I just want to get this done.
So I created a form, with a textbox and timer on it. I have a second object that has a shared method that does the following:
instantiates the form (with a location of -1000,-1000 so the user doesn't see it), passes it a object variable that can be filled when the form closes, then uses the showDialog method so that the form keeps focus.
If a key is presssed or the timer runs out of time, they close the form. In the forms FormClosing method, it updates the object variable passed earlier and closes.
The shared method then gets control again and simply returns the value in the object variable that was passed to the form.
Not elegant or clean, but it does the job and I can now get on with mine.
Thanks again for all your help and suggestions.
Thanks,
FletcherJ
Tuesday, August 4, 2009 9:25 PM | 1 vote
fletcher, i'm not 100% sure of this, but if a user has 4 monitors (Configured in a square, with the Top Left Monitor being the Main Monitor) it may show your form on the bottom right.
Any and All code is provided only as a guide. - learning visual basic
Tuesday, August 4, 2009 11:14 PM
yes, best to set the forms visible state to false, or use Me.Hide() on the load event, or something similar, so the user just can't at all see it.
Wednesday, August 5, 2009 3:48 PM
jwalker343,
I will test this out, but I was under the impression that a negative number was left (or up) and a positive number was down/right. On the other hand, given your scenario, if the bottom right monitor was the primary, then the upper left could represent a negative location and, therefore, show the form.
I guess I could (if VB allows) get the upper left location of all active monitors and subtract 1000 from that.... But I am not sure if this is really worth the effort as such a layout would be quite confusing and I don't believe anyone here would have such a layout.
But, it's worth testing.
Thanks for the heads up,
Fletcher
Wednesday, August 5, 2009 3:50 PM
Give it an insane number like 99999999, then on startup of the form use Me.Hide() this will ensure nobody ever sees it unless they are stupidly stupid.
Wednesday, August 5, 2009 3:51 PM
Michael,
I will test this as well, but I was under the impression that if a form (or control) was invisible, then it couldn't get focus. I need it to be able to have focus so that it can trap the keypress.
But, as with jwalkers comment, it's worth testing - if for no other reason than that I don't, at some future time, make a forms visible property false and assume that it can't get focus.
Take care,
FletcherJ
Wednesday, August 5, 2009 4:13 PM | 1 vote
A control doesn't need fovus for keypresses, the main way to get a working xample is to search for VB Keylogger, it wont be detected by a virus scanner, because it's essentially not really, and, it will help you with your issue.