Re: How to avoid that a key can be hold down



On 1 Aug, 03:41, Stefan Mueller <seekw...@xxxxxxxxx> wrote:

First of all thanks a lot for your great help and
your code. It does exactly what I was looking for
but in my project I have some very strange behavior.
Here my open questions and problems:

1) Why do I need
CallNextHookEx Hook, ncode, wParam, ByVal lParam
I don't see any differences if I omit it.

Because Microsoft specifically recommend it for various reasons. In
fact on second thoughts I should have been using it in the following
manner (as a proper function returning a value):

KeyboardProc = CallNextHookEx(Hook, ncode, _
wParam, ByVal lParam)

If you want to see details of this stuff have a look at:

http://msdn2.microsoft.com/en-us/library/ms644984.aspx

2) Please add
MsgBox ("Key: " & (wParam And &HFF))
just before
CallNextHookEx Hook, ncode, wParam, ByVal lParam
Now start the code with Run - Start (not with F5!)
and press a key (e.g. 'F10') just once.

I can see the result you are getting, but whatever the reason (see
below) it really is not very wise to add extra code to a hook
procedure of any kind other than the code you require to quickly
process the hooked procedure to your requirements and immediately pass
it on to the rest of the system. You certainly should not be putting
"show stopping" things like message boxes in a hook procedure.

3) Please replace the just added line
MsgBox ("Key: " & (wParam And &HFF))
with
Form1.List1.AddItem "Key: " & (wParam And &HFF)
Now start the code again with Run - Start
(not with F5!) and press again a key (e.g. 'F10')
just once. Do you understand what's going on?
The ListBox gets somehow continuously filled with
the just pressed key information.

Yes. I noticed that as well. It occurs with a ListBox but not with
other things. However, the code we're currently using is complicated
by the fact that we are using both the KeyDown event and the hook
procedure itself to partially process they key press, which as I said
previously is not really a good idea. perhaps we should do it
differently, so that all the required code is in the hook procedure.
Also, the code I postred was rather quickly "knocked up" and I might
have placed one of the code lines on the wrong side of an If End If
block. I'll have another look later to check it out.

I/we could get it running but it will always be
somehow critical (e.g.if I press Ctrl+Break, so
that the UnHookKeyboard has not be executed.)

I'm sure we can. But you must realise that any hooking of this kind is
by its very nature dangerous, especially when you run the code in the
IDE. You must take great care to stop your program properly in the
normal way, and not use Run / End or anything of that nature. That's
because with hooks you need to make sure that the "code that processes
the hook" (the hook code in the module) is always present in memory
while the hook is in operation (with other forms of hooking, for
example system wide hooks, it is even more dangerous if you don't do
it properly). Also, when running hooking code in the IDE any error
break due to a coding error will completely kill the IDE. Running such
code as a compiled exe does not present anywhere near as much as a
problem, and is usually very sound. There are various techniques that
use a clever manipulation of the messaging system to allow "safe in
the IDE" hooking if you're really worried about it. I can't remember
now, but I think there is an example on the VBAcvcelerator site or
somewhere similar.

I'd really like to understand what's going
on in my/your code.

In that case perhaps you should start off by simplifying things a
little to check stuff out. For example, place all code relating to
your desired function in the hook procedure itself and get rid of the
associated stuff in the KeyDown event. Then you'll be able to perform
a few experiments and check out the results against the information in
the above MSDN link. The first things to realise when writing your
hook code is that the value you return in your hook function "tells
the system" whether or not you have completely finished with the job.
Returning a value of -1 for example tells the system that we're done.
This allows you to completely "eat" a keystroke (since we're doiung
keyboard hooking at the moment) so that your VB app will behave as
though the key had not actually been pressed. This is not usually the
required acrtion, but it is useful when we want to do something
*instead of* the normal thing that would get done, rather than *as
well as* the normal thing.

Also, you need to realise that running VB code in the IDE is not
anywhere near as straightforward as running the equivalent compiled VB
exe file. That's because the VB IDE itself has a hook into the system
as well as your running code (which probably explains many of the
various symptoms you've noticed when performing your tests in the
IDE). For example, start a new VB project with one TextBox on yourt
Form and paste in the following Form and Module code. Run the code in
the VB IDE and type something into the TextBox. Each time you press
the letter "E" (the hooked key) you will see two DOWN "events"
followed by two UP "events" (showing our hook code is run twice each
time a key is pressed). That's because the VB IDE (which is in many
ways effectively running as an old fashioned BASIC Interpreter for
your code) also has a hook into this stuff as well.

Run exactly the same code as a compiled exe and you will see that this
time there is only one DOWN and one UP "event". So that sort of stuff
sometimes needs to be considered when running code in the IDE,
depending on exactly what job your hook code is doing.

Now, as a different test, change the very first occurrence of:

KeyboardProc = CallNextHookEx(Hook, ncode, _
wParam, ByVal lParam)

