Question

How to Detect WM_KEYUP and WM_KEYDOWN in a KeyboardHook procedure using WPARAM and LPARAM

Asked by: ramavorray

I have a KeyboardHook (as a DLL) which senses all keyboard activity and it is of type WH_KEYBOARD

The keyboard hook is working well and the keyboard callback procedure is called with parameters WPARAM and LPARAM

I am able to sense the key pressed (like VK_A, VK_DOWN) but I am not able to sense KEYUP/KEYDOWN

I tried many alternatives including code found online (even on EE) but it doesn't work.

When a key is hit my Keyboard Callback Procedure is being called multiple times instead of only one time (that is, when key is pressed)

Code snippets are attached.

I am using Visual Studio 2005 and running on Windows XP Professional 32bit system

//Keyboard Hook Procedure inside in the DLL which posts a message to my application
KEYDLL3_API LRESULT CALLBACK hookproc(int ncode,WPARAM wparam,LPARAM lparam)
{
	if(ncode>=0)
	{
		if((lparam & 0x80000000) == 0x00000000)//Check whether key was pressed(not released).
		{
			hwnd = FindWindow("#32770","Keylogger Exe");//Find application window handle
			PostMessage(hwnd,WM_USER+755,wparam,lparam);//Send info to app Window.
		}
	}
	return ( CallNextHookEx(hook,ncode,wparam,lparam) );//pass control to next hook in the hook chain.
}
 
 
 
