Solved

Keyboard advice from nietod

Posted on 2000-03-10
21
279 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:
http://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:
http://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

0
Comment
Question by:Volga
  • 12
  • 6
  • 3
21 Comments
 
LVL 22

Expert Comment

by:nietod
ID: 2606548
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.
0
 

Author Comment

by:Volga
ID: 2606773
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);
}
0
 
LVL 5

Expert Comment

by:Wyn
ID: 2607041
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
0
 
LVL 22

Accepted Solution

by:
nietod earned 50 total points
ID: 2607567
I thought the hook had the option to alter the data, it does not.  (you are just altering the parameter passed to you, not the value the OS has.  i.e. the data is not pased by reference.)

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.  
0
 
LVL 5

Expert Comment

by:Wyn
ID: 2607619
->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?
0
 
LVL 22

Expert Comment

by:nietod
ID: 2607640
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.  
0
 
LVL 5

Expert Comment

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

Expert Comment

by:Wyn
ID: 2607687
Volga ,
I suggest you use another kind of hook ,like WH_GETMESSAGE,then you can change that message .
0
 
LVL 22

Expert Comment

by:nietod
ID: 2607695
>> 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.
0
 
LVL 5

Expert Comment

by:Wyn
ID: 2607803
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.
0
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

 
LVL 5

Expert Comment

by:Wyn
ID: 2607806
btw,maybe you should add lParam&0x80000000 to your code to test if the key is up .
0
 
LVL 22

Expert Comment

by:nietod
ID: 2607880
>>  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.
0
 
LVL 5

Expert Comment

by:Wyn
ID: 2608872
Thanx,nietod.
So,Volga ,you'v got to change your way.
Regards
W.Yinan
0
 

Author Comment

by:Volga
ID: 2608953
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
0
 
LVL 5

Expert Comment

by:Wyn
ID: 2609157
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  
0
 
LVL 5

Expert Comment

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

Author Comment

by:Volga
ID: 2609164
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
0
 
LVL 5

Expert Comment

by:Wyn
ID: 2609195
->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.
0
 
LVL 5

Expert Comment

by:Wyn
ID: 2609196
->If I use all the three functions that you suggested, which hook should I be using?
=========================
No Hook!!!
My method doesnt use hook!!!
0
 
LVL 22

Expert Comment

by:nietod
ID: 2609344
Wyn, I don't understand what you are proposing.
0
 
LVL 5

Expert Comment

by:Wyn
ID: 2609724
:(
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
0

Featured Post

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

  Included as part of the C++ Standard Template Library (STL) is a collection of generic containers. Each of these containers serves a different purpose and has different pros and cons. It is often difficult to decide which container to use and …
Many modern programming languages support the concept of a property -- a class member that combines characteristics of both a data member and a method.  These are sometimes called "smart fields" because you can add logic that is applied automaticall…
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.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

746 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

13 Experts available now in Live!

Get 1:1 Help Now