Webブラウザコントロールで検索をするには?

解決


マロン  2005-05-25 20:25:08  No: 90039

どうもお世話になります。
Webブラウザコントロールの使い方で、また教えて頂けないでしょうか。

http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/jpisdk/dhtml/content/TextRange.asp

の「ドキュメントのテキストを検索する」という解説で、

■コード1
  var rng = document.body.createTextRange();
  if (rng.findText("sample")==true) {
      rng.select();
      rng.scrollIntoView();
  }

というコードが書いてあるのですが、これを参考にして、私は次のようなVBのコードを書いてみました。

■コード2
  Private WithEvents Body As MSHTML.HTMLBody

  Private Sub WebBrowser1_DocumentComplete(ByVal pDisp As Object, URL As Variant) 
      Set Body = WebBrowser1.Document.Body
  End Sub

  Private Sub Command1_Click()
      If Body.createTextRange.findText("テキスト") Then
          Body.createTextRange.Select
          Body.createTextRange.scrollIntoView True
      End If
  End Sub

私としては、コード1と2は内容的には同じだと思ったのですが、これを実行するとドキュメント全体が選択された状態になってしまいます。一体何がおかしいのでしょうか。
(MSDNを詳しく読んではいますが、いまいち私にはピンと来ませんので、要領を得ない質問ですみません)


魔界の仮面弁士  2005-05-25 20:59:50  No: 90040

> 私としては、コード1と2は内容的には同じだと思ったのですが、
異なります。同じにするのならば、こうなりますね。
(コメント部を解除すると、動作の意味がわかるかも)

Private Sub Command1_Click()
    Dim Rng As MSHTML.IHTMLTxtRange
    Set Rng = Body.createTextRange()
    'MsgBox Rng.htmlText, vbInformation
    If Rng.findText("テキスト") Then
        'MsgBox Rng.htmlText, vbInformation
        Rng.Select
        Rng.scrollIntoView True
    End If
    Set Rng = Nothing
End Sub

http://www.microsoft.com/japan/msdn/library/ja/jpisdk/dhtml/references/objects/obj_TextRange.asp
上記を読んでみると、このような事が書かれています。

》move、moveToElementText、findTextなどのメソッドを使って、
》TextRangeオブジェクトの先頭と末尾を移動させてその範囲を変更できる。

つまり、findTextを使うと、その TextRangeオブジェクトの範囲が
変更されるという事です。

マロンさんのコードでは、毎回 createRangeメソッドによって、
「新たなTextRangeオブジェクトを作り直している」ので、
TextRangeの範囲が、初期状態(BODY要素内の全ての範囲を示す)に
なってしまっていたわけですね。


マロン  2005-05-26 16:51:38  No: 90041

なるほど。了解しました。
おっしゃるようにしましたらうまく行きました。

ところで、2回目の検索を次の位置へ移動したい場合、moveStartを使えば実現できるだろうと思って、次のようなコードをまず試しに書いてみました。

  Dim Rng As MSHTML.IHTMLTxtRange

  Set Rng = Body.createTextRange()
  Rng.moveStart "character", 100    →  例えば50文字目で1回目の検索がなされたとします
  
  If Rng.findText("テキスト") Then                        
    Rng.Select
    Rng.scrollIntoView True
  End If
  Set Rng = Nothing

一応これで次の場所の"テキスト"を検索するようですが、問題はありませんでしょうか。


魔界の仮面弁士  2005-05-26 18:07:55  No: 90042

「100」という固定数値を使っている点に若干疑問を感じますが、
考え方としてはそれで良いかと。

以下は5年前、某所に投稿したサンプルです。参考になれば。
Text1に指定された語句を検索し、それを黄色く反転させています。

Private Sub Command1_Click()
    Dim Doc As Object       'MSHTML.HTMLDocument
    Dim Body As Object      'MSHTML.HTMLBody
    Dim objRange As Object  'MSHTML.IHTMLTxtRange
    Dim BMK As String
    'Dim L As Long

    '検索文字列を入れておいてください。
    If Len(Text1.Text) = 0 Then Exit Sub
    
    Set Doc = WebBrowser1.Document
    Set Body = Doc.Body
    Set objRange = Body.createTextRange

    '≫≫≫≫≫ 検索開始
    'For L = 0 To 255
    '   If objRange.findText(Text1.Text) = False Then Exit For
    Do While objRange.findText(Text1.Text)
        '最初に見つかった位置を保存しておきます。
        If Len(BMK) = 0 Then BMK = objRange.getBookmark
        
        '検索した語句を黄色く反転させる。
        objRange.execCommand "BackColor", False, "YELLOW"
        
        '論理カーソル位置を、検索した語句の末尾に移動させる。
        objRange.collapse False
    Loop
    'Next L
    '≪≪≪≪≪ 検索終了

    'ついでに、最初に見つけた語句の位置までスクロールさせています。
    If Len(BMK) Then
        objRange.moveToBookmark BMK
        objRange.scrollIntoView
    End If

    '最後は一応、後始末を。
    Set objRange = Nothing
    Set Body = Nothing
    Set Doc = Nothing
