C#からIMEを使って逆検索でかな変換する | .NET Framework 2.0 と C#での開発ブログ

C#からIMEを使って逆検索でかな変換する

ひさしぶりの日記更新です。
Insider.NETに面白い情報があったのでメモメモ。

C#でMS-IMEを使い、辞書の逆検索によりかな変換を行うものです。

「例えば」 => 「たとえば」

こんなことがIMEで出来ます。
(ちなみに知らなかったのですがたとえばIEのアドレスバーとかに漢字やカタカナを入力して、選択 > 右クリックすると下のほうに再変換ってのが出ます。これを使えば言葉道理再変換したり全部ひらがなにしたりすることが出来ます)

もちろんこれは以前ご紹介したMecab等の形態素解析器で出来ますし、そっちのほうが精度高い感じがしますが、私が引かれたのはMS-IMEが標準で用意されているので辞書ファイルが既に用意されているってことです。
なので辞書ファイルの配布が必要なく、もし、ダウンロードして使うソフトを配布するのなら、相当違いますね。

ってか、もともとMS-IMEを使ってかな変換できるのは知ってたんですよ。
でも私の知識が低いためか、用途がせまく、ふりがなをふる等には使えないなぁーと思ってMecab様を調べてたんです。

例えば
「ひさしぶりの日記更新です」 = > 「ひさしぶりのにっきこうしんです」
というのはできますが、これを品詞ごとに分ける方法がわからない。

「ひさしぶり」 = > 「ひさしぶり」
「の」 = > 「の」
「日記」 = > 「にっき」
「更新」 = > 「こうしん」
「です」 = > 「です」

(↑超適当にわけてますW)

こんな感じにしないとふりがなはつけれないんですね。
だってどこのふりがななのかわからないですから。

なので諦めてたのですが、最近ちょっと試してみようかなぁと思っているのは、例えば、Mecabで”わかちがき”をしてそれをMS-IMEでかな変換とかだったら、こちらが用意しなければならない辞書がすげー減るんじゃん?ってことです。
まあ、面倒な話ではありますけど、、、

さてC#でMS-IMEを使うサンプルですが、こんな感じで私の環境では動いたと思います。


(情報源:http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=7712&forum=7)
-----------------------------------------------------------------------------------------
const int GCL_REVERSECONVERSION = 0x0002;

[DllImport("Imm32.dll")]
public static extern IntPtr ImmGetContext(IntPtr hWnd);

[DllImport("User32.dll")]
public static extern IntPtr GetKeyboardLayout(int idThread);

[DllImport("Imm32.dll")]
public static extern int ImmGetConversionList(
IntPtr hKL,
IntPtr hIMC,
string lpSrc,
IntPtr lpDst,
int dwBufLen,
int uFlag
);

[DllImport("Imm32.dll")]
public static extern bool ImmReleaseContext(IntPtr hWnd, IntPtr hIMC);

[StructLayout(LayoutKind.Sequential)]
public class CANDIDATELIST
{
public int dwSize;
public int dwStyle;
public int dwCount;
public int dwSelection;
public int dwPageStart;
public int dwPageSize;
public int dwOffset;
}

public string GetReverseConversion(string AText)
{
IntPtr hIMC = ImmGetContext(this.Handle);
IntPtr hKL = GetKeyboardLayout(0);
CANDIDATELIST list = new CANDIDATELIST();
int dwSize = ImmGetConversionList(hKL, hIMC, AText, IntPtr.Zero, 0, GCL_REVERSECONVERSION);
IntPtr BufList = Marshal.AllocHGlobal(dwSize);
ImmGetConversionList(hKL, hIMC, AText, BufList, dwSize, GCL_REVERSECONVERSION);
Marshal.PtrToStructure(BufList, list);
byte[] buf = new byte[dwSize];
Marshal.Copy(BufList, buf, 0, dwSize);
Marshal.FreeHGlobal(BufList);
int os = list.dwOffset;
string str = System.Text.Encoding.Default.GetString(buf, os, buf.Length - os - 3);
ImmReleaseContext(this.Handle, hIMC);

return str;
}

上記を用意して、あとは私の場合だとテキストボックス1と2を用意してボタンを押すと1の文字をかな変換して2に表示する感じでテストしました。 (下記、別ソースと間違えてたのを修正しました)

private void button1_Click(object sender, EventArgs e)
{
textBox2.Text = GetReverseConversion(textBox1.Text);
}

-----------------------------------------------------------------------------------------
こんな感じ。テストしたソースをちょっと変更して掲載してるので動作するかわかりませーん。

色々ともう少し色々調べていきたいと思います。

あ~分かち書きもできないかなぁ、、、ってかもうふりがな付きのテキスト返してくれねぇーかな~W