We help IT Professionals succeed at work.

Keyboard advice from nietod

Volga
Volga asked
on
353 Views
Last Modified: 2010-04-02
Hi Nietod,

I posted my question earlier and was able to write a dll for a global hook (SetWindowsHookEx) at:
https://www.experts-exchange.com/jsp/qShow.jsp?ta=cplusprog&qid=10303102 

I went thought earlier questions related to my project and I found your comments at:
https://www.experts-exchange.com/jsp/qShow.jsp?ta=visualbasic&qid=10313395 

You suggested not using the function SendMessage(). Could you tell me which function I should use to translate my keyboard application?

My application is a simple keyboard mapping. Say if I receive the letter 'a', I want to translate it into the letter 'b', for example; and that applies to all windows applications running, that's why I need a global hook. Should I implement that translation routine inside the dll itself (inside  LRESULT CALLBACK KeyboardProc)?

Thank you

Comment
Watch Question

Commented:
I don't see what send message has to di with what you are doing.  The keyboard hook can simply alter the information about which key was pressed and the altered information will be posted.

Author

Commented:
Nietod,

Here is a sample routine that I wrote to test and see if the hook is working. I just wanted to translate 'A', 'B', 'C' into 'X', 'Y', 'Z' respectively. But it didn't work.
 
Apparently the KeyBoardProc ignored the translations I made to wPapram. Another reason I think about using SendMessage is the case I want to translate one key to multiple characters, say from 'A' to 'XYZ'.


LRESULT CALLBACK KeyBoardProc(int nCode,WPARAM wParam,LPARAM lParam)
{

      char vchar;
      if (nCode >= 0)
      {
            vchar = wParam;
            switch (vchar)
            {
            case 'A':
                  wParam = 'X';
                  break;
            case 'B':
                  wParam = 'Y';
                  break;
            case 'C':
                  wParam = 'Z';
                  break;
            }
      return CallNextHookEx(hhook, nCode, wParam, lParam);
      }

      return CallNextHookEx(hhook,nCode,wParam,lParam);
}
Wyn

Commented:
The lParam contains scan code and more.I think it's also necessary to change them.
You can use MapVirtualKey() to get scan code of each character.

If still fails.

Try not call CallNextHookEx().
But this is without promise,just try it.

Regards
W.Yinan
Commented:
This one is on us!
(Get your first solution completely free - no credit card required)
UNLOCK SOLUTION
Wyn

Commented:
->You shoud use keybd_event() to post the keydown and keyup events you need, then return a negative number to indicate to the system that the key was handled.  
=================================
keybd_event will still make a message ,then this will make a endless loop in the hook procedure,won't it?

Commented:
If that is problem (like if you convert A to B and B to C...), then you should be able to use a global or static boolean to prevent recursion.  
Wyn

Commented:
->If that is problem
=============
nietod,maybe,in my opinion ,surely it's a problem which will happen and the boolean is imperative.  
Wyn

Commented:
Volga ,
I suggest you use another kind of hook ,like WH_GETMESSAGE,then you can change that message .

Commented:
>> surely it's a problem which will happen
It depends on the details of what he is doing.  But problems can be avoided.

>> WH_GETMESSAGE,then you can
>> change that message .
That's a good idea too, but your hook will be called for many other reasons and you still have the same problem if you need to convert 1 key into two or more keys.
Wyn

Commented:
Volga ,I try to write a program like yours in your way and I find two suspicious points:

1:I use the keyboard hook and I find I got SAME wParam and lParam in my hook function when I type 'A' or 'a'.
How this happen ?
2:I find when the message comes to my hook function,the letter has already been appear in notepad(I use notepad for experiment),
So,I figure we can not change it because it's too late for us .If we can drag our hook function to the top of the hook chain.Maybe we can change.
Wyn

Commented:
btw,maybe you should add lParam&0x80000000 to your code to test if the key is up .

Commented:
>>  I find I got SAME wParam and lParam in my hook
>> function when I type 'A' or 'a'
You should.  That is the virtual key code.  It doesn't recognize case.  If it is proceeded by the shift key or if caps lock is down a uppercase character wil be generated.  But that is a later phase of translation.  This is prior to generating WM_KEYxxxx messages.   Case only matters when the OS turns those into WM_CHARxxxx  messages.
Wyn

Commented:
Thanx,nietod.
So,Volga ,you'v got to change your way.
Regards
W.Yinan

Author

Commented:
Thanks Nietod and Wyn for the suggestions, even though it looks like I have to find other ways to do it. I still appreciate if you have any afterthought.

You two are the real experts in this forum.

Volga
Wyn

Commented:
Volga ,I'm not a real expert if nietod is just a real expert:*)

Anyway thank you :)

FYI ,you can write a program which will dynamically test out the window have keyboard-focus by calling GetForegoundwindow(),AttachThreadInput() and GetFocus() sequentially.Then in your application,create a child pop-up style window of we find-out window and this will take up the focus without losing active of that original window .Afterwards, record all keystrokes the user type(note,user doesnt know he is working with another window:) and transfer them to user-working window by keybd_event.This way is light-weigt.Only add a middle-tier.

Set a system-hook is overkill and complex ,conversely the way above is optional :when we want to use this virtual keyboard,we can hot-key it and it will find which window we are working with and afterwards all keys are translated and send by our virtual keyboard.
Do you want this kind keyboard or thoroughly change the keyborad for every thread running ?

Regards
W.Yinan  
Wyn

Commented:
->and transfer them to user-working window by keybd_event.This way is light-weigt
==========
or use message.

Author

Commented:
Wyn,

Since I want to intercept the keyboard in all threads, it will be difficult to do without having a global hook. If I use all the three functions that you suggested, which hook should I be using?

One thing I wonder what's good a keyboard hook is if it cannot alter the keystroke.

Volga
Wyn

Commented:
->Since I want to intercept the keyboard in all threads, it will be difficult to do without having a global hook. If I use all the three functions that you suggested, which hook should I be using?
=========================
Volga , you overlook one thing.
Whether or not how many threads you'v hooked,the user can only work with ONE GUI thread at a time.And above way is finding the thread the user is working with and "insert" a virtual keyboard in between for translation.
I dont think hook is good for this.
Wyn

Commented:
->If I use all the three functions that you suggested, which hook should I be using?
=========================
No Hook!!!
My method doesnt use hook!!!

Commented:
Wyn, I don't understand what you are proposing.
Wyn

Commented:
:(
I just do what Volga need by creating a child window of the user-working window and take place the key-board focus ,then translate and generate by using keybd_event.
I dont think hook is necessary.

Best Regards
W.Yinan
Unlock the solution to this question.
Join our community and discover your potential

Experts Exchange is the only place where you can interact directly with leading experts in the technology field. Become a member today and access the collective knowledge of thousands of technology experts.

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.