End Sub


マロン  2005-05-26 20:07:44  No: 90043

早速試してみました。
ご提示のコードは、文字列を検索して1度にすべての結果を黄色反転する訳ですね。
なるほど、納得いたしました。

ではもう一つのバリエーションとして、コマンドボタンを押す度に次の検索箇所へ移動して反転表示させる方法を考えてみますと、1つめの検索文字列の末尾を次の検索の開始位置にすればよいのだと思いますが、それを実現するにはブックマークとmoveStartを利用すればよいのでしょうか。


マロン  2005-05-27 18:54:33  No: 90044

すみません。私の質問の仕方がおかしいようでした。
貴重なアドバイス感謝いたします。
また自分でいろいろと調べてみます。


マロン  2005-05-27 21:06:03  No: 90045

検索ボタンを押す度に次の位置の文字列を検索できるようにするために、moveStartで位置を指定すれば良さそうということは理解できました。ありがとうございました。

ここで、moveStart を利用する目的として、私は次のようなことを考えました。
例えば、表示されているドキュメントのある文字列をマウスでドラッグ反転し、それと同じ文字列を反転文字列以降の位置から検索しようとする場合です。

リッチテキストボックスで SelStart スタートというのがありますが、これは、マウスでドラッグ反転させた文字列の先頭位置がセットされていますよね。
これと同じ事をWebブラウザコントロールで行った場合、SelStart と同じ結果を取得する方法ってあるのでしょうか。

また、

    Rng.findText("テキスト")

で検索された時の文字列の位置を取得する方法として、

    Set Rng = objForm.Body.createTextRange()
    strTarget = Rng.Text
    If Rng.findText("テキスト") Then
        Rng.Select
        lngPos = InStr(strTarget, Rng.htmlText)
        Rng.scrollIntoView True
    End If

のようなことを考えたのですが、これではいつも最初の位置しか取得できないですよね。
最初は moveStart で検索開始位置を指定していれば、検索された文字列の位置も適切に求まるのかな?  と思ったのですが、期待はずれでした。
何か良い方法があれば、是非アドバイス頂けないでしょうか。


pi  2005-05-28 07:32:53  No: 90046

> 表示されているドキュメントのある文字列をマウスでドラッグ反転し、
> それと同じ文字列を反転文字列以降の位置から検索しようとする場合です。

こういうことでしょうか?

Option Explicit

Private WithEvents Doc As HTMLDocument
Private moRng As IHTMLTxtRange
Private msText As String

Private Sub Command1_Click()
    If moRng Is Nothing Then Exit Sub
    If moRng.findText(msText) Then
        moRng.Select
        moRng.scrollIntoView
        moRng.collapse False
    Else
        MsgBox "検索終了"
        Set moRng = Nothing
    End If
End Sub

Private Sub WebBrowser1_BeforeNavigate2(ByVal pDisp As Object, URL As Variant, Flags As Variant, TargetFrameName As Variant, PostData As Variant, Headers As Variant, Cancel As Boolean)
    Set Doc = Nothing
End Sub

Private Sub WebBrowser1_DocumentComplete(ByVal pDisp As Object, URL As Variant)
    Set Doc = WebBrowser1.Document
End Sub

Private Function Doc_onclick() As Boolean
    Dim selRng As IHTMLTxtRange
    Set selRng = Doc.selection.createRange
    msText = selRng.Text
    If Len(msText) Then
        Set moRng = Doc.body.createTextRange
        moRng.moveToBookmark selRng.getBookmark
        moRng.moveStart "word"
    End If
    Set selRng = Nothing
    Doc_onclick = True
End Function


マロン  2005-05-28 17:31:35  No: 90047

どうもお世話になります。
貴重なアドバイスありがとうございました。早速試してみます!


マロン  2005-05-29 00:04:08  No: 90048

結果をご報告します。

ご提示頂いたコードを参考に私のアプリに移植して試したところ、完璧にうまく行きました。

そこで私なりにちょっと工夫をして、試行錯誤ではありましたが、検索が終了したら findText の2番目のパラメータ(検索方向の指定)を負の値に、そして collapse の値をTrueに設定することで、逆方向にも検索できるようにしました。
結果は、何やらうまくやってくれるようです(笑)。

今回の問題がうまく解決できて、とても感激しております。
piさん、そして魔界の仮面弁士さん、本当にありがとうございました。
これからも、よろしくお願い致します。


マロン  2005-05-29 00:05:06  No: 90049

「解決」にチェックを入れるのを忘れました。


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

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






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