複数行テキストボックスからの指定行の文字列取得をするには?

解決


カプチ  2007-10-02 01:22:59  No: 99501

毎々参考にさせていただいております。
過去ログを参照しましたところ、
http://madia.world.coocan.jp/cgi-bin/VBBBS/wwwlng.cgi?print+200302/03020044.txt
のURLと全く同じ現象なのですが、ここにある方法では解決できなかったため、
質問させていただきます。

こちらを参考にプログラムを組んでいるのですが。。。
http://www.bcap.co.jp/hanafusa/VBHLP/Apointrow.htm

コントロール配列で複数のテキストボックスに対して、SendMessageのEM_GETLINE
をしようして、ループで文字列を取得しようとしているのですが、複数回の実行
で文字列取得に成功するテキストボックスやしないテキストボックスが変わった
り、実行ごとに非常に不安定な動作になってしまっています。失敗するときの
SendMessageの戻り値及びErr.LastDLLErrorは0で返ってきます。
安定させる方法をどなたかに御教示いただければ嬉しいです。
よろしくお願いします。

環境は
  VB6.0 SP6
  WINDOWS XP Pro SP2
です。


我龍院  2007-10-02 03:12:21  No: 99502

おかしいと思われる症状が再現出来るコードを
提示されない限り、アドバイスは無理でしょうね。


カプチ  2007-10-02 17:51:30  No: 99503

我龍院さん、失礼しました。
確かにそうですね。コードは下記のような感じです。

Dim i As Integer
Dim Length As Long
Dim TempText As String * 256
Dim GetText As String

For i=0 To 254
    If Me.Text1(i).Text  <> "" Then
        TempText = ""
  Length = SendMessage(Me.Text1(i).hWnd, EM_GETLINE, i, ByVal TempText)
  GetText = RTrim$(Left$(TempText, Length))
    End If
Next 

で、きちんと取れるときはLengthが0以外になるのですが、失敗するときは
なぜかLengthが0になり、GetTextが""になる次第です。
よろしくお願い致します。


大吉末吉  2007-10-02 19:12:46  No: 99504

横から失礼。

> Length = SendMessage(Me.Text1(i).hWnd, EM_GETLINE, i, ByVal TempText)

これって、コントロール配列にしたTextBoxが255個あって、
1番のTextBox(Me.Text1(0))の1行目
2番のTextBox(Me.Text1(1))の2行目
3番のTextBox(Me.Text1(2))の3行目
・・・・
255番のTextBox(Me.Text1(254))の255行目
を参照しているように見えますが・・・

例えば、255番目のTextBoxは、255行ありますか?

無ければ、当然0が返ってきますけど・・・

#「If Me.Text1(i).Text  <> "" Then」この条件だと、
#「255行目があるかどうか」は判断できませんし・・・


カプチ  2007-10-02 19:20:00  No: 99505

大吉末吉さん、ご回答ありがとうございます。
申し訳ありません。ソースの貼付ミスです。。
貼付用に実際のやつを簡略化した際に間違えてしまいました。

Dim i As Integer
Dim Length As Long
Dim TempText As String * 256
Dim GetText As String
Dim MaxRow As Long

For i=0 To 254
  If Me.Text1(i).Text  <> "" Then
    MaxRow = SendMessage(Me.Text1(i).hWnd, EM_GETLINECOUNT, 0&, 0&)
    For j=0 To MaxRow-1
      TempText = ""
      Length = SendMessage(Me.Text1(i).hWnd, EM_GETLINE, j, ByVal TempText)
      GetText = RTrim$(Left$(TempText, Length))
    Next
  End If
Next 

正しくはこんな感じです。すみませんでした。。


魔界の仮面弁士  2007-10-02 21:41:09  No: 99506

実際にはループ中で、何か別の処理をしているのですよね?
# 提示されたコードでは、ループ中に変数の値を上書きしているので、
# 最終的な GetText の値は、Text1(254) の末尾データになってしまう。

で、コードを見る限り、いろいろと問題があるようで。

> Dim TempText As String * 256
> TempText = ""
> Length = SendMessage(Me.Text1(i).hWnd, EM_GETLINE, j, ByVal TempText)
EM_GETLINE の場合、lparam の先頭 2 バイトには、
「バッファの最大サイズ」を指定する必要があるかと。
http://msdn2.microsoft.com/en-us/library/ms672074.aspx

> GetText = RTrim$(Left$(TempText, Length))
ANSI バージョンなら、戻り値は「文字数」ではなく「バイト数」なので、
単純に Left で切り出してしまってはマズいかと。

Unicode バージョンなら「文字数」が返されますが、その場合は、
バッファは String 型ではなく、Byte 配列にしてください。


カプチ  2007-10-02 23:17:06  No: 99507

魔界の仮面弁士さん、いつもありがとうございます。
さらに調べた結果、下記コードで今のところ安定するようになりました。

http://pc2.2ch.net/tech/kako/1047/10477/1047743187.html
の871さんの書込を参照しました。

Dim i As Integer
Dim j As Integer
Dim Length As Long
Dim TempText() As Byte
Dim GetText As String
Dim MaxRow As Long
Dim Index As Long

For i=0 To 254
    If Me.Text1(i).Text  <> "" Then
        MaxRow = SendMessage(Me.Text1(i).hWnd, EM_GETLINECOUNT, 0&, 0&)
        For j=0 To MaxRow-1
            TempText = ""
            Index = SendMessage(Me.Text1(i).hWnd, EM_LINEINDEX, CLng(i), 0&)
            Length = SendMessage(Me.Text1(i).hWnd, EM_LINELENGTH, Index, 0&)
            ReDim TempText((Length - 1) + 1)
            CopyMemory TempText(0), Length, 2
            Length = SendMessage(Me.Text1(i).hWnd, EM_GETLINE, CLng(j), TempText(0))
            GetText =  StrConv(LeftB(TempText, Length), vbUnicode)
        Next
    End If
Next 

前のコードでは正常に動いたり動かなかったりしたので、これでしばらく様子をみたいと思います。

我龍院さん、大吉末吉さん、魔界の仮面弁士さん、ありがとうございました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加