Results 1 to 19 of 19

Thread: Capture Key Strokes of Windows

  1. #1

    Thread Starter
    New Member
    Join Date
    Oct 2000
    Posts
    14

    Question

    how can i capture a key stroke of windows
    like a capture Ctrl+B of any application before the
    message run to the active window.

    i want to get it to did a job. and this program will be acted like a deamon process, running at background.
    so how can i create such program.

    tong
    bug is nature.

  2. #2
    Guest
    Use the GetAsyncKeyState API function.


    Code:
    Private Declare Function GetAsyncKeyState _
    Lib "user32.dll" (ByVal vKey As Long) As Integer
    
    
    Private Sub Form_Load()
    
        Timer1.Interval = 100
    
    End Sub
    
    Private Sub Timer1_Timer()
    
        If GetAsyncKeyState(vbKeyControl) Then
            If GetAsyncKeyState(vbKeyB) Then
                Msgbox "Ctrl+B pressed"
            End If
        End If
    
    End Sub

  3. #3
    Guest
    But that will not catch it before it reaches the active window. In order to do so, you would need to create a global (system-wide) hook.

  4. #4
    PowerPoster Chris's Avatar
    Join Date
    Jan 1999
    Location
    K-PAX
    Posts
    3,238
    Will this better?

    Code:
    '//Put this code under the Basic Module
    Option Explicit
    
    Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, ByVal ncode As Long, ByVal wParam As Long, lParam As Any) As Long
    Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer
    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
    Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long
    Public hHook As Long
    
    Public Const WH_KEYBOARD = 2
    Private Const VK_CONTROL = &H11
    
    Public Function KeyboardProc(ByVal idHook As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
        If idHook < 0 Then
            KeyboardProc = CallNextHookEx(hHook, idHook, wParam, ByVal lParam)
        Else
            If (GetKeyState(VK_CONTROL) And &HF0000000) And GetKeyState(vbKeyB) Then
                MsgBox "Ctrl+B"
            End If
            KeyboardProc = CallNextHookEx(hHook, idHook, wParam, ByVal lParam)
        End If
    End Function
    Code:
    '//Put this code under the Form
    Option Explicit
    
    Private Sub Form_Load()
        hHook = SetWindowsHookEx(WH_KEYBOARD, AddressOf KeyboardProc, App.hInstance, App.ThreadID)
    End Sub
    Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
        UnhookWindowsHookEx hHook
    End Sub

  5. #5

    Thread Starter
    New Member
    Join Date
    Oct 2000
    Posts
    14
    thanks.

    and i am so sorry if what i wrote is not clear.

    what i want is
    i want to create my clipboard that get event of a key stroke such as 'Ctrl+A'
    ok when you use any program and you want to keep
    the screen you just press the key, then it activate my program to keep the current screen in memory.

    conclusion
    1. my program will run in background
    2. it keep looking for a signal, a key stroke, to operate some task.

    that is my scenario.

    tong.
    bug is nature.

  6. #6
    Junior Member
    Join Date
    Feb 2001
    Location
    Singapore
    Posts
    24
    Sorry to interrupt,when u run an application in background and keeps looking for events or keystrokes, do you use a timer to constantly check for the events or keystrokes. Is there any other method?

  7. #7

    Thread Starter
    New Member
    Join Date
    Oct 2000
    Posts
    14
    thank you very much heavenhell

    your method like active method that keep refresh, using time, information. it comsume more resources.

    then, i want passive method that waiting for information which coming and response on it. how can we do?


    tong.
    bug is nature.

  8. #8
    Guest
    You would need to create a global hook, and use the KeyboardProc callback function. It's similar to Chris's method, but instead of catching them locally, catch them globally.

  9. #9
    Lively Member
    Join Date
    Jun 2000
    Posts
    124

    Cool On a related note...

    Is there a way to catch all messages of any sort set to a window? The idea is to record all the mouse and keyboard messages so they can be replicated later.
    On Error Resume Screaming...

  10. #10
    coder. Lord Orwell's Avatar
    Join Date
    Feb 2001
    Location
    Elberfeld, IN
    Posts
    7,628

    Cool

    No, a timer isn't the only way. You could have your program simply loop back on itself and give system time back with a doevents(). Have it execute code every 100 clock ticks or whatever.
    Also, pressing the print screen button already saves what's on display to the clipboard FYI.
    Capturing the keyboard and mouse:
    You need to use several different api calls.
    Use the ones above for the keyboard.
    Use this one for mouse position:
    Declare Function GetCursorPos& Lib "user32" (lpPoint As POINTAPI)
    Type POINTAPI ' 8 Bytes
    x As Long
    y As Long
    End Type
    Obviously, position will only need to be read when a button has been pressed on the mouse.
    I can't currently recall how to detect mouse presses. It wouldn't be hard if they click a form of yours.
    The only other way i can think of right now is to subclass the message handler and detect the wm_lbuttondown or whatever. A side effect of this is to negate the need for the GetCursorPos api, since mouse x and y client positions are returned.
    If any one knows an easier way, please post it. I've been puzzling on this one myself.
    My light show youtube page (it's made the news) www.youtube.com/@lightsofelberfeld
    Contact me on the socials www.facebook.com/lordorwell

  11. #11
    coder. Lord Orwell's Avatar
    Join Date
    Feb 2001
    Location
    Elberfeld, IN
    Posts
    7,628

    Smile

    OK, going with what i said earlier, i did some research and found out that you can actually use the GetAsyncKeyState function shown above to determine the status of the mouse buttons. The Virtual Keys are:
    VK_LBUTTON (&H01)
    VK_RBUTTON (&H02)
    VK_MBUTTON (&H04)
    And If your mouse buttons are swapped, it doesn't make
    any difference to the function. It detects the actual buttons themselves. Hope this helps.
    If you are interested in recording every keystroke, your program might benefit from this subroutine:

    Declare Function GetKeyboardState Lib "user32" _(pbKeyState As Byte) As Long
    Private Sub Timer1_timer()
    Dim keyarray(256) As Byte
    dim dl
    dl& = GetKeyboardState(keyarray(0))
    control% = keyarray(vbKeyControl)
    b% =keyarray(vbKeyB)
    if (control% AND 128) = TRUE And (B% AND 128) = _
    TRUE then msgbox "You pressed ctrl-b"

    Virtual key codes work like indexes to the array. Bit one
    of each index is "on" or "off" for toggle keys like caps lock. Bit 7 is 1 or 0 depending on if a button was pressed when the snapshot was taken.
    So you could have just one API call to "snapshot" the
    keyboard button status. This method is superior because of the time involved. Someone might have pressed ctrl-b (or whatever) and while you are processing the ctrl request using getasynckeystate, they might no longer have b pressed. My method insures you can tell they were both pressed at the same time.
    If you want to actually INTERCEPT keyboard messages meant for an application and then prevent them from reaching that application, you would have to use some form of subclassing .dll or .ocx, since a vb program can only subclass itself. Since windows messages are sent to the top level window and trickle down to the child window that needs the message, i would guess that (if its possible) you would need to subclass the message handler of the desktop. If windows won't let you, you would need to subclass the message handler of each parent window open. Unless there is a specific application that you had in mind.
    Last edited by Lord Orwell; Feb 10th, 2001 at 10:26 PM.
    My light show youtube page (it's made the news) www.youtube.com/@lightsofelberfeld
    Contact me on the socials www.facebook.com/lordorwell

  12. #12
    Lively Member
    Join Date
    Jun 2000
    Posts
    124
    So, get keyboardstate can check the mouse buttons too? That's cool.

    Now, let me see if I understand what you've got there.

    keyarray is an array of 256 bytes, and when you do
    dl& = GetKeyBoardState(keyarray(0)) it is filling keyarray with the "on" or "off" information for every key.

    the b% = keyarray(VK_B) is true or false, and it determines this by checking the status of the byte with an index of VK_B. one question there. I know VK_B is a virtual key constant, but isn't it some weird hex number? If it's going to be an index number, doesn't it have to be an integer? oh, and what does the % after a variable name do?

    then, if(B% and 128) = true. What does the 128 mean? I can see that the b% is checking if the previous statement returned true, but what relevance does the 128 have?

    Sorry if I seem dense, but those couple things are confusing me.
    On Error Resume Screaming...

  13. #13

    Thread Starter
    New Member
    Join Date
    Oct 2000
    Posts
    14

    Cool

    YES, All of it's really COOL.........

    for all of your reply it is work very well..

    i have got and see that is a solution.....

    thanks everyone

    tong,
    bug is nature.

  14. #14
    coder. Lord Orwell's Avatar
    Join Date
    Feb 2001
    Location
    Elberfeld, IN
    Posts
    7,628
    an answer to each question you posed about my code:
    the keyboard array is filled with the following info: bit 7 is up/down info and bit one is on/off info. thus when i and the value by 128 (binary bit 7) i am ignoring the other bits. 1000000 = 128.
    wierd hex number... hex numbers are really regular numbers represented in hex notation...
    The API function is designed so that the virtual key you want to check for corresponds with that same index number in the array.
    the % (and &) after a variable simply signify what kind of data the variable contains. check your help file, or visit this thread:
    http://forums.vb-world.net/showthrea...2&goto=newpost
    for an indepth discussion of the use (and why i, in particular, use them) of these symbols.
    Hope this helps explain not only how, but WHY my code works.
    My light show youtube page (it's made the news) www.youtube.com/@lightsofelberfeld
    Contact me on the socials www.facebook.com/lordorwell

  15. #15
    coder. Lord Orwell's Avatar
    Join Date
    Feb 2001
    Location
    Elberfeld, IN
    Posts
    7,628
    heh heh buggy code. I can possibly see how (b and 128) = true could confuse you. I meant to type:
    (ctrl and 128) > 0
    (b and 128) > 0
    {blush} You might get errors ...
    My light show youtube page (it's made the news) www.youtube.com/@lightsofelberfeld
    Contact me on the socials www.facebook.com/lordorwell

  16. #16
    Lively Member
    Join Date
    Jun 2000
    Posts
    124

    Cool

    actually, i hadn't tested it yet, and just figured that true would evaluate to 1.
    On Error Resume Screaming...

  17. #17
    Addicted Member
    Join Date
    Feb 2001
    Location
    Classified
    Posts
    234
    Hmm, i think what ive been wondering was basicaly the same as what tongbiscom originaly wanted,,,

    .... A Key logger
    My ICQ Status: (85634850)

    Seriously Sick Tshirts

  18. #18
    Junior Member
    Join Date
    Feb 2001
    Location
    Singapore
    Posts
    24
    Quoted:
    You could have your program simply loop back on itself and give system time back with a doevents(). Have it execute code every 100 clock ticks or whatever

    How do you this?? Can someone tell mi how this can be done.

    Thanks

  19. #19
    coder. Lord Orwell's Avatar
    Join Date
    Feb 2001
    Location
    Elberfeld, IN
    Posts
    7,628
    sub main()
    'sub main is required if youdon't have a form
    dim zz as boolean
    do
    for cl = 1 to 100'set to some arbitrary number.
    'the larger the better.
    doevents()
    next cl
    zz= CheckForKeypressSub(ctrl-b)
    'checkforkeypresssub is your sub (shown before)
    'that you will check for keypresses with
    if zz = true then call DoMeWhenTrue()
    'DoMeWhenTrue is the code you want activated when
    'ctrl-b or whatever is pressed.
    'the beauty of this method is it's impossible to call the
    'routine more than one time, since keypress checking
    'stops while the code is being done.
    loop
    My light show youtube page (it's made the news) www.youtube.com/@lightsofelberfeld
    Contact me on the socials www.facebook.com/lordorwell

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width