Browse Source

AvalonEdit IME support: use the default input context, and fix issues with IME not activating in some cases using ITfThreadMgr.SetFocus(null).

pull/28/head
Daniel Grunwald 13 years ago
parent
commit
28453802ea
  1. 47
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/ImeNativeWrapper.cs
  2. 19
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/ImeSupport.cs

47
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/ImeNativeWrapper.cs

@ -76,15 +76,16 @@ namespace ICSharpCode.AvalonEdit.Editing @@ -76,15 +76,16 @@ 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")]
// public static extern IntPtr ImmCreateContext();
//
// [DllImport("imm32.dll")]
// [return: MarshalAs(UnmanagedType.Bool)]
// public static extern bool ImmDestroyContext(IntPtr hIMC);
[DllImport("imm32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool ImmDestroyContext(IntPtr hIMC);
// [DllImport("imm32.dll")]
// public static extern IntPtr ImmAssociateContext(IntPtr hWnd, 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")]
@ -103,11 +104,19 @@ namespace ICSharpCode.AvalonEdit.Editing @@ -103,11 +104,19 @@ namespace ICSharpCode.AvalonEdit.Editing
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool ImmGetCompositionFont(IntPtr hIMC, out LOGFONT font);
public static IntPtr AssociateContext(HwndSource source, IntPtr hIMC)
[DllImport("msctf.dll")]
static extern int TF_CreateThreadMgr(out ITfThreadMgr threadMgr);
[ThreadStatic] static bool textFrameworkThreadMgrInitialized;
[ThreadStatic] static ITfThreadMgr textFrameworkThreadMgr;
public static ITfThreadMgr GetTextFrameworkThreadManager()
{
if (source == null)
throw new ArgumentNullException("source");
return ImmAssociateContext(source.Handle, hIMC);
if (!textFrameworkThreadMgrInitialized) {
textFrameworkThreadMgrInitialized = true;
TF_CreateThreadMgr(out textFrameworkThreadMgr);
}
return textFrameworkThreadMgr;
}
public static bool NotifyIme(IntPtr hIMC)
@ -194,4 +203,20 @@ namespace ICSharpCode.AvalonEdit.Editing @@ -194,4 +203,20 @@ namespace ICSharpCode.AvalonEdit.Editing
.TransformToDevice(source.RootVisual); // rect on HWND
}
}
[ComImport, Guid("aa80e801-2021-11d2-93e0-0060b067b86e"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface ITfThreadMgr
{
void Activate(out int clientId);
void Deactivate();
void CreateDocumentMgr(out object docMgr);
void EnumDocumentMgrs(out object enumDocMgrs);
void GetFocus(out object docMgr);
void SetFocus(object docMgr);
void AssociateFocus(IntPtr hwnd, object newDocMgr, out object prevDocMgr);
void IsThreadFocus([MarshalAs(UnmanagedType.Bool)] out bool isFocus);
void GetFunctionProvider(ref Guid classId, out object funcProvider);
void EnumFunctionProviders(out object enumProviders);
void GetGlobalCompartment(out object compartmentMgr);
}
}

19
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/ImeSupport.cs

@ -23,7 +23,7 @@ namespace ICSharpCode.AvalonEdit.Editing @@ -23,7 +23,7 @@ namespace ICSharpCode.AvalonEdit.Editing
{
readonly TextArea textArea;
IntPtr currentContext;
IntPtr previousContext;
//IntPtr previousContext;
HwndSource hwndSource;
public ImeSupport(TextArea textArea)
@ -46,8 +46,9 @@ namespace ICSharpCode.AvalonEdit.Editing @@ -46,8 +46,9 @@ namespace ICSharpCode.AvalonEdit.Editing
void ClearContext()
{
if (hwndSource != null) {
ImeNativeWrapper.AssociateContext(hwndSource, previousContext);
ImeNativeWrapper.ImmDestroyContext(currentContext);
//ImeNativeWrapper.AssociateContext(hwndSource, previousContext);
//ImeNativeWrapper.ImmDestroyContext(currentContext);
ImeNativeWrapper.ReleaseContext(hwndSource, currentContext);
currentContext = IntPtr.Zero;
hwndSource.RemoveHook(WndProc);
hwndSource = null;
@ -66,11 +67,19 @@ namespace ICSharpCode.AvalonEdit.Editing @@ -66,11 +67,19 @@ namespace ICSharpCode.AvalonEdit.Editing
return;
hwndSource = (HwndSource)PresentationSource.FromVisual(this.textArea);
if (hwndSource != null) {
currentContext = ImeNativeWrapper.ImmCreateContext();
previousContext = ImeNativeWrapper.AssociateContext(hwndSource, currentContext);
//currentContext = ImeNativeWrapper.ImmCreateContext();
//previousContext = ImeNativeWrapper.AssociateContext(hwndSource, currentContext);
currentContext = ImeNativeWrapper.GetContext(hwndSource);
// ImeNativeWrapper.SetCompositionFont(hwndSource, currentContext, textArea);
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(null);
}
}
}

Loading…
Cancel
Save