🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Windows Forms

Windows Forms(WinForms)はMicrosoft .NET フレームワークに含まれる視覚的なアプリケーションのプログラミングインターフェイス(API)です。WinFormsは管理されているコードの既存のWindowsのAPIをラップすることで元のMicrosoft Windowsのインターフェイスのエレメントにアクセスすることができます。

オートコンプリート

オートコンプリートはアプリケーションから与えられるUIの機能で、ユーザが望む言葉や節をプログラムが自動的に予測し、実際に全て打たなくても入力できるように補完してくれるものです。

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

Q&A

解決済

1回答

6613閲覧

VB.NET ComboBoxのオートコンプリートが動作しない場合がある

kkktt

総合スコア9

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Windows Forms

Windows Forms(WinForms)はMicrosoft .NET フレームワークに含まれる視覚的なアプリケーションのプログラミングインターフェイス(API)です。WinFormsは管理されているコードの既存のWindowsのAPIをラップすることで元のMicrosoft Windowsのインターフェイスのエレメントにアクセスすることができます。

オートコンプリート

オートコンプリートはアプリケーションから与えられるUIの機能で、ユーザが望む言葉や節をプログラムが自動的に予測し、実際に全て打たなくても入力できるように補完してくれるものです。

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

0グッド

1クリップ

投稿2021/03/14 05:00

前提・実現したいこと

VB.NETで、
ComboBoxにオートコンプリートを適用したいと思い試作してみたのですが、
オートコンプリートが動作しない場合があります。
(具体的な発生条件については、「発生している問題・エラーメッセージ」にて記載しています。)

自分で調べてみましたがわからなかったため、
原因・解決策等教えていただきたいです。

ComboBoxは以下のように設定しています。
・Items:ひらがなの「あ~ん」までを、昇順で1字ずつ設定。(濁音・半濁音・促音・拗音等は含まず、項目数46)
・AutoCompleteSource:ListItems
・AutoCompleteMode:Suggest
・DropDownStyle:DropDownList

発生している問題・エラーメッセージ

上記設定でデバッグ実行し、ComboBoxにフォーカスがあたっている&アイテム未選択の状態で文字を入力すると、

○ 「あ」~「む」:オートコンプリートが機能し、入力した文字と同一のアイテムが選択される
× 「め」~「ん」:オートコンプリートが機能せず、リストが開く(ComboBox右の矢印をクリックした時と同じ動作をする)

となります。

「め」~「ん」入力時にも、「あ」~「む」入力時と同様、オートコンプリートが機能するようにしたいです。

試したこと

・AutoCompleteMode:SuggestAppendにしてみる
・Sorted:False→Trueにしてみる
・MaxDropDownItems:デフォルトの値(8)→大きな値(100とか)にしてみる
・Formを縦に大きくしてみる

 → 全て効果なし

補足情報(FW/ツールのバージョンなど)

Visual Studio 2019 Version 16.9.1
.NET Framework 4.7.2
Windows 10 Home

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

たしかに不具合ある感じの奇妙な動きですね。

調べてみたら根源はAuto~となる以前からの問題に起因しているようで、
こちらが事の始まり(にして終わり)でしょうか。

Microsoft KB Archive/814362
https://www.betaarchive.com/wiki/index.php?title=Microsoft_KB_Archive/814362

文中、'This behavior is by design.'「これは仕様です」とありますので、
2バイト文字利用下でしたらこれら機能はオマケ程度に考えといてね、という結論。

対策を考えてみますと。

1.KeyDown で情報が取れて
2.続いて必ず KeyDown イベントが来て
3.うまく動くときは SelectedIndexChanged イベントが来る
4.最後に KeyUp イベントが来る

という流れですので、
KeyUp イベントのとき、SelectedIndexChanged が来てなかったら、カバー処理を入れてやればよい。

なんですが。
KeyDown イベントには、IMEで変換された文字は取れないようでAPIに頼らないと無理なようです。

ComboBox を継承したクラス( Combobox4KB814362 )でも問題解消を試みてみました。
(とりあえず動いてますが、VB慣れないのでコーディングの細かいところ適当です。m(_ _)m
ご利用の際は適宜手直ししてください)

VB

