フリガナを取得する
IMEの入力を読み取りフリガナを取得するテクニックです。
※VB6から追加されたAddressOfを指定しているので下記サンプルは旧VBでは動作しません。
サンプル(32bit) ダウンロード
標準モジュール側
'Ime制御 Public Declare Function ImmGetContext Lib "imm32.dll" (ByVal hWnd As Long) As Long Public Declare Function ImmGetCompositionString Lib "imm32.dll" Alias "ImmGetCompositionStringA" (ByVal himc As Long, ByVal dw As Long, ByVal lpv As String, ByVal dw2 As Long) As Long Public Declare Function ImmReleaseContext Lib "imm32.dll" (ByVal hWnd As Long, ByVal himc As Long) As Long Public Const GCS_COMPREADSTR = &H1 Public Const GCS_COMPREADATTR = &H2 Public Const GCS_COMPREADCLAUSE = &H4 Public Const GCS_COMPSTR = &H8 Public Const GCS_COMPATTR = &H10 Public Const GCS_COMPCLAUSE = &H20 Public Const GCS_CURSORPOS = &H80 Public Const GCS_DELTASTART = &H100 Public Const GCS_RESULTREADSTR = &H200 Public Const GCS_RESULTREADCLAUSE = &H400 Public Const GCS_RESULTSTR = &H800 Public Const GCS_RESULTCLAUSE = &H1000 'イベント処理関連 Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long Public Const GWL_WNDPROC = (-4) Public Const WM_IME_COMPOSITION = &H10F '保存用変数 Public FURIGANA_STR As String Public Save_WindowLong As Long Public Save_hWnd As Long Public Function GetFurigana(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long Dim himc As Long Dim nLEN As Long Dim WorkStr As String 'IME文字確定後で文字が入力された場合 If (uMsg = WM_IME_COMPOSITION) And ((lParam And GCS_RESULTREADSTR) <> 0) Then 'フリガナを取得 'コンテキスト取得 himc = ImmGetContext(hWnd) 'バッフア確保のため入力した文字数を取得 nLEN = ImmGetCompositionString(himc, GCS_RESULTREADSTR, vbNullChar, 0) '入力文字数分バッファ確保 WorkStr = Space(nLEN + 1) '入力文字列取得 Call ImmGetCompositionString(himc, GCS_RESULTREADSTR, WorkStr, nLEN + 1) 'コンテキスト開放 Call ImmReleaseContext(hWnd, himc) FURIGANA_STR = FURIGANA_STR & RTrim(WorkStr) End If GetFurigana = CallWindowProc(Save_WindowLong, hWnd, uMsg, wParam, lParam) End Function Public Sub Furigana_Start(KANJI_Control As Control) 'フリガナ監視スタート 'GetFuriganaイベントをバインドしてます。 Save_WindowLong = SetWindowLong(KANJI_Control.hWnd, GWL_WNDPROC, AddressOf GetFurigana) 'ハンドル保存 Save_hWnd = KANJI_Control.hWnd 'ふりがな文字列初期化 FURIGANA_STR = "" End Sub Public Sub Furigana_End() 'フリガナ監視終了 'イベントのバンドルを解除 Call SetWindowLong(Save_hWnd, GWL_WNDPROC, Save_WindowLong) End Sub
フォーム側
Private Sub Text1_GotFocus() Dim himc As Long Dim hWnd As Long hWnd = Text1.hWnd 'IMEをOn himc = ImmGetContext(hWnd) Call ImmSetOpenStatus(himc, 1) Call ImmReleaseContext(hWnd, himc) '文字列を反転させる Text1.SelStart = 0 Text1.SelLength = Len(Text1.Text) 'フリガナ監視スタート Call Furigana_Start(Text1) End Sub Private Sub Text1_LostFocus() Dim himc As Long Dim nLEN As Long Dim hWnd As Long hWnd = Text1.hWnd 'IMEをOff himc = ImmGetContext(hWnd) Call ImmSetOpenStatus(himc, 0) Call ImmReleaseContext(hWnd, himc) 'フリガナ監視終了 Call Furigana_End '取得したフリガナをセット Text2.Text = Text2.Text & FURIGANA_STR End Sub
サンプル解説
以下の手順でフリガナを取得します。
- テキストボックスのGotFocusイベント時にFurigana_Startプロシージャを呼び出し、フリガナ取得を開始します。(同時にPublic変数FURIGANA_STRが初期化されます)
- テキストボックスのLostFocusイベント時にFurigana_Endプロシージャを呼び出し、フリガナ取得を終了します。
- Public変数FURIGANA_STRには取得したフリガナが入っています、
ます、Furigana_StartプロシージャのSetWindowLong関数を使用してIMEのイベント用にGetFurigana関数をテキストボックスのイベントにバインドしています。
引数の内容は次の通りです。
(引数の名前は、Declare Functionで指定したものです)
メンバー I/O 説明 hWnd In イベントをバンドルするコントロールのハンドル
サンプルではテキストボックスのハンドルを渡しています。nIndex In オフセット
サンプルではGWL_WNDPROCを渡し、ウィンドプロシージャを書き換えることを指定しています。dwNewLong In バンドルする関数のポインタ
サンプルではAddressOfを使用してGetFurigana関数のポインタを渡しています。↑によってテキストボックスのイベント処理がGetFurigana関数に切り替わります。
(SetWindowLong関数の戻り値は元のイベントプロシージャを返します。これは後で必要となるのでPublic変数に保存して置きます)そして、GetFurigana関数では「IME文字確定がされ and 文字が入力されている」と言うメッセージを受け取ったら、ImmGetCompositionString関数で入力文字列を取得します。
引数の内容は次の通りです。
(引数の名前は、Declare Functionで指定したものです)
メンバー I/O 説明 himc In IMEのコンテキスト dw In 取得する情報を表すフラグ
サンプルではGCS_RESULTREADSTRをセットして入力された文字列を1バイトカタカナで返すように指定しています。lpv Out 取得した情報のバッファ dw2 In lpvのサイズ ただし、文字列の取得するには2段階の手順が必要です。(入力された文字の長さが分からないのでバッファが用意できないためです)
- 入力文字のサイズの取得。
引数lpvにNull、引数dw2に0をセットして、ImmGetCompositionString関数を呼び出します。
ImmGetCompositionString関数は文字のサイズを返します。文字のサイズを取得したらバッファを確保します。
末尾にNullが入るので1文字分多くバッファを確保します。
- 入力文字の取得。
確保したバッファとそのサイズを引数lpv、引数dw2にセットして入力文字列を取得します。
そして、取得した入力文字列をPublic変数FURIGANA_STRに追加しています。
なぜ追加しているかというと、1つのコントロールで複数回確定が起こるためです。最後に、テキストボックスの通常イベントをWindowsに処理させるためにCallWindowProc関数でWindowsにイベント処理を渡しています。
(コレをしないと、テキストボックスのLostFocusイベントやChangeイベントが発生しないなどの問題が発生します)引数の内容は次の通りです。
(引数の名前は、Declare Functionで指定したものです)
メンバー I/O 説明 lpPrevWndFunc In コントロールの元のイベントプロシージャ
サンプルではSetWindowLong関数が返して保存してた古いイベントプロシージャを渡しています。hWnd In イベントをバンドルするコントロールのハンドル
サンプルではテキストボックスのハンドルを渡しています。Msg In メッセージ
サンプルではGetFurigana関数に入ってきたメッセージをそのまま渡しています。wParam In パラメータ1
サンプルではGetFurigana関数に入ってきたのを、そのまま渡しています。lParam In パラメータ2
サンプルではGetFurigana関数に入ってきたのを、そのまま渡しています。
この処理をまとめると以下のイメージになります。
SetWindowLong関数でイベントプロシージャが書き換えられると・・・
テキストボックスのイベント発生 ↓ GetFurigana関数の実行
(入力文字列の取得)↓ CallWindowProc関数で
元のイベントプロシージャを呼び出す↓ 元のイベントプロシージャの実行
(テキストボックス本来の動き)と、つまり、このフリガナ取得処理は、テキストボックスの通常のイベントプロシージャの前に割り込んで独自のイベント処理を実装して実現している訳です。
ちなみに、テキストボックスのLostFocusイベントで行っているFurigana_Endプロシージャはイベントプロシージャを念のため元に戻しています。
[ Window Close ]