117 lines
3.5 KiB
C#
117 lines
3.5 KiB
C#
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
|
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
|
|
|
using System;
|
|
using System.ComponentModel;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Runtime.InteropServices;
|
|
using System.Security;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Input;
|
|
using System.Windows.Interop;
|
|
using System.Windows.Media;
|
|
using System.Windows.Media.TextFormatting;
|
|
using ICSharpCode.AvalonEdit;
|
|
using ICSharpCode.AvalonEdit.Document;
|
|
using ICSharpCode.AvalonEdit.Rendering;
|
|
|
|
namespace ICSharpCode.AvalonEdit.Editing
|
|
{
|
|
class ImeSupport
|
|
{
|
|
readonly TextArea textArea;
|
|
IntPtr currentContext;
|
|
//IntPtr previousContext;
|
|
HwndSource hwndSource;
|
|
|
|
public ImeSupport(TextArea textArea)
|
|
{
|
|
if (textArea == null)
|
|
throw new ArgumentNullException("textArea");
|
|
this.textArea = textArea;
|
|
InputMethod.SetIsInputMethodSuspended(this.textArea, true);
|
|
textArea.OptionChanged += TextAreaOptionChanged;
|
|
currentContext = IntPtr.Zero;
|
|
}
|
|
|
|
void TextAreaOptionChanged(object sender, PropertyChangedEventArgs e)
|
|
{
|
|
if (e.PropertyName == "EnableImeSupport" && textArea.IsKeyboardFocused) {
|
|
CreateContext();
|
|
}
|
|
}
|
|
|
|
void ClearContext()
|
|
{
|
|
if (hwndSource != null) {
|
|
//ImeNativeWrapper.AssociateContext(hwndSource, previousContext);
|
|
//ImeNativeWrapper.ImmDestroyContext(currentContext);
|
|
ImeNativeWrapper.ReleaseContext(hwndSource, currentContext);
|
|
currentContext = IntPtr.Zero;
|
|
hwndSource.RemoveHook(WndProc);
|
|
hwndSource = null;
|
|
}
|
|
}
|
|
|
|
public void OnGotFocus(KeyboardFocusChangedEventArgs e)
|
|
{
|
|
CreateContext();
|
|
}
|
|
|
|
void CreateContext()
|
|
{
|
|
ClearContext(); // clear old context if necessary
|
|
if (!textArea.Options.EnableImeSupport)
|
|
return;
|
|
hwndSource = (HwndSource)PresentationSource.FromVisual(this.textArea);
|
|
if (hwndSource != null) {
|
|
//currentContext = ImeNativeWrapper.ImmCreateContext();
|
|
//previousContext = ImeNativeWrapper.AssociateContext(hwndSource, currentContext);
|
|
currentContext = ImeNativeWrapper.GetContext(hwndSource);
|
|
hwndSource.AddHook(WndProc);
|
|
// UpdateCompositionWindow() will be called by the caret becoming visible
|
|
|
|
var threadMgr = ImeNativeWrapper.GetTextFrameworkThreadManager();
|
|
if (threadMgr != null) {
|
|
// Even though the docu says passing null is invalid, this seems to help
|
|
// activating the IME on the default input context that is shared with WPF
|
|
threadMgr.SetFocus(IntPtr.Zero);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void OnLostFocus(KeyboardFocusChangedEventArgs e)
|
|
{
|
|
if (e.OldFocus == textArea && currentContext != IntPtr.Zero)
|
|
ImeNativeWrapper.NotifyIme(currentContext);
|
|
ClearContext();
|
|
}
|
|
|
|
IntPtr WndProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
|
|
{
|
|
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;
|
|
case ImeNativeWrapper.WM_IME_COMPOSITION:
|
|
UpdateCompositionWindow();
|
|
break;
|
|
}
|
|
return IntPtr.Zero;
|
|
}
|
|
|
|
public void UpdateCompositionWindow()
|
|
{
|
|
if (currentContext != IntPtr.Zero) {
|
|
ImeNativeWrapper.SetCompositionFont(hwndSource, currentContext, textArea);
|
|
ImeNativeWrapper.SetCompositionWindow(hwndSource, currentContext, textArea);
|
|
}
|
|
}
|
|
}
|
|
} |