[リストへもどる]   [VBレスキュー(花ちゃん)]
一括表示

投稿時間:2006/02/13(Mon) 11:22
投稿者名:じゅん
Eメール:
URL :
タイトル:
フリガナ取得いついて
テキストボックス1に入力した文字をフリガナ取得してテキストボックス2へ表示させたいのですが・
・・
今、下記のコードを書いてやってるのですが、ファンクションキーに設定したボタンや、他のテキス
トボック
スにフォーカスが移ったりすると【スタック領域の不足です】とエラーがでて強制終了してしまいま
す。解決
方法があったら教えてください。下記のコードは全てではないので、これ以外原因がありそうなら、
コード載
せます。

/// 標準モジュールのコード ////

Option Explicit
'Ime制御
Public Declare Function ImmGetContext Lib "imm32.dll" (ByVal hWnd As Long) As Lon
g
Public Declare Function ImmSetOpenStatus Lib "imm32.dll" (ByVal himc As Long, ByV
al b 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, By
Val 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&q
uot; (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&quo
t; (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


●フォームでの処理(テキストボックスは配列を使用しています。配列名:txtTokField(0)〜txtTokFie
ld
(18))
●漢字のテキストボックスはtxtTokField(1)、フリガナのテキストボックスはtxtTokField(2)です

以下フォームのコード
Private Sub txtTokField_GotFocus(index As Integer)
    
    Dim himc As Long
    Dim hWnd As Long
    Dim nLEN As Long
    
    If index = 1 Then

        hWnd = txtTokField(1).hWnd

        'IMEをOn
        himc = ImmGetContext(hWnd)
        Call ImmSetOpenStatus(himc, 1)
        Call ImmReleaseContext(hWnd, himc)

        '文字列を反転させる
        txtTokField(1).SelStart = 0
        txtTokField(1).SelLength = Len(txtTokField(1).Text)

        'フリガナ監視スタート
        Call Furigana_Start(txtTokField(1))
    End If

    If index = 2 Then

        hWnd = txtTokField(1).hWnd

        'IMEをOff
        himc = ImmGetContext(hWnd)
        Call ImmSetOpenStatus(himc, 0)
        Call ImmReleaseContext(hWnd, himc)

        'フリガナ監視終了
        Call Furigana_End

        '取得したフリガナをセット
        txtTokField(2).Text = txtTokField(2).Text & FURIGANA_STR
    End If
        
End Sub 

投稿時間:2006/02/13(Mon) 12:11
投稿者名:GOD
Eメール:
URL :
タイトル:
Re: フリガナ取得いついて
修正機能を使ってコード投稿モードで投稿し直した方が良いですよ。(現状だとコードがみにくい。)
本問題点とは関係ないかも知れませんが、txtTokField(1)のGotFocusイベントが発生する前に
txtTokField(2)のGotFocusイベントが発生するとウィンドウプロシージャが変なことになりませんか?

投稿時間:2006/02/13(Mon) 12:43
投稿者名:じゅん
Eメール:
URL :
タイトル:
Re^2: フリガナ取得いついて
> 本問題点とは関係ないかも知れませんが、txtTokField(1)のGotFocusイベントが発生する前に
> txtTokField(2)のGotFocusイベントが発生するとウィンドウプロシージャが変なことになりません
か?
返事ありがとうございます。
修正機能使うの知りませんでした。ごめんなさい。
上記の問題は起こらないと思います。

投稿時間:2006/02/13(Mon) 15:19
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
Re^3: フリガナ取得いついて
> 修正機能使うの知りませんでした。ごめんなさい。
まずは、コード投稿モード(図表モード) で修正願います。

> 上記の問題は起こらないと思います。
確かめられたのでしょうか?
無限ループのような処理をどこかで行っておられる可能性があります。
[F8]でステップ実行して確認して見て下さい。

投稿時間:2006/02/13(Mon) 16:17
投稿者名:じゅん
Eメール:
URL :
タイトル:
Re^4: フリガナ取得いついて
返事送れてすみません。以下コード修正いたします。
●以下モジュールのコード
Option Explicit
'Ime制御
Public Declare Function ImmGetContext Lib "imm32.dll" (ByVal hWnd As Long) As Long
Public Declare Function ImmSetOpenStatus Lib "imm32.dll" (ByVal himc As Long, ByVal b 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 txtTokField_GotFocus(index As Integer)
    
    Dim himc As Long
    Dim nLEN As Long
    Dim hWnd As Long
    
    If index = 1 Then
            
        hWnd = txtTokField(1).hWnd
        
        'IMEをOn
        himc = ImmGetContext(hWnd)
        Call ImmSetOpenStatus(himc, 1)
        Call ImmReleaseContext(hWnd, himc)
        
        '文字列を反転させる
        txtTokField(1).SelStart = 0
        txtTokField(1).SelLength = Len(txtTokField(1).Text)
        
        'フリガナ監視スタート
        Call Furigana_Start(txtTokField(1))
    
    End If
        
    If index = 2 Then
        
        hWnd = txtTokField(1).hWnd
        
        'IMEをOff
        himc = ImmGetContext(hWnd)
        Call ImmSetOpenStatus(himc, 0)
        Call ImmReleaseContext(hWnd, himc)
            
        'フリガナ監視終了
        Call Furigana_End
            
        '取得したフリガナをセット
        txtTokField(2).Text = txtTokField(2).Text & FURIGANA_STR

    End If
End Sub


●ループしているところは GetFurigana みたいです。みたいですみませ。
一応動きを
@txtTokField(1)へフォーカス移る→Furigana_Start 走る
A画面を広こうとする(止めて走らすとコードが出てきて画面は後ろに行くのでそれを呼び出そうとする)

GetFurigana
BGetFuriganaが3回る
CA〜Bの繰り返し

投稿時間:2006/02/13(Mon) 17:51
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
Re: フリガナ取得いついて
ステップ実行した結果はどうだったのですか?
そもそも、ここへ投稿したコードでそのようなエラーが発生しますか?何度も同じコードを
投稿しても問題が他にあれば何もならないのでは、もっと自分で試すようにして下さい。
エラーが確認できるシンプルなコードを新たに作るなりして試して、順次機能を追加
しながら確認すれば、どこが悪いか解るかと思うのですが。

投稿時間:2006/02/13(Mon) 18:01
投稿者名:じゅん
Eメール:
URL :
タイトル:
Re^2: フリガナ取得いついて
> ステップ実行した結果はどうだったのですか?
ステップ実行した結果は書いたつもりなんですが・・・。
で、フリガナ変換は一応できるのです。が、フォーカスが他に移動したりするとエラーがでるのです。

投稿時間:2006/02/13(Mon) 18:24
投稿者名:GOD
Eメール:
URL :
タイトル:
Re^3: フリガナ取得いついて
>> 本問題点とは関係ないかも知れませんが、txtTokField(1)のGotFocusイベントが発生する前に
>> txtTokField(2)のGotFocusイベントが発生するとウィンドウプロシージャが変なことになりま
>> せんか?
>>
>上記の問題は起こらないと思います。
>
↑ということは Furigana_Start関数や Furigana_End関数が何度も片方のみ通過するのは想定の
範囲内ですか?
Furigana_Start関数だけを連続で動作させるなら txtTokField の(1)→(3)→(1)を繰り返せば
Furigana_End関数を呼ばずに何度も呼ぶはずですが。
Furigana_End関数も同様でしょう。(2)→(3)→(2)...

#プログラムは貴方の組んだようにしか動作してくれませんよ。
#Debug.Print等(or ステップ実行)で SetWindowLong関数に設定する値が思ったとおりになってい
#るのか確かめてますか?

投稿時間:2006/02/13(Mon) 18:31
投稿者名:じゅん
Eメール:
URL :
タイトル:
Re^4: フリガナ取得いついて
> ↑ということは Furigana_Start関数や Furigana_End関数が何度も片方のみ通過するのは想定の
> 範囲内ですか?
想定の範囲外です!
> Furigana_Start関数だけを連続で動作させるなら txtTokField の(1)→(3)→(1)を繰り返せば
> Furigana_End関数を呼ばずに何度も呼ぶはずですが。
> Furigana_End関数も同様でしょう。(2)→(3)→(2)...
もう一度確認してみます!!!!

投稿時間:2006/02/13(Mon) 18:58
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
Re^3: フリガナ取得いついて
> で、フリガナ変換は一応できるのです。が、フォーカスが他に移動したりするとエラーがでるので
す。
OS やVBのバージョン等環境は?
フォーカスが移動した時ではなく、IMEの変換の途中(未確定状態)の時に他のコントロールに
移動したりするとVB事落ちてしまうと言う事ですか?

IMEの変換を確定してからなら移動しても問題ありませんよ。
漢字を入力しているテキストボックスのtxtTokField_LostFocus イベントで
Call Furigana_End の処理をすればいいのでは。
私の環境では上記を追加すれば落ちる事もエラーも発生しません。
(WindowsXP(Home SP2) VB6.0(SP6))

スタック領域の不足です のエラーがでるのは、Furigana_Start → Furigana_End →
Furigana_Start → Furigana_End のような動作をせず、Furigana_Start → Furigana_Start
のような動作をするから起きるのです。

もっとも、ImmGetContext と ImmGetCompositionString と ImmReleaseContext
だけのAPIでリアルタイムにフリガナを取得する事ができます。(態々サブクラス化しなくても)
ここのサンプル(No.210)のように

又は、魔界の仮面弁士さん 03/04-15:18 No.2964 の投稿のタイプライブラリーを使わせて
もらうとか。

投稿時間:2006/02/14(Tue) 09:55
投稿者名:じゅん
Eメール:
URL :
タイトル:
Re^4: フリガナ取得いついて
> 漢字を入力しているテキストボックスのtxtTokField_LostFocus イベントで
>  Call Furigana_End の処理をすればいいのでは。
おはようございます。返事遅くなってすみません。
あれから、やってみたところ、LostFocusのイベントにもっていったら落ちないようになりました。前やったと
きには落ちたのに・・・。構文がおかしかったのだと思います。
こうやてやってみるとインプットマンってかなり便利なものだなぁ〜と思いました。
返答してくださった方々、本当にありがとうございました。では失礼します。

投稿時間:2006/02/14(Tue) 10:13
投稿者名:じゅん
Eメール:
URL :
タイトル:
Re^4: フリガナ取得いついて
> もっとも、ImmGetContext と ImmGetCompositionString と ImmReleaseContext
> だけのAPIでリアルタイムにフリガナを取得する事ができます。(態々サブクラス化しなくても)
> ここのサンプル(No.210)のように
↑についての質問なのですが、リアルタイムとはEnter1回押しただけで変換されるということなのでしょう
か?ちなみに、今はEnter2回押して変換されます(1回目:漢字変換、2回目:Enter押したのでフォーカス移
動がいどうしてカタカナに変換)

> 又は、魔界の仮面弁士さん 03/04-15:18 No.2964 の投稿のタイプライブラリーを使わせて
> もらうとか。
↑のやつを見ようとしたのですが、行き方がわかりません。どうやったらいけるのでしょうか?Noだけで検索し
たら出てこなかったので!

何度もすみません。

投稿時間:2006/02/14(Tue) 12:17
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
Re^5: フリガナ取得いついて
> か?ちなみに、今はEnter2回押して変換されます(1回目:漢字変換、2回目:Enter押したのでフ
下記をDLして確認して見てください。
hhttp://www.bcap.co.jp/hanafusa/furi.lzh

> > 又は、魔界の仮面弁士さん 03/04-15:18 No.2964 の投稿のタイプライブラリーを使わせて
> > もらうとか。
> ↑のやつを見ようとしたのですが、行き方がわかりません。どうやったらいけるのでしょうか?Noだ
けで検索し
> たら出てこなかったので!

2003 年のログなので、過去のログのNo.1 の方の ワード検索で 2964 で検索するば2番目位に
出てくるかと思うのですが?
hhttp://www.bcap.co.jp/hanafusa/logbbs/wforum.cgi?mode=allread&no=2962#2964

投稿時間:2006/02/14(Tue) 13:41
投稿者名:じゅん
Eメール:
URL :
タイトル:
Re^6: フリガナ取得いついて
> 下記をDLして確認して見てください。
> hhttp://www.bcap.co.jp/hanafusa/furi.lzh
ありがとうございます。
上記と同じ動きが理想の動きなのです。ソースは見せてもらえませんよね(笑)
一回の変換で変換文字を何かに持たせたらいいのでしょうか?ヒントをば(!^_^)

投稿時間:2006/02/14(Tue) 13:51
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
Re^7: フリガナ取得いついて
> 一回の変換で変換文字を何かに持たせたらいいのでしょうか?ヒントをば(!^_^)
ヒントはサンプルの内容を紹介している所に書いてありますし、特に難しい事は
何もしておりません。(アイデアだけ)
その辺を考えるのがプログラムの醍醐味かと。

投稿時間:2006/02/14(Tue) 14:06
投稿者名:じゅん
Eメール:
URL :
タイトル:
Re^8: フリガナ取得いついて
> > 一回の変換で変換文字を何かに持たせたらいいのでしょうか?ヒントをば(!^_^)
> ヒントはサンプルの内容を紹介している所に書いてありますし、特に難しい事は
> 何もしておりません。(アイデアだけ)
> その辺を考えるのがプログラムの醍醐味かと。
ありがとうございます。
がんばってみます(^_^)