Solved

Keyboard (intercept & modify)

Posted on 2004-05-01
16
1,397 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
 
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
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
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

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Templates For Beginners Or How To Encourage The Compiler To Work For You Introduction This tutorial is targeted at the reader who is, perhaps, familiar with the basics of C++ but would prefer a little slower introduction to the more ad…
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.

757 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

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now