none
AccessのテキストボックスのIME入力モードが反映されない。 RRS feed

  • 質問

  • お世話になります。
    Microsoftコミュニティで質問させて頂いた所、こちらでも質問を勧められたので投稿させて頂きます。

    AccessのテキストボックスのIME入力モードが反映されない現象が出て困っています。
    以下のようにファイルを作成すると再現できました。

    ①新規でデータベースを作成

    ②フォームを2つ作成。
    名称は「フォーム1」、「フォーム2」

    ③フォーム1にボタンを1つ、テキストボックス2つを設置。
    テキストボックスのIME入力モードを「オン」に変更。

    ④ボタンを押したらフォーム2が開くように
    ボタンのクリック時のイベントに以下のコードを記述
    DoCmd.OpenForm "フォーム2", , , , , acDialog

    ⑤フォーム2にボタンを1つ設置。
    ボタンを押したらフォーム2が閉じるように
    ボタンのクリック時のイベントに以下のコードを記述
    DoCmd.Close acForm, Me.Name

    ⑥フォーム1を実行
    テキストボックス1、テキストボックス2をクリックしてIMEがONになることを確認。

    ⑦フォーム1のボタンをクリックしてフォーム2を表示。

    ⑧フォーム2のボタンをクリックしてフォーム2を閉じる。

    ⑨テキストボックス1をクリックしてIMEがONになることを確認。
    次にテキストボックス2をクリックするとIMEがOFFになってしまう。
    一度OFFになると、テキストボックス1、テキストボックス2のどちらをクリックしてもOFFのままになってしまいます。

    どうやら、別のフォームをダイアログで表示して、戻ると現象が出るようです。


    現象が出るパソコン
    Windows 10 Pro 20H2
    (1909の時は現象がでませんでしたが、20H2でも出ないパソコンもあります)

    以下の方法を試してみましたが、すべて解決できませんでした。

    Access 2010、2013、2016、365で実行。
    Microsoft IME、GoogleIMEを切り替えて実行。
    Accessのオプションのクライアントの設定の中の「データシート上でIMEを制御する」はon、offを切り替えて実行。
    Microsoft IMEのオプションで「以前のバージョンのMicrosoft IMEを使う」にして実行。
    Microsoft IMEの再インストールを行って実行。

    ユーザーを新規に作ってログインすると、一見直ったように見えますが、
    ⑨の時点でテキストボックス1、2を何回も交互にクリックしてると、
    onになったり、offになったりと違う現象が出たりします。


    どなたか、解決策をお持ちの方がいらっしゃいましたら、ご教授お願いいたします。
    2021年4月19日 10:35

