Solved

Keyboard (intercept & modify)

Posted on 2004-05-01
16
1,428 Views
Last Modified: 2006-11-17
Here's the standard keyboard callback:

LRESULT CALLBACK KeyboardProc(          int code,
    WPARAM wParam,
    LPARAM lParam
);

Is there a way to change the message or create a new one by hooking into a window?:

wParam
[in] Specifies the virtual-key code of the key that generated the keystroke message.

It is a hook, so what I want to know is if it is read-only, or can I modify the message (or substitute new ones) to get things rolling?
0
Comment
Question by:rossryan
  • 7
  • 6
  • 2
  • +1
16 Comments
 
LVL 19

Expert Comment

by:mrwad99
ID: 10971198
I am not sure this is what you are after, but

http://www.codeproject.com/cpp/sendkeys_cpp_Article.asp

allows you to send keyboard messages to a certain window.  So you could modify this maybe...
0
 
LVL 86

Expert Comment

by:jkr
ID: 10972304
You can definitely modify the message - here's a hook proc that remaps keys (wrote that one when I got a laptop with a different keyboard layout):

typedef struct _tagSWAPENTRY
{
    USHORT  usIn;
    USHORT  usOut;
}   SWAPENTRY,  *PSWAPENTRY;

typedef map<int, int> SWAPMAP;

SWAPMAP       g_map;
SWAPMAP::iterator g_iMap;

LRESULT CALLBACK HookProc   (   int     nCode,  // hook code
                                WPARAM  wParam, // removal flag
                                LPARAM  lParam  // address of structure with message
                            )
{
    PMSG    pmsg    =   ( PMSG) lParam;

    if  (   0   >   nCode   ||  PM_NOREMOVE ==  wParam)
        {
            return  (   CallNextHookEx  (   g_hhk,
                                            nCode,
                                            wParam,
                                            lParam
                                        )
                    );
        }

    if  (       WM_KEYDOWN  ==  pmsg->message
            ||  WM_KEYUP    ==  pmsg->message  
        )
        {
            /* this one is for us, so check key state */
#ifdef _DEBUG
            OutputDebugString   (   "KeySwap->HookProc():\tAction!\n");
#endif
            g_iMap  =   g_map.find  (   pmsg->wParam);

            if  (   g_iMap  !=  g_map.end   ())
                    pmsg->wParam    =   ( *g_iMap).second;
        }

    return  (   CallNextHookEx  (   g_hhk,
                                    nCode,
                                    wParam,
                                    lParam
                                )
            );
}
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 10973773
jkr, how long ago was that?  I recall reading that keyboard hooks can only be used to "monitor" keystrokes and cannot cancel or modify them with newer OSes (...something about a security exploit).

http://msdn.microsoft.com/library/en-us/winui/WinUI/WindowsUserInterface/Windowing/Hooks/AboutHooks.asp
(see ... /HookFunctions/KeyboardProc.asp)

I can't find a specific reference, but the dox refer to the wparam as an [in] parameter  (never [in/out]) and the wording is careful to talk about "monitoring" never modifying.

-- Dan
0
Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
LVL 49

Expert Comment

by:DanRollins
ID: 10973792
On the other hand, this Knoweledgebase article shows code that changes the WM_COMMAND in a WH_GETMESSAGE hook... so I could be way off:
       http://support.microsoft.com/default.aspx?scid=kb;en-us;233263

On the other other hand, the dox for the GetMsgProc spell out...

     After the hook procedure returns control to the system, the GetMessage or
     PeekMessage function returns the message, along with any modifications, to
     the application that originally called it.

While the keyboardhook version of the same paragraph does not say anything about  making modifications.
0
 
LVL 86

Expert Comment

by:jkr
ID: 10973917
>>jkr, how long ago was that?

The file says: Last Change date Sep. 22, 2000 :o)
0
 

Author Comment

by:rossryan
ID: 10974177
I wish I knew more about the Win32 API. I mean, is there a single keyboard buffer, and does that send stroke to the active window, or is there a buffer per window? If so, how can I slam keystrokes into a non-active window? Maybe not through the traditional buffer, but there is some command or callback that sends messages after they are in the buffer to the window, and as each window handles processing differently (notepad vs mplayer)....hmm.

Why does Windows have to make it so bloody hard?

0
 
LVL 49

Expert Comment

by:DanRollins
ID: 10974368
hard... compared to what? :-)

The active window has the focus, so it gets all keystrokes.  You can use alternative APIs:
     keybd_event  
or
     SendInput

to send keystrokes to a running program.  Some apps might malfunction if they get keystrokes while they do not have the focus, but it might be worth a try.
0
 

Author Comment

by:rossryan
ID: 10974624
I'm going to quit while I'm ahead...(Slackware). ;)

Ok, can you provide two examples: one for use with the active window, one which takes a window handle and attempts to send input?

It's going into a dll, and will be injected into a process. I'll use a custom message to send the keys I need.

0
 
LVL 49

Expert Comment

by:DanRollins
ID: 10982535
SendInput is so simple it hardly needs an example, but here's one:

    http://groups.google.com/groups?UTF-8&oe=UTF-8&selm=txYv9.18438%24wG.66279%40rwcrnsc51.ops.asp.att.net

And the API dox can be found here:
   http://msdn.microsoft.com/library/en-us/winui/winui/windowsuserinterface/userinput/keyboardinput.asp
    (see SendInput)

As to sending it to the Active window and some other window, you can just use the same function, but call GetForegroundWindow beforehand.

0
 

Author Comment

by:rossryan
ID: 10983062
You wouldn't happen to know an easy way to convert ascii characters to virtual keys, would you?
0
 
LVL 49

Accepted Solution

by:
DanRollins earned 500 total points
ID: 10983417
When I needed to do that once, I copied the MSDN virtual key table

     http://msdn.microsoft.com/library/en-us/winui/WinUI/WindowsUserInterface/UserInput/VirtualKeyCodes.asp

into a text editor and edited it into a lookup table.

The keycodes for the letters are the same as the ASCII codes for the uppercase version.  This Q might save you some typing:

    http://www.experts-exchange.com/Cplusplus/Q_10203848.html
0
 

Author Comment

by:rossryan
ID: 10983579
You've got the points. I may have one or two follow up comments (questions), but I must say, great job!
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 10984551
Glad to help.  Thanks for the points and the grade.
-- Dan
0
 

Author Comment

by:rossryan
ID: 10992598
Hmm. I call EnableWindow, then SetActiveWindow, but input does not appear unless I alt-tab to that window (then it rapidly fills in). How should I enable the window?
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 10999915
There is a trick involving SetForegroundWindow, but I've never really tried it.  Try a search on Microsoft to find the discussion of that:

    http://search.microsoft.com/search/results.aspx?view=en-us&st=a&qu=SetForegroundWindow
0
 

Author Comment

by:rossryan
ID: 11002336
Hmm. Then I'll set my program to always be on top (fun!), and whichever window is selected will grab the input...
0

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In days of old, returning something by value from a function in C++ was necessarily avoided because it would, invariably, involve one or even two copies of the object being created and potentially costly calls to a copy-constructor and destructor. A…
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.

821 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question