Hello there. I'm new here and I want to ask help to you on solving this problem. I'm trying to detect which character is produced whenever the user presses a key. For this, I'm using the ToUnicodeEx function, which translates the specified virtual-key code and keyboard state to the corresponding Unicode character, inside a keyboard system wide hook. However, every time the user presses dead keys, such as the ones producing '', '~' or '', strange things happen. Here is sample code of the first version:

Code:
private static int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam)
{
	//indicates if any of underlaing events set e.Handled flag
	bool handled = false;

	if (nCode >= 0)
	{
		//read structure KeyboardHookStruct at lParam
		KeyboardHookStruct MyKeyboardHookStruct = (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));
		//raise KeyDown
		if (s_KeyDown != null && (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN))
		{
			Keys keyData = (Keys)MyKeyboardHookStruct.VirtualKeyCode;
			KeyEventArgs e = new KeyEventArgs(keyData);
			s_KeyDown.Invoke(null, e);
			handled = e.Handled;
		}

		// raise KeyPress
		if (s_KeyPress != null && wParam == WM_KEYDOWN)
		{
			bool isDownShift = ((GetKeyState(VK_SHIFT) & 0x80) == 0x80 ? true : false);
			bool isDownCapslock = (GetKeyState(VK_CAPITAL) != 0 ? true : false);

			byte[] keyState = new byte[256];
			GetKeyboardState(keyState);
			System.Text.StringBuilder sbString = new System.Text.StringBuilder();
			IntPtr HKL = GetKeyboardLayout(0);

			switch (ToUnicodeEx((uint)MyKeyboardHookStruct.VirtualKeyCode,
				(uint)MyKeyboardHookStruct.ScanCode,
				keyState,
				sbString,
				5,
				(uint)MyKeyboardHookStruct.Flags,
				HKL))
			{
				case 1:
					char key = sbString.ToString()[0];
					if ((isDownCapslock ^ isDownShift) && Char.IsLetter(key)) key = Char.ToUpper(key);
					KeyPressEventArgs e = new KeyPressEventArgs(key);
					s_KeyPress.Invoke(null, e);
					handled = handled || e.Handled;
					break;
			}
		}

		// raise KeyUp
		if (s_KeyUp != null && (wParam == WM_KEYUP || wParam == WM_SYSKEYUP))
		{
			Keys keyData = (Keys)MyKeyboardHookStruct.VirtualKeyCode;
			KeyEventArgs e = new KeyEventArgs(keyData);
			s_KeyUp.Invoke(null, e);
			handled = handled || e.Handled;
		}

	}

	//if event handled in application do not handoff to other listeners
	if (handled)
		return -1;

	//forward to other application
	return CallNextHookEx(s_KeyboardHookHandle, nCode, wParam, lParam);
}
(I know the sample code I'm posting is C#, but it is really easy to read and the question here is about the ToUnicodeEx WinAPI call.)

With this code I faced the following problem: Whenever I tried to type "" in notepad, which requires '' to be pressed before 'a', the result would be "a". Although the captured character by ToUnicodeEx was '', I can't admit that my application prevents the user from using characters such as ''.

So, I worked around this problem by avoiding ToUnicodeEx to be called whenever a dead key is pressed. This way, I can avoid the ToUnicodeEx function from messing with the keyboard state. Here is the current version code:

Code:
private static int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam)
{
	//indicates if any of underlaing events set e.Handled flag
	bool handled = false;

	if (nCode >= 0)
	{
		//read structure KeyboardHookStruct at lParam
		KeyboardHookStruct MyKeyboardHookStruct = (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));
		//raise KeyDown
		if (s_KeyDown != null && (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN))
		{
			Keys keyData = (Keys)MyKeyboardHookStruct.VirtualKeyCode;
			KeyEventArgs e = new KeyEventArgs(keyData);
			s_KeyDown.Invoke(null, e);
			handled = e.Handled;
		}

		// raise KeyPress
		if (s_KeyPress != null && wParam == WM_KEYDOWN)
		{
			bool isDownShift = ((GetKeyState(VK_SHIFT) & 0x80) == 0x80 ? true : false);
			bool isDownCapslock = (GetKeyState(VK_CAPITAL) != 0 ? true : false);

			byte[] keyState = new byte[256];
			GetKeyboardState(keyState);
			System.Text.StringBuilder sbString = new System.Text.StringBuilder();
			IntPtr HKL = GetKeyboardLayout(0);

			if (!IsDeadKey((uint)MyKeyboardHookStruct.VirtualKeyCode))
			{
				switch (ToUnicodeEx((uint)MyKeyboardHookStruct.VirtualKeyCode,
					(uint)MyKeyboardHookStruct.ScanCode,
					keyState,
					sbString,
					5,
					(uint)MyKeyboardHookStruct.Flags,
					HKL))
				{
					case 1:
						char key = sbString.ToString()[0];
						if ((isDownCapslock ^ isDownShift) && Char.IsLetter(key)) key = Char.ToUpper(key);
						KeyPressEventArgs e = new KeyPressEventArgs(key);
						s_KeyPress.Invoke(null, e);
						handled = handled || e.Handled;
						break;
				}
			}
		}

		// raise KeyUp
		if (s_KeyUp != null && (wParam == WM_KEYUP || wParam == WM_SYSKEYUP))
		{
			Keys keyData = (Keys)MyKeyboardHookStruct.VirtualKeyCode;
			KeyEventArgs e = new KeyEventArgs(keyData);
			s_KeyUp.Invoke(null, e);
			handled = handled || e.Handled;
		}

	}

	//if event handled in application do not handoff to other listeners
	if (handled)
		return -1;

	//forward to other application
	return CallNextHookEx(s_KeyboardHookHandle, nCode, wParam, lParam);
}

static bool IsDeadKey(uint key)
{
	if ((MapVirtualKey(key, 2) & 2147483648) == 2147483648)
	{
		return true;
	}
	else
	{
		return false;
	}
}
I though this solution would solve my problem, but I was wrong. The result has improved, but it's not quite what I wanted. Now, typing '' in notepad results in 'a'. Notice that the accent '' is missing.

Does anyone know how to work around this issue? My current method already captures the correct character, but prevents the user from producing characters with accents or diacritics. I think the KeyboardHookProc method just need a few changes, but I can't figure them out.

Thanks in advance.

PS: I tried the solution described in the following link: http://social.msdn.microsoft.com/For...1-33c7ccea735c. However, the result is quite the same as in my current version. That code only erases the keyboard buffer, which deletes the accents, therefore not allowing the user to use them.