1
Vote

[PATCH] sometimes XNA window is in code-page mode and diacritics cause garbage

description

On my Windows 7 system XNA in windowed mode is in code-page mode, causing WM_CHAR to return code-page garbage instead of nice UTF-16. WM_UNICHAR apparently isn't emitted at all. After patching the problem goes away and I can zażółcić gę

file attachments

comments

Cygon wrote Aug 13, 2011 at 8:47 AM

Do you have any links or explanation for when a window or process will enter Code Page mode? As far as I know, everything depends on whether XNA uses RegisterClassA() or RegisterClassW() when setting up the game window and that shouldn't change. The only case I can imagine where the window might be an ANSI window would be when someone uses Nuclex.Input on a window created manually via P/Invoke.

I'll try to handle these cases in the next released version, but I'd really love to know why this is happening.

sthalik wrote Sep 20, 2011 at 10:10 PM

Sorry, no idea. Created a game the usual way, double-clicked the .exe without any compatibility tweaks or anything. It just happened. Program.cs was just Game.Run() as it should be.

elisee wrote Jan 26, 2012 at 6:44 PM

(I tried to apply the diff to the current Nuclex codebase but it doesn't fix the problem at least for me - I'm running Windows 7).

I've been working on an XNA text input system similar in design to Nuclex's and stumbled upon the same codepage-related issue. Basically if I switch to a Russian keyboard layout and start typing, the WM_CHAR messages I receive are codepage-local and not UTF-16. There is apparently a way to convert the character from the codepage to a Unicode codepoint (with MultiByteToWideChar?), but you can't even get the currently used codepage. (You can get the system's default codepage but it's different from active one)

I just spent upwards of 6 hours trying to find a fix, and I just managed to get it to work, so here it is: for some weird reason, the window created by XNA isn't Unicode-aware (even though all Windows Forms windows are supposed to be). The Win32 api has a IsWindowUnicode() function which allowed me to verify this (it returns false).

This means that WM_CHAR messages are codepage-local, not UTF-16. (I think we should get WM_UNICHAR messages in UTF-32 but nobody seems to get those...)

The solution is very simple in concept: in the constructor of your Game-inheriting class, force the window to be Unicode-aware by running this:

SetWindowLongW( Window.Handle, (int)GWL.GWL_WNDPROC, GetWindowLong( Window.Handle, (int)GWL.GWL_WNDPROC ) );

You can check this diff for the full code with the necessary DllImports & enum: http://nuclearwinter.codeplex.com/SourceControl/changeset/changes/db94450ddac0#NuclearWinter%2fNuclearGame.cs

Hope this helps!

sthalik wrote Jan 26, 2012 at 7:23 PM

elisee, thank you very much for tracking this issue down after so much time passed! :-)

wrote Feb 21, 2013 at 11:26 PM