すべての返信

  • ライフ菊池さん、こんにちは。

    ご指摘の現象を確認しましたが、規則性とかはわかりませんでした。

    IMEツールバーを表示しておいて、変換機能がどうなっているかを見ながらテキストボックスに文字を入力してみましたら、IMEツールバーが"A"となっているときに変換されず、"あ"となっているときには変換されるということがわかりました。

    IMEツールバーの表示は、テキストボックスにカーソルがあるときは”あ"となっていても、ボタンをクリックするとき、また、フォーム2が表示されフォーム2上(ボタンを含む。)にカーソルがある場合は、”A" となっており、テキストボックス1からテキストボックス2にカーソルを移動する際も一瞬"A"になることがわかりました。

    また、フォーム1にもう一つボタンを設けて、テキストボックス1とテキストボックス2のそれぞれの「IMEMode」の値を表示させるようにしてみましたところ、変換がされるときも、されないときも、一応、「acImeModeOn(=1)」となっておりました。

    ということで、各テキストボックスのIMEモードの設定は生きているのですが、IMEツールバーに表示されている変換モードが優先されて、変換できないのだということが推測されました。

    何しろ、気ままに変換onから変換offに、また、変換offから変換onに変りますので、どうしようもない感じがします。しかし、変換offだったら「半角/全角」キーをたたいて変換onに戻す、という手動での対処ができますので、勝手に変わらないのが一番で、そもそもそう作られているはずではないのかい?と文句を言いたい気持ちは共有するものの、「vbaであらかじめ仕組まれている変換機能を、必要に応じて手動で簡単に変更できるのだから、気にはなるけれど深刻な問題ではないのではないか?」位に考えて対処するということではないかと愚考する次第。

    2021年4月21日 7:07
  • ライフ菊池さん、今晩は。

    前の返信で記した現象(変換ができなくなったときに、各テキストボックスのIMEModeはONになっているけれど、アクセスのIMEがoffになっているので、変換できない。)を踏まえて、何とかならないかと思案し、テキストボックス1及びテキストボックス2がそれぞれ選択されて入力できるようになったときに、アクセスのIME変換をonにするコードを走らせたらうまくいくのではないか?と考えて、WindowsAPIを使ってコードを作って、走らせてみました。

    残念ながら、ちょっとマシ、になった程度で、完璧に変換できない現象を抑えることはできませんでした。

    なお、その試行錯誤の結果、次の様な現象が分かりました。

    1.フォーム2を表示するまでは、テキストボックス1とテキストボックス2を交互に選択しても、IMEは変換モードのままで、選択の切り替え時に変換モードが無変換に変わることが無い。

    2.フォーム2を表示した後は、テキストボックス1とテキストボックス2を交互に選択すると、選択の切り替え時に、IMEは一瞬無変換に変わる。ON→OFF→ONと、テキストボックス1からテキストボックス2へ選択を変えるときにIMEモードが変わる。

    3.そして、たまにON→OFFからONに戻らないままになって、無変換状態となる。

    やはり、ライフ菊池さんのご指摘の通り、フォーム2を表示することにより、この症状が生じるようになるようです。

    と、ここまで記して、ちょっと気になる点があり、WindowsAPIで作ったコードにDoEventsの1行を加えてみたところ、IMEモードのON→OFF→ONの変化が無くなりました。どうやらうまくいきそうなので、以下にコードを参考までに掲示しておきます。

    なお、小生はAPIに詳しいわけではありませんので、何か間違いがあるようでしたら、どなたか詳しい方からご指摘が得られればうれしく存じますので、よろしくお願いします。

    なお、MsgBoxの行は必須ではありませんので、念のため。また、当方、Windows10_64bit+Access2016_32bitなので「ptrsafe」は付けておりません。

    ’フォーム1のテキストボックス1 Private Sub テキストボックス1_GotFocus() Call ImeMode_ON End Sub ’フォーム1のテキストボックス2 Private Sub テキストボックス2_GotFocus() Call ImeMode_ON End Sub ’標準モジュール

    Private Declare Function ImmGetContext Lib "imm32" (ByVal hwnd As Long) As Long
    Private Declare Function ImmSetOpenStatus Lib "imm32" (ByVal himc As Long, ByVal fOpen As Long) As Long
    Private Declare Function ImmGetConversionStatus Lib "imm32" (ByVal himc As Long, lpfdwConversion As Long, lpfdwSentence As Long) As Long
    Private Declare Function ImmSetConversionStatus Lib "imm32" (ByVal himc&, ByVal fdwConversion As Long, ByVal fdwSentence As Long) As Long
    Private Declare Function ImmReleaseContext Lib "imm32" (ByVal hwnd As Long, ByVal himc As Long) As Long

    Public Sub ImeMode_ON() Dim acHwnd As Long Dim lngInputContextHandle As Long Dim imeMode As Long Dim lngWin32apiResultCode As Long
    Dim lpfdwConversion
    Dim lpfdwSentence 'このアクセスのハンドルを取得 acHwnd = Application.hWndAccessApp If acHwnd <> 0 Then 'このアクセスに関連付けられている入力コンテキストのハンドルを取得 lngInputContextHandle = ImmGetContext(acHwnd) If lngInputContextHandle <> 0 Then lngWin32apiResultCode = ImmSetOpenStatus(lngInputContextHandle, True) '---IMEを開く If lngWin32apiResultCode <> 0 Then '現在の変換状態を取得する lngWin32apiResultCode = ImmGetConversionStatus(lngInputContextHandle, lpfdwConversion, lpfdwSentence) 'IMEモード imeMode = acImeModeOn '=1 'IMEを設定する lngWin32apiResultCode = ImmSetConversionStatus(lngInputContextHandle, lpfdwConversion, imeMode) DoEvents Else MsgBox "On切替出来ませんでした。" End If Else MsgBox "On切替出来ませんでした。" End If '入力コンテキストを開放 lngWin32apiResultCode = ImmReleaseContext(acHwnd, lngInputContextHandle) Else MsgBox "On切替出来ませんでした。" End If End Sub


    2021年4月22日 13:24
  • KokemomoYamamom様

    ご返信ありがとうございます。
    色々と試していただいたようで、ありがとうございます。
    お客様のパソコンで現象が出ていて、何とかして欲しいとの事で困っていました。

    殆どの人は気にならないのか、ネットで検索しても情報もなく、
    Accessからフィードバックは送ったのですが、返信があるわけでも無いので手詰まりになっていました。

    コードの作成までして頂いたので、早速試してみたいと思います。

    ありがとうございました。
    フィードバックの返信があれば、こちらに共有させて頂きます。

    以上、よろしくお願いいたします。
    2021年4月22日 23:35
  • ライフ菊池さん、こんにちは。

    若干修正して、Windows10_64bit+Access2019_64bitで動作確認したので、念のためコードを貼り付けておきます。

    フォーム1のテキストボックス1とテキストボックス2のGotFocus()については、変更が無いので、掲載しません。
    修正は、64bitなので「PtrSafe」を記入したこと、変数の定義で型指定していなかったのを指定したこと、前のコードでは、IMEが開いていても開いていなくても開くようにしていましたが、IMEが開いていない場合に開くようにしたこと、の3点の修正をいたしました。

    Private Declare PtrSafe Function ImmGetContext Lib "imm32" (ByVal hwnd As Long) As Long
    Private Declare PtrSafe Function ImmGetOpenStatus Lib "imm32" (ByVal himc As Long) As Long
    Private Declare PtrSafe Function ImmSetOpenStatus Lib "imm32" (ByVal himc As Long, ByVal fOpen As Long) As Long
    Private Declare PtrSafe Function ImmGetConversionStatus Lib "imm32" (ByVal himc As Long, lpfdwConversion As Long, lpfdwSentence As Long) As Long
    Private Declare PtrSafe Function ImmSetConversionStatus Lib "imm32" (ByVal himc&, ByVal fdwConversion As Long, ByVal fdwSentence As Long) As Long
    Private Declare PtrSafe Function ImmReleaseContext Lib "imm32" (ByVal hwnd As Long, ByVal himc As Long) As Long
    
    ' IME_ON切替メソッド---IMEをonにする
    Public Sub ImeMode_ON()
    Dim acHwnd                As Long
    Dim lngInputContextHandle As Long
    Dim imeMode               As Long
    Dim lngWin32apiResultCode As Long
    Dim lpfdwConversion       As Long
    Dim lpfdwSentence         As Long
      'このアクセスのハンドルを取得
      acHwnd = Application.hWndAccessApp
      If acHwnd <> 0 Then
        'このアクセスに関連付けられている入力コンテキストのハンドルを取得
        lngInputContextHandle = ImmGetContext(acHwnd)
        If lngInputContextHandle <> 0 Then
          lngWin32apiResultCode = ImmGetOpenStatus(lngInputContextHandle)    '---IMEが開いているか
          If lngWin32apiResultCode = 0 Then                                  '---IMEが開いていない場合
            lngWin32apiResultCode = ImmSetOpenStatus(lngInputContextHandle, True)  '---IMEを開く
          End If
          If lngWin32apiResultCode <> 0 Then
            '現在の変換状態を取得する
            lngWin32apiResultCode = ImmGetConversionStatus(lngInputContextHandle, lpfdwConversion, lpfdwSentence)
            'IMEモード
            imeMode = acImeModeOn   '=1
            'IMEを設定する
            lngWin32apiResultCode = ImmSetConversionStatus(lngInputContextHandle, lpfdwConversion, imeMode)
            DoEvents
          Else
            MsgBox "On切替出来ませんでした。"
          End If
        Else
          MsgBox "On切替出来ませんでした。"
        End If
        '入力コンテキストを開放
        lngWin32apiResultCode = ImmReleaseContext(acHwnd, lngInputContextHandle)
      Else
        MsgBox "On切替出来ませんでした。"
      End If
    End Sub
    

    2021年4月23日 4:42
  • ライフ菊池さん、今晩は。

    その後、チェックしてみたところ、昨日はテキストボックス1の入力からテキストボックス2の入力へ移る際に、IMEのON→OFF→ONの一瞬の切り替わりが見られなくなっていたのでしたが、今晩は切り替わりが見られるようになり、たまに切り替わりが生じ無くなったり、という状態です。切り替わりがみられる場合は、たまにIMEモードがOFFのままとなって変換ができなくなる、ということが発生します。

    ということで、昨晩はこれでうまくいくのではないか、と思えたのでしたが、どうやら、これも駄目なようです。解決策でないものをご提示して申し訳ありませんでした。

    2021年4月23日 13:20
  • KokemomoYamamom様

    おはようございます。
    色々と検証して頂きありがとうございます。
    私も色々とプロパティを変えて試したりしているのですが、進展がない状況です。

    何か進展がありましたら、こちらで報告させて頂きます。
    以上、よろしくお願いいたします。
    2021年4月23日 23:33
  • ライフ菊池さん、おはようございます。

    残念ながら、完璧な解決策ではないのですが、何もしないより良いのではないかと思われる案が見つかりましたので、お知らせします。ただし、実際のvbaはもっといろいろ処理が含まれているでしょうから、利用可能でないかもしれません。また、同じようなフォームの処理の数が多いと、コードの修正はちょっと煩雑であまりやりたくない力仕事になってしまうかもしれません。

    何もしないより良い、という理由は、次の通りです。
    1.何もしない場合、フォーム2を表示した後では、テキストボックスから他のテキストボックスに移動する際に、IMEが一瞬ON→OFF→ONと切り替わり、これが時としてうまく動作せずにOFFの状態で止まってしまって、変換機能が使えなくなるということが起きる。この案では、通常の場合は、フォーム2を表示した後でも、テキストボックスから他のテキストボックスに移動する際に、IMEはONのままで変わらないので、通常の場合は、変換機能が使えなくなることが無い。
    2.ただし、時として通常でない場合が発生する。この場合は、IMEが一瞬ON→OFF→ONと切り替わり、これが時としてうまく動作せず変換できなくなる症状は、何もしないときと同じ。ただし、テキストボックスをクリックするとONに復帰して変換が有効になる。又は、フォーム2を再度開いて閉じれば、通常の場合に復帰でき、変換が有効となる。
    3.何もしない場合は、IMEを有効に戻すためにはIMEを手動で操作しなければならず、IMEを有効にしても、引き続きテキストボックスから他のテキストボックスに移動すると、再びIMEがOFFになる可能性が有るが、この案であれば、フォーム2を再度開いて閉じた時に通常の場合に復帰すれば、その後テキストボックスから他のテキストボックスに移動してもIMEがOFFになることはない。
    4.通常でない場合で、IMEがOFFとなった場合でも、テキストボックスをもう一度クリックすれば、通常でない場合のままではあるが、IMEがONとなって、変換機能が有効となる。したがって、ユーザーが対処しやすい。

    次に、この案をご説明します。修正は、以下の通り、フォーム1とフォーム2のモジュールについて行います。

    ’フォーム1に次の2つのイベント処理コードを記入する。(前の返信でご提示したGotFocus()のコードはそのまま残す。)
    
    Private Sub テキストボックス1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
      Call ImeMode_ON
    End Sub
    
    Private Sub テキストボックス2_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
      Call ImeMode_ON
    End Sub
    
    ’フォーム2に次のイベント処理コードを記入する。
    
    Private Sub Form_Unload(Cancel As Integer)
      Call ImeMode_ON
    End Sub

    なお、標準モジュールのImeMode_On()も、ちょっと修正した方が良い点がないわけではないのですが、目下の問題点にはプラスにもマイナスにも影響しないので、いじらずに、そのまま残してください。

    以上、ご確認いただければと思います。

    2021年4月23日 23:57
  • ライフ菊池さん、こんにちは。

    その後、いろいろ試行錯誤したものの、やはり、IMEのバグ(だと思いますが…。)を完璧にカバーするコードは見つかりませんでした。ただ、かなり「無いよりはまし」ではないかと思われるレベルのコードのうち、一番IME変換ができなくなる確率が低いコードはこれではないかと思うものが出来ましたので、行数が多くなりますが、以下にご提示します。以前、ご提示したコードと重複するものもありますが、端折らずに、全部を掲示します。

    '▼フォーム1のコード
    
    Private Sub コマンド0_Click() 'コマンド0という名前のコマンドボタンをクリックしたときの処理
    'ライフ菊池さんご呈示のコード
      DoCmd.OpenForm "フォーム2", , , , , acDialog
    End Sub
    
    Private Sub Form_Activate()
      Call ImeMode_ON
    End Sub
    
    Private Sub テキストボックス1_GotFocus()
      Call ImeMode_ON
    End Sub
    
    Private Sub テキストボックス2_GotFocus()
      Call ImeMode_ON
    End Sub
    
    Private Sub テキストボックス1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
      Call ImeMode_ON
    End Sub
    
    Private Sub テキストボックス2_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
      Call ImeMode_ON
    End Sub
    
    '▼フォーム2のコード
    
    Private Sub コマンド0_Click() 'コマンド0という名前のコマンドボタンをクリックしたときの処理
    'ライフ菊池さんご呈示のコード
      DoCmd.Close acForm, Me.Name
    End Sub
    
    Private Sub Form_Activate()
      Call ImeMode_ON
    End Sub
    
    Private Sub Form_Unload(Cancel As Integer)
      Call ImeMode_ON
    End Sub
    
    '▼標準モジュールのコード
    
    Private Declare PtrSafe Function ImmGetContext Lib "imm32" (ByVal hwnd As Long) As Long
    Private Declare PtrSafe Function ImmGetOpenStatus Lib "imm32" (ByVal himc As Long) As Long
    Private Declare PtrSafe Function ImmSetOpenStatus Lib "imm32" (ByVal himc As Long, ByVal fOpen As Long) As Long
    Private Declare PtrSafe Function ImmGetConversionStatus Lib "imm32" (ByVal himc As Long, lpfdwConversion As Long, lpfdwSentence As Long) As Long
    Private Declare PtrSafe Function ImmSetConversionStatus Lib "imm32" (ByVal himc&, ByVal fdwConversion As Long, ByVal fdwSentence As Long) As Long
    Private Declare PtrSafe Function ImmReleaseContext Lib "imm32" (ByVal hwnd As Long, ByVal himc As Long) As Long
    
    ' IME_ON切替メソッド---IMEをonにする
    Public Sub ImeMode_ON()
    Dim acHwnd                As Long
    Dim lngInputContextHandle As Long
    Dim imeMode               As Long
    Dim lngWin32apiResultCode As Long
    Dim lpfdwConversion       As Long
    Dim lpfdwSentence         As Long
    Dim tryCount              As Integer
    
      'このアクセスのハンドルを取得
      acHwnd = Application.hWndAccessApp
      If acHwnd <> 0 Then
        'このアクセスに関連付けられている入力コンテキストのハンドルを取得
        lngInputContextHandle = ImmGetContext(acHwnd)
        If lngInputContextHandle <> 0 Then
          lngWin32apiResultCode = ImmGetOpenStatus(lngInputContextHandle)    '---IMEが開いているか
          If lngWin32apiResultCode = 0 Then                                  '---IMEが開いていない場合
            tryCount = 0
            Do While (lngWin32apiResultCode = 0 And tryCount < 10)
              lngWin32apiResultCode = ImmSetOpenStatus(lngInputContextHandle, True)  '---IMEを開く
              tryCount = tryCount + 1
            Loop
          End If
          If lngWin32apiResultCode <> 0 Then
            lngWin32apiResultCode = 0
            tryCount = 0
            Do While (lngWin32apiResultCode = 0 And tryCount < 10)
              '現在の変換状態を取得する
              lngWin32apiResultCode = ImmGetConversionStatus(lngInputContextHandle, lpfdwConversion, lpfdwSentence)
              tryCount = tryCount + 1
            Loop
            If lngWin32apiResultCode <> 0 Then
              'IMEモード
              imeMode = acImeModeOn   '=1
              lngWin32apiResultCode = 0
              tryCount = 0
              Do While (lngWin32apiResultCode = 0 And tryCount < 10)
                'IMEを設定する
                lngWin32apiResultCode = ImmSetConversionStatus(lngInputContextHandle, lpfdwConversion, imeMode)
                DoEvents
    DoEvents tryCount = tryCount + 1 Loop If lngWin32apiResultCode = 0 Then MsgBox "Access_IME_On切替出来ませんでした。" End If Else MsgBox "Access_IME_On切替出来ませんでした。" End If Else MsgBox "Access_IME_On切替出来ませんでした。" End If Else MsgBox "Access_IME_On切替出来ませんでした。" End If '入力コンテキストを開放 lngWin32apiResultCode = ImmReleaseContext(acHwnd, lngInputContextHandle) Else MsgBox "Access_IME_On切替出来ませんでした。" End If End Sub

    なお、標準モジュールのWindowsApiの「PtrSafe」は、記したままでも32bitで動作するようですので、記したままにしています。また、WindowsApi の説明によると、戻り値は成功した場合はゼロ以外の値、しなかった場合はゼロが返る、とのことで、成功しない場合があり得る説明なので、念のため、Do~Loopのプロセスを挿入しましたが、小生の試行錯誤の範囲では成功しなかった例はないので、無用かもしれません。

    ※ 2021/4/29修正;DoEventsを1行追加して2行にすると動作が改善する現象が見られましたので、追加しました。

    2021年4月25日 3:59
  • KokemomoYamamom様、こんばんは。

    さらなる調査をして頂きありがとうございます。
    ご提示頂いたコードを反映して、試してみたいと思います。

    以上、よろしくお願いいたします。
    2021年4月26日 11:23