WinFormsのTextBox Controlの話題です。とても基本的なControlですが落とし穴がありました。IMEで漢字変換中にフォーカスを失うと未確定文字はそのままIMEが持って行ってしまいます。 WinFormsがこのような挙動をすることを知らず何も制御していなかったために、自作のアプリケーションがクソ呼ばわりされる事態に陥ってしまいました。 とても悲しかったのでTextBoxを派生して挙動を改良してみました。 IMEが開いているかどうかはImeContext.IsOpen()で調べることができますが、そのあと同じハンドルを使用して処理することになるため、IsOpenは使いませんでした。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Runtime.InteropServices; | |
using System.Windows.Forms; | |
namespace Sayuri.Windows.Forms { | |
class TextBox2 : TextBox { | |
[DllImport("Imm32.dll")] | |
static extern IntPtr ImmGetContext(IntPtr hWnd); | |
[DllImport("Imm32.dll")] | |
static extern bool ImmGetOpenStatus(IntPtr hIMC); | |
[DllImport("Imm32.dll")] | |
static extern bool ImmNotifyIME(IntPtr hIMC, int dwAction, int dwIndex, int dwValue); | |
[DllImport("Imm32.dll")] | |
static extern bool ImmReleaseContext(IntPtr hWnd, IntPtr hIMC); | |
const int NI_SELECTCANDIDATESTR = 0x0015; | |
const int CPS_COMPLETE = 0x0001; | |
protected override void OnLostFocus(EventArgs e) { | |
var context = ImmGetContext(Handle); | |
if (context != IntPtr.Zero) { | |
if (ImmGetOpenStatus(context)) | |
ImmNotifyIME(context, NI_SELECTCANDIDATESTR, CPS_COMPLETE, 0); | |
ImmReleaseContext(Handle, context); | |
} | |
base.OnLostFocus(e); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Sayuri.Windows.Forms | |
open System.Runtime.InteropServices | |
open System.Windows.Forms | |
type TextBox2 () = | |
inherit TextBox () | |
[<DllImport "Imm32.dll">] | |
static extern nativeint ImmGetContext(nativeint hWnd) | |
[<DllImport "Imm32.dll">] | |
static extern bool ImmGetOpenStatus(nativeint hIMC) | |
[<DllImport "Imm32.dll">] | |
static extern bool ImmNotifyIME(nativeint hIMC, uint32 dwAction, uint32 dwIndex, uint32 dwValue) | |
[<DllImport "Imm32.dll">] | |
static extern bool ImmReleaseContext(nativeint hWnd, nativeint hIMC) | |
[<Literal>] | |
static let NI_SELECTCANDIDATESTR = 0x0015u | |
[<Literal>] | |
static let CPS_COMPLETE = 0x0001u | |
override this.OnLostFocus e = | |
let context = ImmGetContext this.Handle | |
if context <> 0n then | |
if ImmGetOpenStatus context then | |
ImmNotifyIME(context, NI_SELECTCANDIDATESTR, CPS_COMPLETE, 0u) |> ignore | |
ImmReleaseContext(this.Handle, context) |> ignore | |
base.OnLostFocus e |
0 件のコメント:
コメントを投稿