ToAsciiEx generating an extra char when a dead-key is entered

When I set a system wide keyboard hook using WH_KEYBOARD_LL or WH_JOURNALRECORD, parses it with ToAsciiEx  and then types a dead key (ex. ë ê ~ ), this is handled incorrectly in both the key recording and the actual window.

So if I open notepad and start typing when the hook is active, I am unable to even type these dead chars correctly. If I write "ë" it will appear as "¨¨e" instead. So the problem is not only that it is recorded incorrectly but also that ToAsciiEx seems to flush the contents to whatever window is active

According to msdn, this is what happens:
"Two characters were copied to the buffer. This usually happens when a dead-key character (accent or diacritic) stored in the keyboard layout cannot be composed with the specified virtual key to form a single character."

I need help in finding a way to handle these dead keys correctly, so ToAsciiEx would hold this char until it recives the next one it chould be combined with - instead of just inserting an extra dead key and flush it.

bool GetKey(UINT uVirtKey, UINT uScanCode, char *thekey)
      BYTE KeyState[256];
      HKL KeyLayout;
      int size,ascii_result;
      bool funckey;
      if (GetKeyboardState(KeyState)==FALSE)
            return false;
      KeyLayout = GetKeyboardLayout(0);

      UINT uScanCode2 = MapVirtualKeyEx(uVirtKey, 2, KeyLayout);

      ascii_result = ToAsciiEx(uVirtKey, uScanCode2, KeyState, (LPWORD)thekey, 0, KeyLayout);

      return true;
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

I'm not sure what the function you posted is about.  The functions for the hooks you mention both have different parameters and return values than the GetKey you post, and both should call CallNextHookEx unless you have a very good reason not to.

What I'd suggest is trying just having a hook that calls the next hook without any processing.  Then try adding the functionality you need until the dead keys stop working.  That's the easiest way to narrow down the problematic code.

Hope this helps.
ksv_Author Commented:
The problem occurs once I call ToAsciiEx, regardless if I pass it on to CallNextHookEx or not. I have tried both.

The getkey function is called from the callback function. If we use WH_KEYBOARD_LL it could look like this:

__declspec(dllexport) LRESULT CALLBACK KeyEvent (int nCode, WPARAM wParam, LPARAM lParam)
      if(nCode < 0)
            return CallNextHookEx(hKeyHook, nCode, wParam, lParam);
      else if(nCode == HC_ACTION)
            if(wParam == WM_KEYDOWN)

                  char ch[256];
                  if (GetKey(pEvt->vkCode, pEvt->scanCode, ch) == true)
                        // a character is recieved in ch
                        // write to file, echo to the consol.
                        // GetKeyNameText() could be used to get the name of spec. keys
      return 0;
Hmm, what are you doing with the results of ToAsciiEx?  Obviosuly you know you have a dead character if the function returns a 0.  If you call ToAsciiEx first, and then skip all other processing if it returns 0, does that help any?
ksv_Author Commented:
It seems it doesn´t matter what I do after ToAsciiEx.

I have also tried using MapVirtualKeyEx to determine if it is a dead char ahead and then just returning without calling ToAsciiEx. But the next time it is called with the regular char (that the dead char should be mixed with), the dead char isn´t remembered.
Did you note this section of the documentation:

"The parameters supplied to the ToAsciiEx function might not be sufficient to translate the virtual-key code, because a previous dead key is stored in the keyboard layout."

So if dead keys are being recorded, ToAsciiEx won't detect it.  Neither will ToUnicodeEx.  It seems you will have to bypass this function if a dead key was just passed, although the documentation doesn't say that.  I guess it's just another case where MS's documentation is inadequate to tell the whole story.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today

From novice to tech pro — start learning today.