C# で IME 操作(3)

ImmGetCompositionString() で文字の読み仮名を返してもらう場合、半角カナで返ってくるので、全角に直すための関数を用意しておく。

private static Dictionary<char, char> hKanaToHiraDic;
private static Dictionary<char, char> hKanaToHiraDic2;
private static Dictionary<char, char> hKanaToHiraDic3;

/// <summary>
/// 半角カナを、全角かなに変換する
/// </summary>
/// <param name="src"></param>
/// <returns></returns>
public static string HalfKatakanaToHiragana(string src)
{
    if (src == null)
    {
        throw new ArgumentNullException("ソース文字列が null");
    }

    if (hKanaToHiraDic == null)
    {
        hKanaToHiraDic = new Dictionary<char, char>();
        hKanaToHiraDic2 = new Dictionary<char, char>();
        hKanaToHiraDic3 = new Dictionary<char, char>();
        const string hKanaString = "アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲンァィゥェォッャュョ";
        const string hiraString = "あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもやゆよらりるれろわをんぁぃぅぇぉっゃゅょ";
        const string hKanaString2 = "カキクケコサシスセソタチツテトハヒフヘホ";
        const string hiraString2 = "がぎぐげござじずぜぞだぢづでどばびぶべぼ";
        const string hKanaString3 = "ハヒフヘホ";
        const string hiraString3 = "ぱぴぷぺぽ";
        for (int i = 0; i < hiraString.Length; i++)
        {
            hKanaToHiraDic.Add(hKanaString[i], hiraString[i]);
        }
        for (int i = 0; i < hiraString2.Length; i++)
        {
            hKanaToHiraDic2.Add(hKanaString2[i], hiraString2[i]);
        }
        for (int i = 0; i < hiraString3.Length; i++)
        {
            hKanaToHiraDic3.Add(hKanaString3[i], hiraString3[i]);
        }
    }

    string dst = "";
    int n = 0;
    while (n < src.Length)
    {
        char c = src[n];
        char d = ' ';
        int skip = 1;
        // 'ア'から'ン'までのいずれかだったら
        if (hKanaToHiraDic.ContainsKey(c))
        {
            // 処理は完了してるか否か
            bool b = false;

            // 濁点、半濁点の可能性があるか
            if (hKanaToHiraDic2.ContainsKey(c) || hKanaToHiraDic3.ContainsKey(c))
            {
                // 次の文字をみる
                if (n + 1 < src.Length)
                {
                    char c2 = src[n + 1];
                    switch (c2)
                    {
                        case '゙':
                            d = hKanaToHiraDic2[c];
                            skip = 2;
                            b = true;
                            break;
                        case '゚':
                            d = hKanaToHiraDic3[c];
                            skip = 2;
                            b = true;
                            break;
                    }
                }
            }

            // 濁点、半濁点ではなかったので、普通のひらがなとして変換
            if (!b)
            {
                // 普通のひらがなに変換
                d = hKanaToHiraDic[c];
            }
        }
        else
        {
            // 半角カナじゃないので飛ばす
            d = c;
        }
        // 文字追加
        dst += d;

        // 次の検索文字へ
        n += skip;
    }

    return dst;
}

'!' や '?' といった記号も全角に変換したい場合は、hKanaString と hiraString にそれぞれ半角文字と全角文字を追加すればいい。