テキストボックス内の現在表示位置を知るには?

解決


はるきち  2006-10-23 21:46:48  No: 133804

プロパティScrollBarsで縦スクロールバーをつけたテキストボックスにおいて、
利用者がスクロールバーを動かした状態で表示更新した場合、
表示先頭が常に先頭に戻ってしまいます。
動かしたスクロールバーの位置を保持したまま再表示できる方法はないでしょうか?

今のところSelStartプロパティを使うのではないかとがんばっていますが、
この場合、スクロールバーを動かすごとにその先頭表示位置を認識していなければならず
そのやり方がわかりません。

どうかご教授ください。


特攻隊長まるるう  2006-10-23 22:31:36  No: 133805

> 表示先頭が常に先頭に戻ってしまいます。
それが標準的で一番問題の少ない動作なのでは?
更新後のデータでカレント行のデータが削除されていたら?
変更されていたら?デフォルト(先頭)に戻るのが一番問題ないでしょう?

> 今のところSelStartプロパティを使うのではないかとがんばっていますが、
> この場合、スクロールバーを動かすごとにその先頭表示位置を認識していなければならず
> そのやり方がわかりません。
少し厳密に考えないといけないのは、スクロールバーの状態とキャレットの
位置(SelStart)は食い違う場合があるということです。
スクロールバーをマウスで直接操作すれば、キャレットの位置が表示
されない場所までスクロールできますよね?この場合はどうします?

とりあえず『スクロール』等のキーワードで過去ログ検索すれば、
手段が複数ある事が分かります。他のコントロールを使う案もあります。
…開発環境が書かれていません。
[VB.NET]では SelectionStart になると思うので[VB6.0]と判断します。
http://madia.world.coocan.jp/cgi-bin/VBBBS2/wwwlng.cgi?print+200512/05120020.txt
とか。


はるきち  2006-10-24 00:19:32  No: 133806

開発環境はWindows2000ver.5.0、VB6.0です。

書き足りないことがあったので補足します。

表示行数は初期表示から増減することはなく、
初期表示で何も表示していない行はずっと無表示、
何か表示されている行はずっと何かを表示…で
その内容が更新されていきます。

そのテキストボックスはあるファイル内容を表示していて、
別プロセスがその内容を書き換えて表示更新を通知しています。


我龍院  2006-10-24 16:14:50  No: 133807

テキストの変更前に、SendMessageで「EM_GETFIRSTVISIBLELINE」を送り、
先頭行を取得保持して、変更後同じくSendMessageで「EM_LINESCROLL」を送り、
先頭行をセットした後、SelStartでキャレットをセットします。
長いテキストだと、スクロールに少し時間がかかり、見苦しいのですが、
あまり良い対策は無いようです。
出来るなら、SelTextやSelStart等で部分的にテキストをが編集出来る
ルーチンを外から呼べる様に作ることをお勧めします。


はるきち  2006-10-24 21:34:39  No: 133808

どうやっても画面側ではできないようなので、
ファイル内容を書き換えるプロセスが先頭表示バイト数を計算して
コントロールすることで対応しました。


我龍院  2006-10-24 22:36:13  No: 133809

どこが上手くいかないか言って戴かないと....
テキストを書き換えてるなら、ハンドルは取れていますよね。

Private Declare Function SendMessage _
    Lib "user32" Alias "SendMessageA" _
    (ByVal hwnd As Long, _
    ByVal wMsg As Long, _
    ByVal wParam As Long, _
    lParam As Any) As Long
Private Const EM_GETFIRSTVISIBLELINE = &HCE
Private Const EM_SCROLL = &HB5

Private Sub Form_Load()
    Dim i, j
    For i = 1 To 50
        Text1 = Text1 & i
        For j = 1 To 3
            Text1 = Text1 & "富士山、fujiyama"
        Next
        Text1 = Text1 & vbCrLf
    Next
    Text1.SelStart = 1005
    Text1.SelLength = 3
    For i = 1 To 5
        SendMessage Text1.hwnd, EM_SCROLL, 1, ByVal (0)
    Next
End Sub

Private Sub Command1_Click()
    Dim t As Integer, t1 As Integer, t2 As Integer
    Dim i As Integer
    Dim s As String
    t = SendMessage(Text1.hwnd, EM_GETFIRSTVISIBLELINE, 0, 0)
    t1 = Text1.SelStart
    t2 = Text1.SelLength
    s = Text1 
    Text1 = "" '一度消す
    Text1 = Replace(s, "富士山", "高尾山")  'テキスト再設定
    For i = 1 To t
        SendMessage Text1.hwnd, EM_SCROLL, 1, ByVal (0)
    Next
    Text1.SelStart = t1
    Text1.SelLength = t2
    Text1.SetFocus
End Sub


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

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






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