in the code module KeyBoardProc so that it is:

KeyboardProc = -1

Now run the code again in the IDE. You'll see that there is now only
one DOWN and one UP (whereas before there were two). More importantly,
you'll notice that the letter "e" does not actually appear in the
TextBox. Note that the code below is in some cases deliberately "long
winded" and I don't hold out this example code as a finished product,
or as an explanation of how all this stuff works, because to be frank
I'm only really beginning to investigate the finer details of this
hooking stuff properly myself (although I do understand basically how
it works and I can do all sorts of tricks with it). The code I've
posted here and in my previous responses should really be looked upon
as a sort of "testbed" routine. But it should be a good start for you.
Personally, when you've investigated the hooking procedures in more
detail, I would advise that you place *all* code to the the entire job
you wish to do (or, better still, place sufficient code in the hook to
detect your required condition and to "trigger" the appropriate "main
action" in an event in your Form) rather than doing the sort of "mix
and match" that we are currently doing in which we carry out half the
task in the Form using its KeyPreview and the other half in the hook.

Regarding your desire to find another way around this problem that
does not involve hooking there will no doubt be a way of doing it if
you think about it hard enough, but I would in any case still suggest
that you do it "the hooking way" if for no other reason than to learn
about hooking. The reason I say that is because there will be other
jobs you come across that simply cannot be carried out in any other
way and using a hook is essential if you want to carry out those jobs
(there are lots and lots of such tasks I can think of). Anyway, here's
the example code that I mentioned:

Mike

' *** START OF FORM CODE ***
Option Explicit
Private Sub Form_Load()
HookKeyboard
End Sub

Private Sub Form_Unload(Cancel As Integer)
UnHookKeyboard
End Sub
' *** END OF FORM CODE ***
'
' *** START OF MODULE CODE ***
Option Explicit
Private Declare Function SetWindowsHookEx Lib "user32" _
Alias "SetWindowsHookExA" (ByVal idHook As Long, _
ByVal lpfn As Long, ByVal hmod As Long, _
ByVal dwThreadId As Long) As Long
Private Declare Function CallNextHookEx Lib "user32" _
(ByVal hHook As Long, ByVal ncode As Long, _
ByVal wParam As Long, lParam As Any) As Long
Private Declare Function UnhookWindowsHookEx Lib "user32" _
(ByVal hHook As Long) As Long
Private Const WH_KEYBOARD As Long = 2
Private Hook As Long

Public Sub HookKeyboard()
Hook = SetWindowsHookEx(WH_KEYBOARD, _
AddressOf KeyboardProc, App.hInstance, App.ThreadID)
End Sub

Public Sub UnHookKeyboard()
UnhookWindowsHookEx Hook
End Sub

Public Function KeyboardProc(ByVal ncode As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
If ncode >= 0 Then
If (wParam And &HFF) = vbKeyE Then
If (lParam And &H80000000) <> 0 Then
Form1.Print "Up"
Else
Form1.Print "Down"
End If
KeyboardProc = CallNextHookEx(Hook, ncode, _
wParam, ByVal lParam)
Else
KeyboardProc = CallNextHookEx(Hook, ncode, _
wParam, ByVal lParam)
End If
Else
' we must not perform any action if ncode < 0
KeyboardProc = CallNextHookEx(Hook, ncode, _
wParam, ByVal lParam)
End If
End Function
' *** END OF MODULE CODE ***



.



Relevant Pages

  • Re: More than 4 IDE devices?
    ... >Buy a PCI controller card and use it for the other devices. ... >to a maximum of eight IDE devices; usually four on the motherboard and, ... I want to hook up two cd roms and three ... I think that makes 10 hard disks plus as many CDROM/DVD ...
    (microsoft.public.windowsxp.hardware)
  • Re: Problems with drive...
    ... Is it a IDE or USB connection? ... I get the same thing when I hook up my camera, ... Prev by Date: ...
    (microsoft.public.windowsxp.hardware)
  • Re: hook calc.exe in vb
    ... Problem is if you intend to hook other apps/threads, ... so it will work within your app. ... Either way be advised windows hooks can be decidedly unfriendly to the ... hook is active without crashing the IDE. ...
    (microsoft.public.vb.winapi)
  • Re: hook calc.exe in vb
    ... I'm not really sure that hook is the best way to do that (in fact, ... > crash trying to do it from within your app. ... > Either way be advised windows hooks can be decidedly unfriendly to the ... > hook is active without crashing the IDE. ...
    (microsoft.public.vb.winapi)
  • Re: SysHook and STATUS_ACCESS_VIOLATION
    ... > Excuse me you claim Microsoft has a hooking library, ... Once you hook you can never unhook! ... > Don Burn (MVP, Windows DDK) ... >> So, before write so much STUPID, probably you have to listen my answer, ...
    (microsoft.public.development.device.drivers)