2

ユーザーがアプリケーション フィールドにデータを入力しているときに、キーボード入力が使用しているコード ページを検出する必要があります。

使用しようとしましSystem.Text.Encoding.Default.CodePage;たが、地域設定で構成されているコードページが表示されます。

その後、うまくいくと思いConsole.InputEncoding.CodePage;ましたが、それでもコードページは上記の例と同じです。

問題は、ユーザーが地域設定のためにキリル文字 (Windows-1251) コード ページを使用している可能性があることですが、別の入力言語を使用したい場合があります。ユーザーが入力したデータはファイルに保存され、そのファイルは異なる地域設定を持つシステムで開くことができます。テキストとともに、コード ページ番号を保存しているので、アプリはファイルを読み込んでテキストを正しく表示できます。Unicode をサポートしていない別のアプリとの相互互換性のために Unicode を使用できません。

4

1 に答える 1

3

免責事項:私は .NET Framework のグローバリゼーション側の専門家ではないため、同等の機能がどこかにラップされている可能性があります。もしそうなら、あなたはそれを見つけることができます.素晴らしい - 代わりにそれを使用してください. Globalization.CultureInfo.CurrentCulture探している情報が返されるのではないかと思っていましたが、残念ながらそうではありません。代わりに、キーボード レイアウトが変更された場合でも、システムの既定のカルチャを返すように見えます。調べるのをやめました。説明されているアプローチは、コードが少し追加されますが、動作することが保証されています。

特定のキーボード レイアウトに関連付けられているコード ページを確認するには、Win32GetLocaleInfo関数を呼び出して、現在のキーボード レイアウトに関連付けられている言語 ID を指定します。LOCALE_IDEFAULTANSICODEPAGE定数を使用してこれを要求します。

これらの関数を .NET アプリケーションから呼び出すには、P/Invoke を使用する必要があります。また、いくつかの重要なマクロに対して同等の関数を定義する必要があります。

const int LOCALE_IDEFAULTANSICODEPAGE = 0x1004;
const int LOCALE_RETURN_NUMBER        = 0x20000000;
const int SORT_DEFAULT                = 0x0;

static int LOWORD(IntPtr val)
{
   return (unchecked((int)(long)val)) & 0xFFFF;
}

static int MAKELCID(int languageID, int sortID)
{
   return ((0xFFFF & languageID) | (((0x000F) & sortID) << 16));
}

static int MAKELANGID(int primaryLang, int subLang)
{
   return ((((ushort)(subLang)) << 10) | (ushort)(primaryLang));
}

[DllImport("kernel32.dll", SetLastError = true)]
static extern int GetLocaleInfo(int locale,
                                 int lcType,
                                 out uint lpLCData,
                                 int cchData);

[DllImport("user32.dll")]
static extern IntPtr GetKeyboardLayout(uint idThread);

次のように使用します。

// Get the keyboard layout for the current thread.
IntPtr keybdLayout = GetKeyboardLayout(0);

// Extract the language ID from it, contained in its low-order word.
int langID = LOWORD(keybdLayout);

// Call the GetLocaleInfo function to retrieve the default ANSI code page
// associated with that language ID.
uint codePage = 0;
GetLocaleInfo(MAKELCID(langID, SORT_DEFAULT),
               LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER,
               out codePage,
               Marshal.SizeOf(codePage));

米国英語のキーボード レイアウトでテストすると、codePage1252 です。ギリシャ語のキーボード レイアウトに切り替えた後codePageは、1253 です。同様に、トルコ語は 1254 を返し、さまざまなキリル言語は 1251 を返します。文書化されているとおりです。

リンクされたドキュメントでは、これらの API 関数は置き換えられたものとして示されていることに注意してください。最新バージョンの Windows では、Microsoft は名前付きロケールに移行しました。これは、最初に数値 ID の余地がなかったためであり、次にカスタム ロケールのサポートを有効にするためでした。ただし、実行していることには古い関数を使用する必要があります。最新の Windows アプリケーションも ANSI コード ページを使用していません。

ただし、逆に噛まれてしまうこともあるので注意が必要です。ANSI コード ページが関連付けられていないキーボード レイアウトがあります。これらには、Unicode のみを使用できます。上記のコードはCP_ACP(数値に相当する) を返します0。その扱いはあなた次第です。エラーを表示するか、ファイルを Unicode として保存する必要があります (他のアプリケーションを壊しますが、ユーザーの期待に応えます)。

最後に、値をキャッシュするcodePageと、ユーザーがいつでもキーボード レイアウトを変更できるため、値が古くなる可能性があることを指摘しておく必要があります。保存を実行するたびに値を決定して、値をキャッシュしない方がおそらく最も簡単です。WM_INPUTLANGCHANGEただし、キャッシュする場合は、メッセージを処理し、それに応じてキャッシュされた値を更新する必要があります。

于 2014-05-20T07:21:24.063 に答える