none
テキストボックスなどで予測入力を表示させない方法は? RRS feed

  • 質問

  • Windowsフォームを使ってアプリケーションを作成しているのですが、
    テキストボックスとIMEについて質問があります。

    テキストボックスに文字を入力する際に表示される予測変換を
    プログラム側で表示させなくする方法はあるでしょうか?

    IMEの詳細設定の「予測入力」タブにある「予測入力を使用する」の
    チェックを外した状態をプログラムで実現したいのです。
    (レジストリでこの設定の値を変更する等の方法は避けたいです)

    よろしくお願い致します。


    VB.NET
    .NET Framework 4
    VisualStudio2010




    • 編集済み kinotake 2018年5月19日 13:59
    2018年5月19日 12:58

回答

  • IMEの種類やバージョンやOSについて何も書いてないので、Win10+MSIME

    '要TSF.TypeLib
    '.Net4.5以降ならNugetでhttps://www.nuget.org/packages/TSF.TypeLibを追加しておく
    '.Net4ならhttps://github.com/NyaRuRu/TSF-TypeLibからソースを入手してdllをビルドすること
    Imports TSF.InteropTypes
    Imports TSF.TypeLib
    
    Public Class Form1
    	Private elementSink As New UIElementSink
    
    	Sub New()
    		'InitializeComponent()
    
    		Application.AddMessageFilter(elementSink)
    
    		Dim chk As New CheckBox
    		chk.Text = "予測候補表示"
    		chk.Checked = elementSink.EnableSuggestion
    		chk.Left = 5
    
    		AddHandler chk.CheckedChanged,
    			 Sub(s, e)
    				 elementSink.EnableSuggestion = chk.Checked
    			 End Sub
    
    		Dim txb As New TextBox
    		txb.Top = 30
    		txb.Left = 5
    		txb.Width = Me.ClientRectangle.Width - 10
    		txb.Anchor = AnchorStyles.Top Or AnchorStyles.Left Or AnchorStyles.Right
    
    		Me.Controls.Add(chk)
    		Me.Controls.Add(txb)
    
    	End Sub
    
    	Protected Overrides Sub OnShown(e As EventArgs)
    		MyBase.OnShown(e)
    		If (elementSink.Start()) Then
    			Me.Text = "開始しました"
    		End If
    	End Sub
    
    	Protected Overrides Sub OnClosed(e As EventArgs)
    		Me.elementSink.Dispose()
    
    		MyBase.OnClosed(e)
    	End Sub
    End Class
    
    Class UIElementSink
    	Implements TSF.TypeLib.ITfUIElementSink
    	Implements IMessageFilter
    	Implements IDisposable
    
    	Private thmgr As TSF.TypeLib.ITfThreadMgr
    	Private uimgr As TSF.TypeLib.ITfUIElementMgr
    	Private source As TSF.TypeLib.ITfSource
    
    	Private cookie As UInteger
    	Private context As System.Threading.SynchronizationContext
    
    	Private Const WM_KEYDOWN = &H100
    	Private lastKey As Keys
    	Private islastKeyIsChar As Boolean
    
    	Public Property EnableSuggestion As Boolean = True
    
    	Public Function PreFilterMessage(ByRef m As Message) As Boolean Implements IMessageFilter.PreFilterMessage
    		If (TypeOf Control.FromHandle(m.HWnd) Is TextBox) Then
    			Select Case m.Msg
    				Case WM_KEYDOWN
    					lastKey = CType(m.WParam.ToInt64(), Keys)
    					If m.WParam.ToInt64() = Keys.ProcessKey Then
    						lastKey = CType(ImmGetVirtualKey(m.HWnd), Keys)
    					End If
    
    					Debug.WriteLine(lastKey)
    					islastKeyIsChar = True
    					Select Case lastKey
    						Case Keys.Space
    						Case Keys.D0 To Keys.D9
    						Case Keys.A To Keys.Z
    						Case Keys.NumPad0 To Keys.NumPad9
    						Case Keys.Multiply To Keys.Oem102
    
    						Case Else
    							islastKeyIsChar = False
    					End Select
    			End Select
    		End If
    		Return False
    	End Function
    
    
    
    	Public Function Start() As Boolean
    		context = System.Threading.SynchronizationContext.Current
    		If (context Is Nothing) Then
    			context = System.Threading.SynchronizationContext.Current
    		End If
    
    		thmgr = GetThreadManager()
    		uimgr = TryCast(thmgr, TSF.TypeLib.ITfUIElementMgr)
    		source = TryCast(thmgr, TSF.TypeLib.ITfSource)
    		If (source IsNot Nothing) Then
    			Dim iid = GetGUID(GetType(TSF.TypeLib.ITfUIElementSink))
    			If (source.AdviseSink(iid, Me, cookie).Succeeded) Then
    				Return True
    			End If
    		End If
    
    		System.Runtime.InteropServices.Marshal.ReleaseComObject(source)
    		System.Runtime.InteropServices.Marshal.ReleaseComObject(uimgr)
    		System.Runtime.InteropServices.Marshal.ReleaseComObject(thmgr)
    		Return False
    	End Function
    
    	Private Function BeginUIElement(dwUIElementId As UInteger, ByRef pbShow As Boolean) As HRESULT Implements ITfUIElementSink.BeginUIElement
    		Debug.WriteLine("BeginUIElement")
    		pbShow = True
    
    		If (Not EnableSuggestion) Then
    
    			Dim elem As TSF.TypeLib.ITfUIElement = Nothing
    			If (uimgr.GetUIElement(dwUIElementId, elem).Succeeded) Then
    				Try
    					Dim candidataElement = TryCast(elem, TSF.TypeLib.ITfCandidateListUIElement)
    					If (candidataElement IsNot Nothing) Then
    						pbShow = Not islastKeyIsChar
    					End If
    				Finally
    					System.Runtime.InteropServices.Marshal.ReleaseComObject(elem)
    				End Try
    			End If
    		End If
    		Return New HRESULT() With {.Code = 0}
    	End Function
    
    	Private Function EndUIElement(dwUIElementId As UInteger) As HRESULT Implements ITfUIElementSink.EndUIElement
    		Debug.WriteLine("EndUIElement")
    	End Function
    
    	Private Function UpdateUIElement(dwUIElementId As UInteger) As HRESULT Implements ITfUIElementSink.UpdateUIElement
    		Debug.WriteLine("UpdateUIElement")
    	End Function
    
    #Region "IDisposable Support"
    	Private disposedValue As Boolean
    
    	Protected Overridable Sub Dispose(disposing As Boolean)
    		If Not disposedValue Then
    			If (cookie <> 0 AndAlso source IsNot Nothing) Then
    				source.UnadviseSink(cookie)
    			End If
    
    			System.Runtime.InteropServices.Marshal.ReleaseComObject(source)
    			System.Runtime.InteropServices.Marshal.ReleaseComObject(uimgr)
    			System.Runtime.InteropServices.Marshal.ReleaseComObject(thmgr)
    
    			source = Nothing
    			uimgr = Nothing
    			thmgr = Nothing
    
    		End If
    		disposedValue = True
    	End Sub
    
    	Public Sub Dispose() Implements IDisposable.Dispose
    		Dispose(True)
    		GC.SuppressFinalize(Me)
    	End Sub
    #End Region
    
    	<System.Runtime.InteropServices.DllImport("Msctf.dll")>
    	Private Shared Function TF_GetThreadMgr(ByRef x As TSF.TypeLib.ITfThreadMgr) As TSF.InteropTypes.HRESULT
    	End Function
    
    	Private Shared Function GetThreadManager() As TSF.TypeLib.ITfThreadMgr
    		Dim mgr As TSF.TypeLib.ITfThreadMgr = Nothing
    		If (Not TF_GetThreadMgr(mgr).Succeeded) Then
    			Dim o As Object = Type.GetTypeFromCLSID(GetGUID(GetType(TSF.TypeLib.ITfThreadMgr)))
    			mgr = TryCast(o, TSF.TypeLib.ITfThreadMgr)
    		End If
    		Return mgr
    	End Function
    
    	Private Shared Function GetGUID(ByVal t As Type) As Guid
    		Return New Guid(t.GetCustomAttributes(True).OfType(Of System.Runtime.InteropServices.GuidAttribute).First().Value)
    	End Function
    
    	<System.Runtime.InteropServices.DllImport("Imm32.dll")>
    	Private Shared Function ImmGetVirtualKey(ByVal hwnd As IntPtr) As UInteger
    	End Function
    End Class

    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク kinotake 2018年5月24日 1:55
    • 回答としてマークされていない kinotake 2018年5月24日 1:55
    • 回答としてマーク kinotake 2018年5月24日 1:57
    2018年5月20日 15:01

