IME入力時に読みを別コントロールに設定できる仕様を追加して欲しいとの事。
結局、流れた案件だけど、ある程度の調査結果でも書いておきます。
(たまには技術屋らしい書き込みもしないとねσ(^_^汗
調べると、IME用のAPIを使うとの事。
で、WndProcをOverridesして操作が常道らしい。
まず、ModuleにAPI等を定義
------------------------------------------------------------
Imports System.Runtime.InteropServices
Public Module TestFuncs
#Region "API定数"
''' <summary>WindowMessage:WM_CHAR</summary>
Public Const WM_CHAR As Integer = &H102
''' <summary>WindowMessage:WM_IME_COMPOSITION</summary>
Public Const WM_IME_COMPOSITION As Integer = &H10F
''' <summary>ImmGetCompositionString用定数:GCS_RESULTREADSTR</summary>
Public Const GCS_RESULTREADSTR As Integer = &H200
#End Region
#Region "API定義"
''' <summary>IMEハンドル取得</summary>
<DllImport("Imm32.dll")> _
Public Function ImmGetContext(ByVal hWnd As Integer) As Integer
End Function
''' <summary>IMEハンドル解放</summary>
<DllImport("Imm32.dll")> _
Public Function ImmReleaseContext(ByVal hWnd As Integer, ByVal hIMC As Integer) As Integer
End Function
''' <summary>フリガナ取得</summary>
<DllImport("Imm32.dll")> _
Public Function ImmGetCompositionString(ByVal hIMC As Integer, ByVal dwIndex As Integer, ByVal lpBuf As StringBuilder, ByVal dwBufLen As Integer) As Integer
End Function
''' <summary>IME状態取得</summary>
<DllImport("Imm32.dll")> _
Public Function ImmGetOpenStatus(ByVal hIMC As Integer) As Integer
End Function
#End Region
End Moudle
------------------------------------------------------------
あとはテキストボックス継承のコントロールを作成
------------------------------------------------------------
Imports System.ComponentModel
Public Class TestTextBox
Inherits System.Windows.Forms.TextBox
''' <summary>読み設定先</summary>
Private _YomiControl As Control = Nothing
''' <summary>読み設定先コントロール</summary>
<Category("カスタム")> _
<Description("読み設定先コントロール")>
Public Property YomiControl() As Control
Get
Return _YomiControl
End Get
Set(ByVal value As Control)
_YomiControl = value
End Set
End Property
#Region "WndProcフック"
''' <summary>ウィンドウプロシージャ</summary>
Protected Overloads Overrides Sub WndProc(ByRef wm As System.Windows.Forms.Message)
Try
If Not _YomiControl Is Nothing Then
Select Case wm.Msg
Case WM_IME_COMPOSITION
'IME確定
Dim InpStr As String = ""
If (CUInt(wm.LParam) And CUInt(GCS_RESULTREADSTR)) <> 0 Then
Dim hIM As Integer = ImmGetContext(Me.Handle.ToInt32())
Dim strLen = ImmGetCompositionString(hIM, GCS_RESULTREADSTR, Nothing, 0)
If strLen > 0 Then
Dim temp As New System.Text.StringBuilder(strLen)
ImmGetCompositionString(hIM, GCS_RESULTREADSTR, temp, strLen)
InpStr = temp.ToString()
If InpStr.Length > strLen Then
InpStr = InpStr.Substring(0, strLen)
End If
Try
If Not _YomiControl Is Nothing Then
_YomiControl.Text = _YomiControl.Text & StrConv(InpStr, VbStrConv.Wide)
End If
Catch ex As Exception
End Try
End If
ImmReleaseContext(Me.Handle.ToInt32(), hIM)
End If
Exit Select
Case WM_CHAR
'直接入力
Dim hIM As Integer = ImmGetContext(Me.Handle.ToInt32())
If ImmGetOpenStatus(hIM) = 0 Then
Dim InpChr As Char = Convert.ToChar(wm.WParam.ToInt32() And &HFF)
If wm.WParam.ToInt32() >= 32 Then
Dim InpStr As String = InpChr.ToString()
Try
If Not _YomiControl Is Nothing Then
_YomiControl.Text = _YomiControl.Text & InpStr
End If
Catch ex As Exception
End Try
End If
End If
ImmReleaseContext(Me.Handle.ToInt32(), hIM)
Exit Select
End Select
End If
Catch ex As Exception
End Try
MyBase.WndProc(wm)
End Sub
#End Region
End Class
------------------------------------------------------------
とりあえずカナを取得して、指定の別コントロールに設定するソース。
2時間程度で調べて作ったものなのでバグ等があるやもしれませんがw
0 件のコメント:
コメントを投稿