获取"所属的字符列表"对当前的文化

时间:2015-04-21 15:49:09

标签: c# .net vb.net character-encoding cultureinfo

我想创建一个字符串,其中包含当前用户可以在键盘上输入的所有字符。对于英语文化的用户来说,这将是26个大写字母和26个小写字母,10个十进制数字和30个以上的符号。来自其他国家/地区的用户会有不同的字符

我意识到用户可以输入不在他或她的键盘上的字符,但我不能认为他们知道如何做到这一点。我正在寻找一组角色,我认为任何具有当前文化的人都应该能够进入是合理的。如果该集合缺少一个或两个特殊字符,那么它不是世界末日,但我希望它是合理完整的。

我可以通过硬编码或使用这样的函数快速获得美国英语字符集:

Function GetCharacterSet() As String
    Return Enumerable.Range(32, 95).Select(Function(i) Chr(i)).ToArray
End Function

我不确定如何可靠地为其他文化做到这一点。我可以像这样编写函数:

Function GetCharacterSet() As String
    Dim chars As New List(Of Char) 
    For i As Integer = 0 To UInt16.MaxValue 
        Dim ch As Char = ChrW(i)
        If Char.IsLetterOrDigit(ch) OrElse Char.IsPunctuation(ch) OrElse ch = " "c Then 
            chars.Add(ch)
        End If
    Next
    Return chars.ToArray 
End Function

但结果(非常长)字符串包含在任何文化中有效的字符。有没有办法只检查当前文化中的字符是字母,数字还是标点符号?

1 个答案:

答案 0 :(得分:3)

好的,这有点倒退,但到目前为止,我是用键盘布局API管理的最好的:

public class Api
{
    [DllImport("kernel32.dll")]
    public static extern uint GetCurrentThreadId();

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

    [DllImport("user32.dll", CharSet = CharSet.Unicode)]
    public static extern short VkKeyScanEx(char ch, IntPtr dwhkl);
}

class Program
{
    static bool IsRepresentable(char c, IntPtr keyboardLayout)
    {
        var x = Api.VkKeyScanEx(c, keyboardLayout);
        return x != -1;
    }

    static IEnumerable<char> GetKeyboardLayoutCharacters(IntPtr keyboardLayout)
    {
        return
            Enumerable.Range(32, char.MaxValue - 32)
                .Select(n => (char)n)
                .Where(c => IsRepresentable(c, keyboardLayout));
    }

    static void Main(string[] args)
    {
        Console.OutputEncoding = Encoding.UTF8;
        var layout = Api.GetKeyboardLayout(Api.GetCurrentThreadId());
        Console.WriteLine(string.Concat(GetKeyboardLayoutCharacters(layout)));
    }
}

这实际上搜索了所有BMP,并询问是否每个字符都可以由给定的键盘布局表示。不理想,但它返回以下内容:

<强>德语:

 !"#$%&'()*+,-./0123456789:;<=>?@
ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`
abcdefghijklmnopqrstuvwxyz
{|}~§°²³´µÄÖÜßäöüẞ€

<强>抛光:

 !"#$%&'()*+,-./0123456789:;<=>?@
ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`
abcdefghijklmnopqrstuvwxyz
{|}~ÓóĄąĆćĘꣳŃńŚśŹźŻż€

美国英语:

 !"#$%&'()*+,-./0123456789:;<=>?@
ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`
abcdefghijklmnopqrstuvwxyz{|}~

美国国际; - ):

 !"#$%&'()*+,-./0123456789:;<=>?@
ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`
abcdefghijklmnopqrstuvwxyz
{|}~¡¢£¤¥¦§¨©«¬®°²³´µ¶¹»¼½¾¿ÁÄÅÆÇÉÍÐÑÓÖ×ØÚÜÞßáäåæçéíðñóö÷øúüþ‘’€

我很确定必须有一种实际抓取给定键盘布局可以产生的字符的方法,因为上面的列表没有考虑死键(例如US International实际上可以产生ÿ,{ {1}}或õ,但它们不在列表中,因为使用Shift,Ctrl或Alt无法生成它们 - 您必须使用死键。但作为第一个近似值,这可能已经有用了。此外,有些事情很奇怪,其中包括U + 007F( Del ),而不是U + F000和U + F001。可能需要对返回的列表进行额外过滤。

此方法还假定键盘布局对于表示其语言的用户是活动的。但是,如果仅仅是当前用户的语言,则可能最常见的情况。

修改

Vb.Net版

ï