diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/Caret.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/Caret.cs index c82f906040..a2ed0e1ecd 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/Caret.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/Caret.cs @@ -22,7 +22,6 @@ namespace ICSharpCode.AvalonEdit.Editing { readonly TextArea textArea; readonly TextView textView; - readonly ImeSupport ime; readonly CaretLayer caretAdorner; bool visible; @@ -31,7 +30,6 @@ namespace ICSharpCode.AvalonEdit.Editing this.textArea = textArea; this.textView = textArea.TextView; position = new TextViewPosition(1, 1, 0); - ime = new ImeSupport(textArea); caretAdorner = new CaretLayer(textView); textView.InsertLayer(caretAdorner, KnownLayer.Caret, LayerInsertionPosition.Replace); @@ -436,7 +434,7 @@ namespace ICSharpCode.AvalonEdit.Editing } else { caretAdorner.Hide(); } - ime.UpdateCompositionWindow(); + textArea.ime.UpdateCompositionWindow(); } } diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/ImeNativeWrapper.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/ImeNativeWrapper.cs index 70572c94d2..36744269ac 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/ImeNativeWrapper.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/ImeNativeWrapper.cs @@ -76,16 +76,23 @@ namespace ICSharpCode.AvalonEdit.Editing public const int WM_IME_SETCONTEXT = 0x281; public const int WM_INPUTLANGCHANGE = 0x51; + [DllImport("imm32.dll")] + public static extern IntPtr ImmCreateContext(); + + [DllImport("imm32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool ImmDestroyContext(IntPtr hIMC); + [DllImport("imm32.dll")] static extern IntPtr ImmAssociateContext(IntPtr hWnd, IntPtr hIMC); [DllImport("imm32.dll")] static extern IntPtr ImmGetContext(IntPtr hWnd); [DllImport("imm32.dll")] [return: MarshalAs(UnmanagedType.Bool)] - static extern bool ImmNotifyIME(IntPtr hIMC, int dwAction, int dwIndex, int dwValue = 0); + static extern bool ImmReleaseContext(IntPtr hWnd, IntPtr hIMC); [DllImport("imm32.dll")] [return: MarshalAs(UnmanagedType.Bool)] - static extern bool ImmReleaseContext(IntPtr hWnd, IntPtr hIMC); + static extern bool ImmNotifyIME(IntPtr hIMC, int dwAction, int dwIndex, int dwValue = 0); [DllImport("imm32.dll")] [return: MarshalAs(UnmanagedType.Bool)] static extern bool ImmSetCompositionWindow(IntPtr hIMC, ref CompositionForm form); diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/ImeSupport.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/ImeSupport.cs index fd137c112d..abf075981a 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/ImeSupport.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/ImeSupport.cs @@ -19,11 +19,10 @@ using ICSharpCode.AvalonEdit.Rendering; namespace ICSharpCode.AvalonEdit.Editing { - class ImeSupport : IDisposable + class ImeSupport { - TextArea textArea; + readonly TextArea textArea; IntPtr currentContext; - IntPtr previousContext; HwndSource hwndSource; public ImeSupport(TextArea textArea) @@ -32,47 +31,29 @@ namespace ICSharpCode.AvalonEdit.Editing throw new ArgumentNullException("textArea"); this.textArea = textArea; InputMethod.SetIsInputMethodSuspended(this.textArea, true); - textArea.GotKeyboardFocus += TextAreaGotKeyboardFocus; - textArea.LostKeyboardFocus += TextAreaLostKeyboardFocus; textArea.OptionChanged += TextAreaOptionChanged; currentContext = IntPtr.Zero; - previousContext = IntPtr.Zero; } void TextAreaOptionChanged(object sender, PropertyChangedEventArgs e) { - if (e.PropertyName == "EnableImeSupport" && textArea.IsKeyboardFocusWithin) { + if (e.PropertyName == "EnableImeSupport" && textArea.IsKeyboardFocused) { CreateContext(); } } - - public void Dispose() - { - if (textArea != null) { - textArea.GotKeyboardFocus -= TextAreaGotKeyboardFocus; - textArea.LostKeyboardFocus -= TextAreaLostKeyboardFocus; - textArea.OptionChanged -= TextAreaOptionChanged; - textArea = null; - } - ClearContext(); - } void ClearContext() { if (hwndSource != null) { - hwndSource.RemoveHook(WndProc); - ImeNativeWrapper.AssociateContext(hwndSource, previousContext); - previousContext = IntPtr.Zero; ImeNativeWrapper.ReleaseContext(hwndSource, currentContext); - hwndSource = null; currentContext = IntPtr.Zero; + hwndSource.RemoveHook(WndProc); + hwndSource = null; } } - void TextAreaGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e) + public void OnGotFocus(KeyboardFocusChangedEventArgs e) { - if (e.OriginalSource != this.textArea) - return; CreateContext(); } @@ -84,17 +65,15 @@ namespace ICSharpCode.AvalonEdit.Editing hwndSource = (HwndSource)PresentationSource.FromVisual(this.textArea); if (hwndSource != null) { currentContext = ImeNativeWrapper.GetContext(hwndSource); - previousContext = ImeNativeWrapper.AssociateContext(hwndSource, currentContext); // ImeNativeWrapper.SetCompositionFont(hwndSource, currentContext, textArea); hwndSource.AddHook(WndProc); + // UpdateCompositionWindow() will be called by the caret becoming visible } } - void TextAreaLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e) + public void OnLostFocus(KeyboardFocusChangedEventArgs e) { - if (e.OriginalSource != this.textArea) - return; - if (currentContext != IntPtr.Zero) + if (e.OldFocus == textArea && currentContext != IntPtr.Zero) ImeNativeWrapper.NotifyIme(currentContext); ClearContext(); } @@ -103,6 +82,8 @@ namespace ICSharpCode.AvalonEdit.Editing { switch (msg) { case ImeNativeWrapper.WM_INPUTLANGCHANGE: + // Don't mark the message as handled; other windows + // might want to handle it as well. ClearContext(); CreateContext(); break; @@ -115,7 +96,7 @@ namespace ICSharpCode.AvalonEdit.Editing public void UpdateCompositionWindow() { - if (currentContext != IntPtr.Zero && textArea != null) { + if (currentContext != IntPtr.Zero) { ImeNativeWrapper.SetCompositionWindow(hwndSource, currentContext, textArea); } } diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/TextArea.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/TextArea.cs index c74cebb683..3eaffdedc9 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/TextArea.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/TextArea.cs @@ -29,6 +29,8 @@ namespace ICSharpCode.AvalonEdit.Editing /// public class TextArea : Control, IScrollInfo, IWeakEventListener, ITextEditorComponent, IServiceProvider { + internal readonly ImeSupport ime; + #region Constructor static TextArea() { @@ -68,6 +70,7 @@ namespace ICSharpCode.AvalonEdit.Editing caret = new Caret(this); caret.PositionChanged += (sender, e) => RequestSelectionValidation(); + ime = new ImeSupport(this); leftMargins.CollectionChanged += leftMargins_CollectionChanged; @@ -754,6 +757,8 @@ namespace ICSharpCode.AvalonEdit.Editing protected override void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e) { base.OnGotKeyboardFocus(e); + // First activate IME, then show caret + ime.OnGotFocus(e); caret.Show(); } @@ -762,6 +767,7 @@ namespace ICSharpCode.AvalonEdit.Editing { base.OnLostKeyboardFocus(e); caret.Hide(); + ime.OnLostFocus(e); } #endregion