Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1449
  • Last Modified:

Keyboard (intercept & modify)

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
rossryan
Asked:
rossryan
  • 7
  • 6
  • 2
  • +1
1 Solution
 
mrwad99Commented:
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
 
jkrCommented:
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
 
DanRollinsCommented:
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
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
DanRollinsCommented:
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
 
jkrCommented:
>>jkr, how long ago was that?

The file says: Last Change date Sep. 22, 2000 :o)
0
 
rossryanAuthor Commented:
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
 
DanRollinsCommented:
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
 
rossryanAuthor Commented:
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
 
DanRollinsCommented:
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
 
rossryanAuthor Commented:
You wouldn't happen to know an easy way to convert ascii characters to virtual keys, would you?
0
 
DanRollinsCommented:
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
 
rossryanAuthor Commented:
You've got the points. I may have one or two follow up comments (questions), but I must say, great job!
0
 
DanRollinsCommented:
Glad to help.  Thanks for the points and the grade.
-- Dan
0
 
rossryanAuthor Commented:
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
 
DanRollinsCommented:
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
 
rossryanAuthor Commented:
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: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

  • 7
  • 6
  • 2
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now