Question: The code page on my Windows is set to ANSI (Latin1, Windows-1252).  

I create a font with CreateFont and pass RUSSIAN\_CHARSET in fdwCharSet

This is what I experience:

* Windows controls (like a Static for example) using this font ignore the font's character set: the string passed to SetWindowTextA is displayed with Latin characters
* After selecting this font on the DC, GDI text functions (Ext)TextOutA and DrawTextA use the character set of the font. Strings passed to them are displayed with cyrillic letters.

Why? When is the charset parameter of the font taken into account and when is it ignored? Can I force windows controls to use the font's character set?

Answer: 
You will have to convert the text to Unicode and call `SetWindowTextW()` instead of `SetWindowTextA()`.

Make sure the window's class is registered with `RegisterClassW()` and not `RegisterClassA()`. This is what really determines if a window is Unicode. You can use `IsWindowUnicode()` to verify that the window is really Unicode.

Make sure you pass unhandled messages to `DefWindowProcW()` and not `DefWindowProcA()`.

Or, if the window is a dialog, just make sure it is created with `CreateDialogW()` or `DialogBoxParamW()`.
Here is what is happening:

1. You call SetWindowText with something like `"\xC4\xEE\xE1\xF0\xEE\xE5 xF3\xF2\xF0\xEE"`.
2. You're compiled as an ANSI application rather than Unicode, so that maps to a call to SetWindowTextA.
3. SetWindowTextA sees that the window was created in ANSI mode, so it sets the string directly. (If it had been a Unicode window, then it would converts the ANSI input string to Unicode and passes it onto SetWindowTextW.)
4. The ANSI window converts the ANSI string to Unicode so that it can display it. But it doesn't know the string is in a different code page than the default one for the system. It's this conversion that's changing everything back to Latin characters. It assumes that the input string is in the process's default code page (Windows 1252 in your case). So now you have a bunch of accented Latin characters instead of a string of Cyrillic ones.
5. The control tries to display this Unicode string using something like DrawTextW or TextOutW.
6. The lower level part of the system says, "Oh crap, this string is a bunch of Latin characters, but the user has chosen a Cyrillic font." To solve the problem, it uses font linking (or font fallback, I get those terms confused) to effectively select a font compatible with 1252.
7. You see Latin gobbledygook instead of proper Russian.

I tried coming up with a minimal way to do what you need, but I failed. My first idea was to do the conversion yourself and call SetWindowTextW directly:

```
void SetWindowTextRussian(HWND hwnd, char *pszCyrillic) {
    const int cchCyrillic = ::lstrlen(pszCyrillic);
    const int cchUnicode = 4 * cchCyrillic;  // worst case
    WCHAR *pszUnicode = new WCHAR[cchUnicode];

    // See: http://msdn.microsoft.com/en-us/library/dd317756(v=vs.85).aspx
    const UINT CP_CYRILLIC = 1251;
    if (::MultiByteToWideChar(CP_CYRILLIC, 0, pszCyrillic, -1,
                              pszUnicode, cchUnicode) > 0) {
        ::SetWindowTextW(hwnd, pszUnicode);
    }

    delete [] pszUnicode;
}

```

But this doesn't work. I suspect that since the window was created as an ANSI window, the Unicode string is converted back to ANSI (assuming the wrong code page again), and then you get question marks instead of Latin nonsense.

I think you're going to have to convert to a Unicode app, or only run with the default code page set to 1251.

**Update**: If you control the creation of the window (e.g., you call CreateWindow directly rather than having a dialog box instantiate the controls), then you can probably make the above work by calling CreateWindowW directly and creating a Unicode window for the controls that matter.