すべての返信

  • IMEの種類やバージョンやOSについて何も書いてないので、Win10+MSIME

    '要TSF.TypeLib
    '.Net4.5以降ならNugetでhttps://www.nuget.org/packages/TSF.TypeLibを追加しておく
    '.Net4ならhttps://github.com/NyaRuRu/TSF-TypeLibからソースを入手してdllをビルドすること
    Imports TSF.InteropTypes
    Imports TSF.TypeLib
    
    Public Class Form1
    	Private elementSink As New UIElementSink
    
    	Sub New()
    		'InitializeComponent()
    
    		Application.AddMessageFilter(elementSink)
    
    		Dim chk As New CheckBox
    		chk.Text = "予測候補表示"
    		chk.Checked = elementSink.EnableSuggestion
    		chk.Left = 5
    
    		AddHandler chk.CheckedChanged,
    			 Sub(s, e)
    				 elementSink.EnableSuggestion = chk.Checked
    			 End Sub
    
    		Dim txb As New TextBox
    		txb.Top = 30
    		txb.Left = 5
    		txb.Width = Me.ClientRectangle.Width - 10
    		txb.Anchor = AnchorStyles.Top Or AnchorStyles.Left Or AnchorStyles.Right
    
    		Me.Controls.Add(chk)
    		Me.Controls.Add(txb)
    
    	End Sub
    
    	Protected Overrides Sub OnShown(e As EventArgs)
    		MyBase.OnShown(e)
    		If (elementSink.Start()) Then
    			Me.Text = "開始しました"
    		End If
    	End Sub
    
    	Protected Overrides Sub OnClosed(e As EventArgs)
    		Me.elementSink.Dispose()
    
    		MyBase.OnClosed(e)
    	End Sub
    End Class
    
    Class UIElementSink
    	Implements TSF.TypeLib.ITfUIElementSink
    	Implements IMessageFilter
    	Implements IDisposable
    
    	Private thmgr As TSF.TypeLib.ITfThreadMgr
    	Private uimgr As TSF.TypeLib.ITfUIElementMgr
    	Private source As TSF.TypeLib.ITfSource
    
    	Private cookie As UInteger
    	Private context As System.Threading.SynchronizationContext
    
    	Private Const WM_KEYDOWN = &H100
    	Private lastKey As Keys
    	Private islastKeyIsChar As Boolean
    
    	Public Property EnableSuggestion As Boolean = True
    
    	Public Function PreFilterMessage(ByRef m As Message) As Boolean Implements IMessageFilter.PreFilterMessage
    		If (TypeOf Control.FromHandle(m.HWnd) Is TextBox) Then
    			Select Case m.Msg
    				Case WM_KEYDOWN
    					lastKey = CType(m.WParam.ToInt64(), Keys)
    					If m.WParam.ToInt64() = Keys.ProcessKey Then
    						lastKey = CType(ImmGetVirtualKey(m.HWnd), Keys)
    					End If
    
    					Debug.WriteLine(lastKey)
    					islastKeyIsChar = True
    					Select Case lastKey
    						Case Keys.Space
    						Case Keys.D0 To Keys.D9
    						Case Keys.A To Keys.Z
    						Case Keys.NumPad0 To Keys.NumPad9
    						Case Keys.Multiply To Keys.Oem102
    
    						Case Else
    							islastKeyIsChar = False
    					End Select
    			End Select
    		End If
    		Return False
    	End Function
    
    
    
    	Public Function Start() As Boolean
    		context = System.Threading.SynchronizationContext.Current
    		If (context Is Nothing) Then
    			context = System.Threading.SynchronizationContext.Current
    		End If
    
    		thmgr = GetThreadManager()
    		uimgr = TryCast(thmgr, TSF.TypeLib.ITfUIElementMgr)
    		source = TryCast(thmgr, TSF.TypeLib.ITfSource)
    		If (source IsNot Nothing) Then
    			Dim iid = GetGUID(GetType(TSF.TypeLib.ITfUIElementSink))
    			If (source.AdviseSink(iid, Me, cookie).Succeeded) Then
    				Return True
    			End If
    		End If
    
    		System.Runtime.InteropServices.Marshal.ReleaseComObject(source)
    		System.Runtime.InteropServices.Marshal.ReleaseComObject(uimgr)
    		System.Runtime.InteropServices.Marshal.ReleaseComObject(thmgr)
    		Return False
    	End Function
    
    	Private Function BeginUIElement(dwUIElementId As UInteger, ByRef pbShow As Boolean) As HRESULT Implements ITfUIElementSink.BeginUIElement
    		Debug.WriteLine("BeginUIElement")
    		pbShow = True
    
    		If (Not EnableSuggestion) Then
    
    			Dim elem As TSF.TypeLib.ITfUIElement = Nothing
    			If (uimgr.GetUIElement(dwUIElementId, elem).Succeeded) Then
    				Try
    					Dim candidataElement = TryCast(elem, TSF.TypeLib.ITfCandidateListUIElement)
    					If (candidataElement IsNot Nothing) Then
    						pbShow = Not islastKeyIsChar
    					End If
    				Finally
    					System.Runtime.InteropServices.Marshal.ReleaseComObject(elem)
    				End Try
    			End If
    		End If
    		Return New HRESULT() With {.Code = 0}
    	End Function
    
    	Private Function EndUIElement(dwUIElementId As UInteger) As HRESULT Implements ITfUIElementSink.EndUIElement
    		Debug.WriteLine("EndUIElement")
    	End Function
    
    	Private Function UpdateUIElement(dwUIElementId As UInteger) As HRESULT Implements ITfUIElementSink.UpdateUIElement
    		Debug.WriteLine("UpdateUIElement")
    	End Function
    
    #Region "IDisposable Support"
    	Private disposedValue As Boolean
    
    	Protected Overridable Sub Dispose(disposing As Boolean)
    		If Not disposedValue Then
    			If (cookie <> 0 AndAlso source IsNot Nothing) Then
    				source.UnadviseSink(cookie)
    			End If
    
    			System.Runtime.InteropServices.Marshal.ReleaseComObject(source)
    			System.Runtime.InteropServices.Marshal.ReleaseComObject(uimgr)
    			System.Runtime.InteropServices.Marshal.ReleaseComObject(thmgr)
    
    			source = Nothing
    			uimgr = Nothing
    			thmgr = Nothing
    
    		End If
    		disposedValue = True
    	End Sub
    
    	Public Sub Dispose() Implements IDisposable.Dispose
    		Dispose(True)
    		GC.SuppressFinalize(Me)
    	End Sub
    #End Region
    
    	<System.Runtime.InteropServices.DllImport("Msctf.dll")>
    	Private Shared Function TF_GetThreadMgr(ByRef x As TSF.TypeLib.ITfThreadMgr) As TSF.InteropTypes.HRESULT
    	End Function
    
    	Private Shared Function GetThreadManager() As TSF.TypeLib.ITfThreadMgr
    		Dim mgr As TSF.TypeLib.ITfThreadMgr = Nothing
    		If (Not TF_GetThreadMgr(mgr).Succeeded) Then
    			Dim o As Object = Type.GetTypeFromCLSID(GetGUID(GetType(TSF.TypeLib.ITfThreadMgr)))
    			mgr = TryCast(o, TSF.TypeLib.ITfThreadMgr)
    		End If
    		Return mgr
    	End Function
    
    	Private Shared Function GetGUID(ByVal t As Type) As Guid
    		Return New Guid(t.GetCustomAttributes(True).OfType(Of System.Runtime.InteropServices.GuidAttribute).First().Value)
    	End Function
    
    	<System.Runtime.InteropServices.DllImport("Imm32.dll")>
    	Private Shared Function ImmGetVirtualKey(ByVal hwnd As IntPtr) As UInteger
    	End Function
    End Class

    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク kinotake 2018年5月24日 1:55
    • 回答としてマークされていない kinotake 2018年5月24日 1:55
    • 回答としてマーク kinotake 2018年5月24日 1:57
    2018年5月20日 15:01
  • gekkaさん、ご返答ありがとうございます。

    教えて頂いたコードで、望み通りの結果が得られました!
    ありがとうございました。

    2018年5月24日 1:57