これまで作ってきたプログラムはMicrosoft IMEやATOKを使って日本語が入力されたときには対応していませんでした。今回はこれに対応させます。ところでRicTextBoxの確定文字列を知るにはどうすればいいのでしょうか。
サンプルでつくったアプリ
WndProcをオーバーライドする必要があるのでRichTextBoxを継承する必要があります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
public class ImeEndCompositionArgs { public ImeEndCompositionArgs(string text) { Text = text; } public string Text { get; } } public class RichTextBoxEx : RichTextBox { int imeSelectionStart = 0; public delegate void ImeEndCompositionHandler(object sender, ImeEndCompositionArgs e); public event ImeEndCompositionHandler ImeEndComposition; protected override void WndProc(ref Message m) { const int WM_IME_STARTCOMPOSITION = 0x10D; const int WM_IME_ENDCOMPOSITION = 0x10E; if (m.Msg == WM_IME_STARTCOMPOSITION) { Select(SelectionStart, 0); imeSelectionStart = SelectionStart; Select(imeSelectionStart, 0); base.WndProc(ref m); return; } if (m.Msg == WM_IME_ENDCOMPOSITION) { base.WndProc(ref m); if (imeSelectionStart == SelectionStart) { return; } int len = SelectionStart - imeSelectionStart; int start = imeSelectionStart; this.Select(start, len); string text = SelectedText; SelectedText = ""; ImeEndComposition?.Invoke(this, new ImeEndCompositionArgs(text)); this.Select(start, 0); SelectedText = text; this.Select(start+ len, 0); return; } base.WndProc(ref m); } } |
WM_IME_STARTCOMPOSITIONが来たときに開始点を記憶しておき、WM_IME_ENDCOMPOSITIONが来たときに開始点との差を利用して確定文字列を取得しています。確定文字列を取得するときにカーソルの位置を移動させる必要があるので、ちょっとややこしいことをしています。
独自のイベントを定義することで確定文字列を利用したプログラミングができるようにしています。
では、現在おこなっている複数のRichTextBoxの内容を同期するプログラムにもこれをとりいれてみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
public class RichTextBoxEx : RichTextBox { int imeSelectionStart = 0; public delegate void ImeEndCompositionHandler(object sender, ImeEndCompositionArgs e); public event ImeEndCompositionHandler ImeEndComposition; protected override void WndProc(ref Message m) { const int WM_IME_STARTCOMPOSITION = 0x10D; const int WM_IME_ENDCOMPOSITION = 0x10E; if (m.Msg == WM_IME_STARTCOMPOSITION) { Select(SelectionStart, 0); imeSelectionStart = SelectionStart; Select(imeSelectionStart, 0); base.WndProc(ref m); return; } if (m.Msg == WM_IME_ENDCOMPOSITION) { base.WndProc(ref m); if (imeSelectionStart == SelectionStart) { return; } int len = SelectionStart - imeSelectionStart; int start = imeSelectionStart; this.Select(start, len); string text = SelectedText; SelectedText = ""; ImeEndComposition?.Invoke(this, new ImeEndCompositionArgs(text)); this.Select(start, 0); SelectedText = text; this.Select(start + len, 0); return; } base.WndProc(ref m); } } public partial class SyncRichTextBox : UserControl { public SyncRichTextBox() { // その他、省略 richTextBoxEx1.ImeEndComposition += RichTextBoxEx1_ImeEndComposition; } private void RichTextBoxEx1_ImeEndComposition(object sender, ImeEndCompositionArgs e) { SetSelectedText(e.Text, "ImeEndComposition"); } } |