//the keyboard callback function in my application which received 
//WPARAM and LPARAM. During the multiple number of times this function 
//is getting called it is always going to the line if(w == VK_SPACE || w == VK_DOWN). It is not resulting any KEYUP/KEYREPEAT events
LRESULT CKeyexeDlg::processkey(WPARAM w, LPARAM l)//This block processes the keystroke info.
{
	if (l & 0x80000000) // check bit 31 for up/down
	{
		//KEY UP
	}
	else
	{
		if (l & 0x40000000) // check bit 30 for previous up/down
			//KEY REPEAT
 
		else
		{
			if(w == VK_SPACE || w == VK_DOWN)
			{
				//the virtual character
			}
		}
	}
 
//I tried the other alternative. But it doesn't even enter into the switch block.
	LPMSG m=(LPMSG)l;
	switch(m->message)
	{
	case WM_KEYDOWN:
		l=l;
		break;
	case WM_KEYUP:
		break;
	case WM_CHAR:
		break;
	};

                                  
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:

Select allOpen in new window

This Question has been solved and asker verified All Experts Exchange premium technology solutions are available to subscription members.

Subscribe now for full access to Experts Exchange and get

Instant Access to this Solution

  • Plus...
  • 30 Day FREE access, no risk, no obligation
  • Collaborate with the world's top tech experts
  • Unlimited access to our exclusive solution database
  • Never be left without tech help again

Subscribe Now

Asked On
2008-07-23 at 07:34:21ID23588637
Tags

C++

,

firefox

Topics

Windows Programming

,

C++ Programming Language

Participating Experts
2
Points
250
Comments
29

Trusted by hundreds of thousands everyday for fast, accurate and reliable tech support.

  • "The time we save is the biggest benefit of Experts Exchange to Warner Bros. What could take multiple guys 2 hours or more each to find is accessed in around 15 minutes on Experts Exchange." Mike Kapnisakis, Warner Bros.
  • "Our team likes having a resource that is more secure than just using Google and most experts using this service really know their stuff. It's nice to look here first versus using Google." Dayna Sellner, Lockheed Martin
  • "Anytime that I've been stumped with a problem, 9 out of 10 times Experts Exchange has either the accepted solution or an open discussion of the potential solution to the problem." Kenny Red, eBay Inc.

See what Experts Exchange can do for you.

Got a question?

We've got the answer.

Experts Exchange has been collecting answers to technology questions since 1996…3 million and counting! If you have a question, chances are we already have your answer.

Screenshot of Experts Exchange Knowledgebase

Need individual assistance?

Our experts are ready to help.

If you can't find the exact answer you're looking for, ask our exclusive community of 50,000 experts. You’ll get a personalized answer from a trusted professional.

Screenshot of Experts Exchange Knowledgebase

Want to learn from the best?

Read articles from industry experts.

Thousands of free tech tips, tricks, how-to’s and tutorials are available in our peer reviewed articles section. See for yourself how smart our experts are, no login required.

Screenshot of an Article

Working on a long term project?

Store your work and research.

Save solutions to your questions, answers you’ve discovered through searching plus helpful articles in your personal knowledgebase for easy future access.

Screenshot of Experts Exchange Knowledgebase

Access the answers to your technology questions today.

Subscribe Now

30-day free trial. Register in 60 seconds.

What Makes Experts Exchange Unique?

Members of the expert community talk about why the experience at Experts Exchange is different than what you will find anywhere else.

Trusted by the world's most respected brands.

image of each brand's logo

Faithfully serving IT professionals since 1996.

Experts Exchange Logo

Try it out and discover for yourself.

Subscribe Now

30-day free trial. Register in 60 seconds.

Related Solutions

  1. Restoring a CString From a LPARAM
    I am trying to pass data between two applications via SendMessage. I can pass integers back and forth fine, but I am have problems passing any char data. CWnd* pWnd = CWnd::FromHandle(hWnd); char *text = "this won't come through"; // doesn't work int x = 90; ...
  2. WH_KEYBOARD Hook question
    I am implementing WH_KEYBOARD hook. If I process VK_APPS I cannot discard this message (do not pass it to other applications)? Currently I return TRUE from my Keyboard hook and do not call CallNextHookEx but message is processed.
  3. lParam Decoding in Keyboard Hook
    Hello! I used SetWindowsHookEx to sub-class the keyboard. Then this function: Public Function KeyboardProc(ByVal idHook As Long, ByVal wParam As Long, ByVal lParam As Long) As Long wParam holds the "key value" and lParam holds this: http://msdn.microsoft.com/lib...
  4. Question about LPARAM , WPARAM etc
    A simple theory question (I think). LPARAM , RPARAM , WPARAM etc. What are these?? Using them in my code if I look at them all I see is a value (number) yet somehow this "value" will contain a number I need but can;t see anywhere. ie :OnClickListcontrol(NMHDR* pNM...
  5. WH_JOURNALRECORD Hook callback before take action
    It look like that WH_JOURNALRECORD Hook callback before keyboard or mouse take action. Ex.1 I couldn't get the correct character index in edit control. When typing "abcde", at 5th callback loop the EM_LINELENGTH = 4 and "e" will display in edit control ...
  6. Type Casting lParam as a Pointer
    Windows application. In a WM_NOTIFY message for a tab control, lParam is a pointer to a NMHDR structure. I have the following code which works: case WM_NOTIFY: // Messages from tab control if (lParam && LOWORD (wParam) == IDC_TAB) { LPNM...

Free Tech Articles

  1. WARNING: 5 Reasons why you should NEVER fix a computer for free.
    It is in our nature to love the puzzle. We are obsessed. The lot of us. We love puzzles. We love the challenge. We thrive on finding the answer. We hate disarray. It bothers us deep in our soul. W...
  2. SCCM OSD Basic troubleshooting
    SCCM 2007 OSD is a fantastic way to deploy operating systems, however, like most things SCCM issues can sometimes be difficult to resolve due to the sheer volume of logs to sift through and the dispe...
  3. Migrate Small Business Server 2003 to Exchange 2010 and Windows 2008 R2
    This guide is intended to provide step by step instructions on how to migrate from Small Business Server 2003 to Windows 2008 R2 with Exchange 2010. For this migration to work you will need the fo...
  4. Create a Win7 Gadget
    This article shows you how to create a simple "Gadget" -- a sort of mini-application supported by Windows 7 and Vista. Gadgets can be dropped anywhere on the desktop to provide instant information, ...
  5. Outlook continually prompting for username and password
    There have been a lot of questions recently regarding Outlook prompting for a username and password whilst using Exchange 2007. There are a few reasons why this would happen and I will try to cover t...
  6. Backup Exchange 2010 Information Store using Windows Backup
    There seems to be quite a lot of confusion around the ability to backup Exchange 2010 using the built in Windows Backup feature. This stems from the omission of this feature prior to Exchange 2007 s...

Cloud Class Webinars

  1. Avoiding Bugs in Microsoft Access
    Alison Balter takes and in-depth look at avoiding bugs in Access. In this webinar you will learn about using the immediate window to debug your applications, invoking the debugger, using breakpoints to troubleshoot, stepping through code, setting the next statement to execute, ...
  2. Top 10 Best New Features in Visio 2010
    Scott Helmers gives live demonstrations of the top 10 new features in Visio 2010. This webinar will teach you how to create compelling diagrams by adding shapes to the page with a single click, linking the shapes in a diagram to data in Excel (or SQL Server, or SharePoint), ...
  3. IT Consultant Business Secrets Revealed
    Michael Munger, Experts Exchange tech pro and IT consultant, pulls back the curtain on his very successful businesses and answers question on every IT consultant and business owner should know about. He shares secrets on what he did to solve the 5 most common problems in IT, ...
  4. Disaster Recovery and Business Continuity
    Quest CTO, Mike Billon, gives an overview of the steps involved in building a dunamic disaster recovery plan. Through case studies and an examination of software/hardware tooles for monitoring and testing, you'll gain a better understandin of where you are, where you want ...
  5. Organize Your Visio Diagrams with Containers and Lists
    Scott Helmers uses cross functional flowcharts, wireframe diagrams, data graphic legends and seating charts to teach you: how to ustilize all three new structured diagram components in Visio 2010, the best practices for organizeing shapes in previous version of Visio, how to organize ...
  6. How to Us Objects, Properties, Events and Methods in Microsoft Access
    Alison Dalter gives an in-depbth look at objects, properties, events and methods in Microsoft Access. In this webinar you will learn about using the object browser, referring to objects, working with properties and methods, working with object variables, understanding the ...

Join the Community

Give a Little. Get a Lot.

Join the community of experts here and help other tech pros by answering question in your area of expertise. You can earn FREE access to all Experts Exchange's premium features and resources.

Join the Community

Answers

 

by: jkrPosted on 2008-07-23 at 07:55:38ID: 22069964

Try the following:

//Keyboard Hook Procedure inside in the DLL which posts a message to my application
KEYDLL3_API LRESULT CALLBACK hookproc(int ncode,WPARAM wparam,LPARAM lparam)
{
    PMSG    pmsg    =   ( PMSG) lparam;
 
    if  (   0   >   ncode   ||  PM_NOREMOVE ==  wparam) 
        {
            return  (   CallNextHookEx  (   hook,
                                            ncode,
                                            wparam,
                                            lparam
                                        )
                    );
        }
 
    if  (       WM_KEYDOWN  ==  pmsg->message
            ||  WM_KEYUP    ==  pmsg->message   
        )
        {
           // check if you get here
        }
 
    return  (   CallNextHookEx  (   hook,
                                    ncode,
                                    wparam,
                                    lparam
                                )
            );
}
                                              
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:

Select allOpen in new window

 

by: ramavorrayPosted on 2008-07-23 at 08:25:15ID: 22070266

No, It is not reaching the point you indicated. I tried two alternatives. Please see the code below.

//Tried this as you indicated. No messages are Posted at all, either for keyup or keydown.
KEYDLL3_API LRESULT CALLBACK hookproc(int ncode,WPARAM wparam,LPARAM lparam)
{
	if(0   >   ncode   ||  PM_NOREMOVE ==  wparam)
		return ( CallNextHookEx(hook,ncode,wparam,lparam) );//pass control to next hook in the hook chain.
 
	PMSG msg = (PMSG) lparam;
	if(msg->message == WM_KEYDOWN || msg->message == WM_KEYUP)
	{
		hwnd = FindWindow("#32770","Keylogger Exe");//Find application window handle
		PostMessage(hwnd,WM_USER+755,wparam,lparam);//Send info to app Window.
	}
 
	return ( CallNextHookEx(hook,ncode,wparam,lparam) );//pass control to next hook in the hook chain.
}
 
//thought of checking where the control is going and tested with. Messages are posted. So, the checks of WM_KEYUP/DOWN are not being sensed!!! and I am not understanding why!
KEYDLL3_API LRESULT CALLBACK hookproc(int ncode,WPARAM wparam,LPARAM lparam)
{
	if(0   >   ncode   ||  PM_NOREMOVE ==  wparam)
		return ( CallNextHookEx(hook,ncode,wparam,lparam) );//pass control to next hook in the hook chain.
 
	PMSG msg = (PMSG) lparam;
	if(msg->message == WM_KEYDOWN || msg->message == WM_KEYUP)
	{
		//hwnd = FindWindow("#32770","Keylogger Exe");//Find application window handle
		//PostMessage(hwnd,WM_USER+755,wparam,lparam);//Send info to app Window.
	}
 
	hwnd = FindWindow("#32770","Keylogger Exe");//Find application window handle
	PostMessage(hwnd,WM_USER+755,wparam,lparam);//Send info to app Window.
 
	return ( CallNextHookEx(hook,ncode,wparam,lparam) );//pass control to next hook in the hook chain.
}
 
//For your reference below is the function which installs hook in DLL
KEYDLL3_API void installhook(HWND h)
{
	hook = NULL;
	hwnd = h;
	hook = SetWindowsHookEx(WH_KEYBOARD,hookproc,hinstance,NULL);
	if(hook==NULL)
		MessageBox(NULL,"Unable to install hook","Error!",MB_OK);
}
 
//in my application which receives event message is mapped as
#define WM_KEYSTROKE (WM_USER + 755)
 
//all are defined well and working well, except the sensing of
//WM_KEYUP / WM_KEYDOWN

                                              
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:

Select allOpen in new window

 

by: jkrPosted on 2008-07-23 at 09:15:08ID: 22070816

Hmm, stupid question - how did you check that this point is not reached? I took the above from a working project that successfully detects the keypresses (the purpose was to remap some keys, and that works fine)

 

by: ramavorrayPosted on 2008-07-23 at 09:38:23ID: 22071069

If that point is reached, the procedure in my application which should be called as a result of the posted message should be called.

I can say that this point is not reached as the hook procedure in my application is not called.

It was called in the second situation (where I had put postmessage outside the if...block)

Please get the source code http://www.cs.ucl.ac.uk/staff/R.Vorray/Keyexe.zip A zip file which contains hook DLL project and exe project. please check. LINE NUMBER 241 in KeyExeDlg.cpp in KeyExe project should be reached when everything is working.

Please put the generated Debug DLL in the Debug folder of KeyExe. All include paths are arranged correct.

 

by: jkrPosted on 2008-07-23 at 09:44:30ID: 22071121

Hm, try to just place an

OutputDebugString("Keypress detected\n");

inside the 'if' body and check the output with DebugView (http://technet.microsoft.com/en-us/sysinternals/bb896647.aspx). Chances are that something goes wrong when communicating the event.

 

by: JohnGabyPosted on 2008-07-23 at 09:49:42ID: 22071183

ramavorray, you are setting the WH_KEYBOARD hook.  The code that jkr suggested appears to be appropriate for the WH_GETMESSAGE hook (the lParam for the keyboard hook does not point to a MSG structure).  You might try using the getmessage hook and the code that jkr provided instead of the keyboard hook.

I have not ever used the WH_KEYBOARD hook, but I have successfully intercepted keyboard messages via the WH_GETMESSAGE hook.

 

by: ramavorrayPosted on 2008-07-23 at 11:02:17ID: 22072029

But when WH_GETMESSAGE is used wParam cannot be used to get virtual keycodes!

I cannot do checks like, if(wParam == VK_SPACE)

Also I need to use ToUnicodeEx(...) function to translate the wParam value into a unicode character based on current keyboard layout.

This no longer works when WH_GETMESSAGE is used!!!?

 

by: JohnGabyPosted on 2008-07-23 at 11:09:09ID: 22072109

For the WH_GETMESSAGE hook, the lParam points to a MSG structure.  If you look in that structure for (message == WM_KEYDOWN), then for that message, the wParam of that structure will contain the virtual key code, and the lParam of that structure will contain the key data.

Is there something here that you need that I am missing?

 

by: ramavorrayPosted on 2008-07-23 at 11:37:44ID: 22072413

when typecasted lparam into PMSG in the hook handler procedure inside my applicatin, it is giving me Access Violation exception!

Please see the code below and please consider me a beginner in this regard.

//This is what I am doing inside my hook handler
LRESULT CAI_TalapatraDlg::ProcessKeyboard(WPARAM w, LPARAM l)
{
  PMSG msg = (PMSG)lparam;
  if(msg->message == WM_KEYDOWN)   //access violation error with message.
  //debugger shows invalid data for msg
  {
        if(msg->wParam == VK_SPACE || msg->wParam == VK_DOWN)
		//do stuff
  }
}
 
 
//here is the message posting function inside the DLL. Here everything works fine and the procedure above inside my application is called only once, but not able to process the virtual key code.
KEYHOOK_API LRESULT CALLBACK Hookproc(int nCode, WPARAM wparam, LPARAM lparam)
{
	if(0   >   nCode   ||  PM_NOREMOVE ==  wparam)
                return ( CallNextHookEx(hook,nCode,wparam,lparam) );//pass control to next hook in the hook chain.
 
    PMSG msg = (PMSG) lparam;
    if(msg->message == WM_KEYDOWN)
    {
		hwnd=FindWindow(NULL, _T("AI Talapatra"));
		if(hwnd!=NULL)
			PostMessage(hwnd, WM_USER+3, wparam, lparam);
	}
 
	return (CallNextHookEx(hook, nCode, wparam, lparam));
}

                                              
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:

Select allOpen in new window

 

by: JohnGabyPosted on 2008-07-23 at 11:50:42ID: 22072560

Did you change your call to CreateWindowsHookEx to use WH_GETMESSAGE instead of WH_KEYBOARD?

 

by: ramavorrayPosted on 2008-07-23 at 11:50:54ID: 22072564

sorry there was a typo in the code in previous comment. Please consider code below for the first half.

//This is what I am doing inside my hook handler
LRESULT CAI_TalapatraDlg::ProcessKeyboard(WPARAM w, LPARAM l)
{
  PMSG msg = (PMSG)l;
  if(msg->message == WM_KEYDOWN)   //access violation error with message.
  //debugger shows invalid data for msg
  {
        if(msg->wParam == VK_SPACE || msg->wParam == VK_DOWN)
                //do stuff
  }
}
                                              
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:

Select allOpen in new window

 

by: ramavorrayPosted on 2008-07-23 at 11:56:47ID: 22072611

Yes. now I am using WH_GETMESSAGE

KEYHOOK_API void Installhook(HWND h)
{
	hook = NULL;
	hwnd = h;
	hook = SetWindowsHookEx(WH_GETMESSAGE, Hookproc, hinstance, NULL);
 
	if(hook == NULL)
		MessageBox(NULL, _T("Unable to Install Hook"), _T("Error"), MB_OK);
}

                                              
1:
2:
3:
4:
5:
6:
7:
8:
9:

Select allOpen in new window

 

by: ramavorrayPosted on 2008-07-23 at 12:14:50ID: 22072796

This is what debugger is showing inside the function ProcessKeyboard(WPARAM w, LPARAM l) inside my application.

This conversion is working well in the DLL but not inside my application.


msg              0x0023f7e8 {msg=??? wp=??? lp=???}      tagMSG *
hwnd      CXX0030: Error: expression cannot be evaluated      
message      CXX0030: Error: expression cannot be evaluated      
wParam      CXX0030: Error: expression cannot be evaluated      
lParam      CXX0030: Error: expression cannot be evaluated      
time              CXX0030: Error: expression cannot be evaluated      
pt              {x=??? y=???}      tagPOINT

 

by: JohnGabyPosted on 2008-07-23 at 13:12:33ID: 22073350

You cannot post the pointer to the MSG structure like that.  By the time the posted message reaches your application, the memory to which the pointer is pointing is likely to no longer be valid.  You need to extract the data from the structure and post that to your application.

 

by: ramavorrayPosted on 2008-07-23 at 14:22:10ID: 22074023

when key hits are made In all other applications except MS-Word my hook handler ProcessKeyboard(...) is being called once, indicating Wm_KEYDOWN; But when I type something in MS-Word ProcessKeyboard is being called four times as it did previously. Why is WM_KEYDOWN not being sensed from within MS-Word?

Now, I am posting msg->wParam and msg->lParam as two parameters inside PostMessage function.

below is the code for HookProc. WM_USER + 3 message is being posted four times from MS_WORD. Any clue on this?

KEYHOOK_API LRESULT CALLBACK Hookproc(int nCode, WPARAM wparam, LPARAM lparam)
{
	if(0   >   nCode   ||  PM_NOREMOVE ==  wparam)
                return ( CallNextHookEx(hook,nCode,wparam,lparam) );//pass control to next hook in the hook chain.
 
    PMSG msg = (PMSG) lparam;
    if(msg->message == WM_KEYDOWN)
    {
		hwnd=FindWindow(NULL, _T("AI Talapatra"));
		if(hwnd!=NULL)
			PostMessage(hwnd, WM_USER+3, msg->wParam, msg->lParam);
	}
 
	return (CallNextHookEx(hook, nCode, wparam, lparam));
}

                                              
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:

Select allOpen in new window

 

by: JohnGabyPosted on 2008-07-23 at 14:52:32ID: 22074291

I am not sure I can help you any further.  Oddly enough, a while back I was trying to help another user intercept keys, and he too has some difficulty getting it to work with Word.  As I recall, he was able to get the keyup/down messages, but not the WM_CHAR messages.  It worked with all other apps, but not with Word.  Here is the link to that discussion.

http://www.experts-exchange.com/Programming/Languages/CPP/Q_23471531.html

I am not sure if he ever solved the problem, but perhaps if you posted a comment on that question, he might see it, and answer.
 

 

by: ramavorrayPosted on 2008-07-24 at 06:48:46ID: 22079021

Hi JohnGaby,

I will deal with the MS-Word thing later on. Now another messy problem I am facing with your approach is that I am not able to process SHIFT + key combinations

the wParam is returning 'a' instead of 'A' when I press SHIFT + 'a'

I think it is calling my hook procedure once for SHIFT key press and once from 'a' key press. How to handle this situation?

 

by: ramavorrayPosted on 2008-07-24 at 06:53:48ID: 22079076

I am using ToUnicodeEx(...) function to translate the wParam value into Unicode characters, as I deal with non-english languages aswell.

I get keyboard state using GetKeyboardState(..) and pass the resulting array as one of the arguments to ToUnicodeEx(...) but keyboardsate array here is not possessing the keydown bit for SHIFT key as by the time it is called for 'a' in SHIFT + 'a' shift key is down!

Any clue in this regard?

 

by: ramavorrayPosted on 2008-07-24 at 07:30:43ID: 22079530

sorry in my previous comment please read the last line as "...by the time it is called for 'a' in SHIFT+'a' shift key is UP!

 

by: ramavorrayPosted on 2008-07-24 at 07:36:00ID: 22079581

even if pressed 'a' or SHIFT + 'a' buf contains only 'a'. How can I get 'A' here out of ToUnicodeEx(...) function?

LRESULT CAI_TalapatraDlg::ProcessKeyboard(WPARAM w, LPARAM l)
{
 BYTE ks[256];
 WCHAR buf[10];
 UINT scan=0;
 
 GetKeyboardState(ks);
 
 if(ToUnicodeEx(w, scan, ks, buf, 1, 1, m_hklval))
{
        ......//even if pressed 'a' or SHIFT + 'a' buf contains only 'a'
}
 
}

                                              
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:

Select allOpen in new window

 

by: JohnGabyPosted on 2008-07-24 at 08:27:55ID: 22080231

If you want characters, instead of keys, you should be looking for the WM_CHAR message, rather than the WM_KEYDOWN message.  The WM_KEYDOWN messages returns the raw 'virtual' keys.  The WM_CHAR message is generated when you call the TranslateMessage function in your message loop, and should give you unicode characters if you have compiled using the unicode character set.

 

by: ramavorrayPosted on 2008-07-24 at 08:41:26ID: 22080381

PMSG msg = (PMSG) lparam;
    if(msg->message == WM_CHAR)
    {
		hwnd=FindWindow(NULL, _T("AI Talapatra"));
		if(hwnd!=NULL)
			PostMessage(hwnd, WM_USER+3, msg->wParam, msg->lParam);
	}
 
//in the above code (when using WM_CHAR) what does wParam and lParam indicate?
 
//How do I specify that my WM_USER+3 message is posted only when Key is down but not otherwise
 
//wParam the unicode character?
 
//then which variable indicates other key hits like VK_SPACE, VK_BACK, etc...

                                              
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:

Select allOpen in new window

 

by: ramavorrayPosted on 2008-07-24 at 08:46:25ID: 22080449

This is how my current code looks, which sends key hits to my application called "AI Talapatra". Can I just change WM_KEYDOWN to WM_CHAR and wParam is an Unicode Character? If so, how to sense SPACE, BACKSPACE. etc.

KEYHOOK_API LRESULT CALLBACK Hookproc(int nCode, WPARAM wparam, LPARAM lparam)
{
    if(0   >   nCode   ||  PM_NOREMOVE ==  wparam)
               return ( CallNextHookEx(hook,nCode,wparam,lparam) ); //pass control to next hook in the hook chain.
 
    PMSG msg = (PMSG) lparam;
    if(msg->message == WM_KEYDOWN)
    {
		hwnd=FindWindow(NULL, _T("AI Talapatra"));
		if(hwnd!=NULL)
		PostMessage(hwnd, WM_USER+3, msg->wParam, msg->lParam);
    }
 
return (CallNextHookEx(hook, nCode, wparam, lparam));
}

                                              
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:

Select allOpen in new window

 

by: JohnGabyPosted on 2008-07-24 at 09:06:18ID: 22080685

Here is the manual page for the WM_CHAR message:

http://msdn.microsoft.com/en-us/library/ms646276.aspx

The wParam contains the unicode (UTF16) character.  The lParam is not particularly useful.  If you are looking for the space character, compare (wParam == ' ').  For the backspace look for (wParam == '\b').

Note that you WILL have problems with this message when hooking MS Word (and I believe Excel also).

 

by: ramavorrayPosted on 2008-07-24 at 09:22:34ID: 22080869

When did so I am getting a numerical value in msg->wParam which is posted to my application. (eg., 3108).

How to translate it into an appropriate character?

 

by: JohnGabyPosted on 2008-07-24 at 09:34:09ID: 22080988

I am not sure what is wrong.  Here is some code that uses the WH_GETMESSAGE hook to hook notepad, and replace the character 'x' with 'y' each time it is typed.  This code works with no problem.  Perhaps you can compare this to what you are doing and figure out what is wrong.

It consists of two pieces.  The first is the code for the dll which sets and process the hook.  The second is for a console app which finds an instance of notepad and calls the dll to set the hook.

// HookDll.cpp
//
// This is the DLL which both sets the hook and
//      subclasses the edit window for the notepad app
//      which is hooked
//
 
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
 
HINSTANCE   hMod;
HHOOK       hHook;
 
BOOL APIENTRY DllMain(  HANDLE hModule, 
                        DWORD  ul_reason_for_call, 
                        LPVOID lpReserved)
{
    hMod	= (HINSTANCE) hModule;
 
    return TRUE;
}
 
#ifdef __cplusplus
extern "C" {
#endif
 
LRESULT CALLBACK HookProc(int code, WPARAM wParam, LPARAM lParam)
{
    LRESULT	ret	= 0;
 
    if (code == HC_ACTION)
    {
        MSG		*	pMsg	= (MSG *) lParam;
 
        if (pMsg->message == WM_CHAR)
        {
            if (pMsg->wParam == 'x')
            {
                pMsg->wParam	= 'y';
            }
        }
    }
 
    return(CallNextHookEx(hHook, code, wParam, lParam));
}
 
__declspec(dllexport) BOOL SetHook(DWORD threadId)
{
    hHook = SetWindowsHookEx(WH_GETMESSAGE, HookProc, hMod, threadId);
 
    return(hHook ? TRUE : FALSE);
}
 
__declspec(dllexport) void ClearHook(void)
{
    if (hHook)
    {
        UnhookWindowsHookEx(hHook);
        hHook	= 0;
    }
}
 
#ifdef __cplusplus
}
#endif
 
// GlobalHook.cpp
//
// This is a console application which find an instance of notepad.exe
//  and sets a hook into it's process
//
 
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <conio.h>
 
#ifdef __cplusplus
extern "C" {
#endif
 
__declspec(dllimport) BOOL SetHook(DWORD threadId);
__declspec(dllimport) void ClearHook(void);
 
#ifdef __cplusplus
}
#endif
 
int _tmain(int argc, _TCHAR* argv[])
{
    HWND	hEdit;
 
    /*
     * Find an instance of notepad to hook
     */
    if (hEdit = FindWindow(_T("Notepad"), 0))
    {
        DWORD	threadId = 0;
        DWORD	processId;
 
        /*
         * Get the thread ID for the window
         */
        if (threadId = GetWindowThreadProcessId(hEdit, &processId))
        {
            printf("Setting hook\n");
 
            /*
             * Set a hook for this thread
             */
            if (SetHook(threadId))
            {
                printf("Hook set, press any key to clear hook\n");
                getch();
                printf("Clearing hook\n");
                ClearHook();
            }
            else
            {
                printf("Cannot set hook\n");
            }
        }
    }
    else
    {
		printf("Cannot find an instance of word\n");
    }
 
    return 0;
}
                                              
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:

Select allOpen in new window

 

by: ramavorrayPosted on 2008-07-24 at 09:40:38ID: 22081054

Here you are comparing character with 'x' but similarly can you compare it with '' a Hindi character. Also how can this wParam be converted into a string. ToUnicodeEx(...) function cannot understand the value of wParam.

It is able to understand the value of wParam with WM_KEYDOWN, but with WM_KEYDOWN I am not able to sense SHIFT.

for example, key 'k' gives a character and also SHIFT + K gives another characeter. WM_KEYDOWN is working for sensing single key strokes but not SHIFT + K.

WM_CHAR is giving a numerical value to wParam (because non-english keyboard layout has been loaded) and I am not understanding how to convert it into a string.

 

by: JohnGabyPosted on 2008-07-24 at 09:54:55ID: 22081197

I have not tried this with unicode characters, but according to the manual page, the wParam is the UTF16 unicode character.  This means that it is already converted to unicode (assuming you have compiled your application using the unicode character set).  To compare it to a Hindi character, you would need to know the UTF16 value for the Hindi character.

I cannot tell you much more.  Handling languages other than English (especially ones which require the UTF16 character set) is not my area of expertise.  Perhaps another expert can help you out there.

 

by: ramavorrayPosted on 2008-07-28 at 11:39:31ID: 31479375

Complete solution hasn't been found but my original question has been answered.

20120131-EE-VQP-002

3 Ways to Join

30-Day Free Trial

The Experts

98% positive feedback on 31,087 answers since March 2000. angeliii is a Microsoft Most Valuable Professional for his work with MS SQL Server & Develoment.

He has also proven his knowledge of Visual Basic Programming, PHP Scripting and Oracle Databases.

The Experts

97% positive feedback on 10,752 answers since July 2000. lrmoore has more than 18 years experience in the networking industry.

The six-time Mircosoft MVPs specialties include firewalls, virtual private networking, and network management.

Testimonials

"...and excellent source for support... Kind of like having your very own IT dept." Electriciansnet

Testimonials

"I was apprehensive at signing up at first. However... it has already made my life as an IT administrator much easier." JaCrews

Testimonials

"WOW! You guys have great, active, and knowledgeable people on here." moore50

Business Clients

Business Clients

In the Press

"If you’ve got a question... Experts Exchange can supply an answer.”

In the Press

"...an invaluable aid for both IT professionals and those who require tech support."

In the Press

"where IT professionals provide quick answers on just about any topic"

Business Account Plans

Loading Advertisement...