TextBox に入力済みの文字列を考慮して IME でかな漢字変換できるようにします。「IMEの前後参照変換機能に対応するには」が大変参考になりました。ありがとうございます。
【花が】「さいた」 →[花が咲いた]
IMEの前後参照変換機能に対応するには
【布を】「さいた」 →[布を裂いた]
【時間を】「さいた」 →[時間を割いた]
という風に、文脈を読んだ変換をしてくれます。ちなみにこの機能は IME がサポートしている必要があります。以下のソースコードをコンパイルし、Windows 7 上の ATOK を使って試してみました*1。
コードはあんまり自信ないです。ご利用の際は注意してください。
using System; using System.Diagnostics; using System.Runtime.InteropServices; using System.Text; using System.Windows.Forms; namespace Zengo { class TextBoxEx : TextBox { private const int WM_IME_REQUEST = 0x0288; private const int IMR_DOCUMENTFEED = 0x0007; public struct RECONVERTSTRING { public uint dwSize; public uint dwVersion; public uint dwStrLen; public uint dwStrOffset; public uint dwCompStrLen; public uint dwCompStrOffset; public uint dwTargetStrLen; public uint dwTargetStrOffset; } protected override void WndProc(ref Message m) { // Multiline のことは考えてない。 // てきとー実装なのでとりあえず動くだけ。 unsafe { if (m.Msg == WM_IME_REQUEST && (int)m.WParam == IMR_DOCUMENTFEED) { uint len = (uint)SelectionStart; if (m.LParam.ToInt32() != 0) { RECONVERTSTRING* reconv = (RECONVERTSTRING*)m.LParam.ToPointer(); char* paragraph = (char*)((byte*)reconv + sizeof(RECONVERTSTRING)); reconv->dwSize = (uint)sizeof(RECONVERTSTRING); reconv->dwVersion = 0; reconv->dwStrLen = len; reconv->dwStrOffset = (uint)sizeof(RECONVERTSTRING); reconv->dwCompStrLen = 0; reconv->dwCompStrOffset = len * sizeof(char); reconv->dwTargetStrLen = len; reconv->dwTargetStrOffset = len * sizeof(char); for (int i = 0; i < SelectionStart; i++) { paragraph[i] = Text[i]; } } m.Result = new IntPtr(sizeof(RECONVERTSTRING) + len * sizeof(char)); return; } } base.WndProc(ref m); } } }
ポインタつかっちゃっててなぜだか負けた気がする・・・。