1Imports System.Runtime.InteropServices 2Imports System.Windows.Forms 3Imports System.Text 4 5Public Class Combobox4KB814362 6 Inherits ComboBox 7 8 Const GCS_RESULTSTR As Integer = &H800 '最終変換結果文字列を取得 9 Const WM_IME_COMPOSITION As Integer = &H10F '文字列が確定されたとき他 10 11 Declare Auto Function ImmGetContext Lib "imm32.dll" (ByVal hWnd As IntPtr) As IntPtr 12 Declare Auto Function ImmReleaseContext Lib "imm32.dll" (ByVal hWnd As IntPtr, ByVal hIMC As IntPtr) As Integer 13 Declare Auto Function ImmGetCompositionString Lib "imm32.dll" (ByVal hIMC As IntPtr, 14 ByVal dwIndex As Integer, ByVal lpBuf As StringBuilder, ByVal dwBufLen As Integer) As Integer 15 16 Private Shared Function GetCompositionString(hIMC As IntPtr) As String 17 Dim bufferSB As New StringBuilder(0) 18 Dim length As Integer = ImmGetCompositionString(hIMC, GCS_RESULTSTR, bufferSB, 0) 19 bufferSB.Length = CInt(length / Len(New Char)) 20 length = ImmGetCompositionString(hIMC, GCS_RESULTSTR, bufferSB, length) 21 Return bufferSB.ToString(0, CInt(length / Len(New Char))) 22 End Function 23 24 Enum CTRL_STATE As Integer 25 IDLING 26 DROPDOWN_CATCH 27 SELECTEDINDEXCHANGED_CATCH 28 End Enum 29 30 Private Property mySTATE As CTRL_STATE = CTRL_STATE.IDLING 31 Private Property myBackupIMMString As String = "" 32 33 Protected Overrides Sub WndProc(ByRef m As Message) 34 If m.Msg = WM_IME_COMPOSITION AndAlso (CInt(m.LParam) And GCS_RESULTSTR) = GCS_RESULTSTR Then 35 Dim hIMC As IntPtr = ImmGetContext(Me.Handle) 36 myBackupIMMString = GetCompositionString(hIMC) 37 ImmReleaseContext(Me.Handle, hIMC) 38 End If 39 MyBase.WndProc(m) 40 End Sub 41 Protected Sub ComboBox2_DropDown(sender As Object, e As EventArgs) Handles Me.DropDown 42 mySTATE = CTRL_STATE.DROPDOWN_CATCH 43 End Sub 44 Protected Sub ComboBox2_SelectedIndexChanged(sender As Object, e As EventArgs) Handles Me.SelectedIndexChanged 45 mySTATE = CTRL_STATE.SELECTEDINDEXCHANGED_CATCH 46 End Sub 47 Protected Sub ComboBox2_KeyUp(sender As Object, e As KeyEventArgs) Handles Me.KeyUp 48 If mySTATE <> CTRL_STATE.SELECTEDINDEXCHANGED_CATCH Then 49 Me.SelectedIndex = FindString(myBackupIMMString, Me.SelectedIndex) 50 End If 51 mySTATE = CTRL_STATE.IDLING 52 End Sub 53End Class 54

※参考
IMEで入力された日本語の読みを取得するには?[C#、VB]
https://www.atmarkit.co.jp/fdotnet/dotnettips/875imeyomi/imeyomi.html

ImmGetCompositionStringでUnicodeの文字を取得できない
https://social.msdn.microsoft.com/Forums/ja-JP/f2169cf7-5e34-45b4-ba37-c33ad9a5571e/immgetcompositionstring12391unicode123982599123383124342146224471123911236?forum=csharpgeneralja

ImmGetCompositionString 変換中の文字列の情報を取得
http://nienie.com/~masapico/api_ImmGetCompositionString.html

投稿2021/03/15 10:39

FromMZ1500

総合スコア496

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kkktt

2021/03/15 15:18 編集

詳細な回答ありがとうございます。 提示いただいたソースのうち、KeyUpイベント部分を一部変更することでうまくいきました。  (1)KeyUp→KeyPressに変更(KeyUpだとCtrl、Alt等の修飾キーも取ってきてしまうため)  (2)FindString()関数で一致する項目が見つかるかどうか事前にチェック実施  (アイテム選択済(SelectedIndex<>-1)の状態でリストに該当しない文字(数字等)入力した際に未選択の状態(SelectedIndex=-1)に戻ってしまうので、標準のComboBoxと同様、SelectedIndexは変えずにリストが出る形となるようにしました) Protected Sub ComboBox2_KeyPress(sender As Object, e As KeyPressEventArgs) Handles Me.KeyPress If mySTATE <> CTRL_STATE.SELECTEDINDEXCHANGED_CATCH Then If FindString(myBackupIMMString, Me.SelectedIndex) <> -1 Then '(2) Me.SelectedIndex = FindString(myBackupIMMString, Me.SelectedIndex) End If End If mySTATE = CTRL_STATE.IDLING End Sub
FromMZ1500

2021/03/15 22:34

なるほど。ナイス、カバー、ありがとうございます。 濁音・半濁音・促音抜きでちょろっとテストしただけでした。(汗)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問