tagCANDY CGI VBレスキュー(花ちゃん)の Visual Basic 6.0用 掲示板 [ツリー表示へ]   [Home]
一括表示(VB6.0)
タイトルWebBrowserコントロールとMicrosoft HTML Object Library
記事No12706
投稿日: 2008/07/04(Fri) 19:35
投稿者sayman
はじめまして
セイマンといいます。
よろしくお願いします。

OSはXP VB6.0を使用しています。
いろいろ調べたのですがどうしえもわからないので質問させて下さい。

WebBrowserコントロールを使ってローカルにあるhtmlファイルを表示しています

WebBrowserコントロール上でテキストを選択すると
そのテキストを取得することはできたのですが、
そのテキストがhtmlソースのどの部分なのかというのが分かるようにならないでしょうか?

イメージ的にDreamweberみたいな感じです。

以上よろしくお願いします

[ツリー表示へ]
タイトルRe: WebBrowserコントロールとMicrosoft HTML Object Library
記事No12707
投稿日: 2008/07/04(Fri) 23:15
投稿者sayman
お世話になります
お願いします

少し質問の内容を変えます。
私がしたい動作が2通りあるのではないかと思い
2パターン質問があります
どちらかが実装できればうれしいです

お手数ですがよろしく願いします。

-------パターン1---------
htmlソースに
<html>
<body>
@<!-- &&&TES:1 -->あいうえお<!-- &&&TEE:1 -->


A<!-- &&&TES:2 -->あいうえお<!-- &&&TEE:2 -->
</body>
<html>
と書いてあるとして
先にソースを読み込んで
TES:1=あいうえお
TES:2=あいうえお
というデータを配列か何かに持っておいて

WebBrowserコントロールで表示された
-----------------------
@あいうえお
Aあいうえお
-----------------------
この表示の@の「あいうえお」を
WebBrowserコントロール上で選択したときに

TES:1のあいうえおを選択しています
というような関連付けはできるでしょうか?


-------パターン2--------
先ほど見つけたのですが
WebBrowserに編集モードがあるのを知ったので

htmlソースに
<html>
<body>
@あいうえお

A<!-- &&&TES:1 -->あいうえお<!-- &&&TEE:1 -->


B<!-- &&&TES:2 -->あいうえお<!-- &&&TEE:2 -->
</body>
<html>
と書いてあるときに

-----------------------
@あいうえお
Aあいうえお
Bあいうえお
-----------------------
編集モードでこの表示の
独自タグで囲まれた
AとBのみ編集可能みたいな制限はできるのでしょうか?

以上長文になってしまい申し訳ないですが
よろしくお願いします

[ツリー表示へ]
タイトルRe^2: WebBrowserコントロールとMicrosoft HTML Object Library
記事No12709
投稿日: 2008/07/05(Sat) 08:14
投稿者花ちゃん
下記のような感じで、選択範囲の文字列をテキスト形式及びHTML形式で
取得したのでは、だめですか?

    Set txtRange = WebBrowser1.Document.selection.createRange()
    txtRange.Text
    txtRange.htmlText

上記取得結果(当サイトのトップ画面の一部)

あなたは累計人目の訪問者です。
-------------------------------------------------------------------------------
あなたは累計<IMG alt=累計カウンター
src="http://hanatyan.sakura.ne.jp/daycount/daycount.cgi?gif">人目の訪問者です。

[ツリー表示へ]
タイトルRe^3: WebBrowserコントロールとMicrosoft HTML Object Library
記事No12710
投稿日: 2008/07/05(Sat) 10:04
投稿者sayman
返信ありがとうございます。
してみたのですが

この場合
「あいうえお」のテキストの「あい」のみを選択された場合
当然と言えば当然なのですが
「あい」しか取得できず、この「あい」がhtmlソースの中でどの部分なのかが
わかりません。

でも、花さんのおかげでhtmlソースコードの取得ができたので

ソースコードに
<span id="1"><!-- &&&TES:1 -->あいうえお<!-- &&&TEE:1 --></span>
となっていた場合、spanの中をクリックまたは選択されたときに
<span>内をすべて選択みたいなjavascriptをいれこめばできるのかな
と思っています。

この動作をVB上でさせれるといいのですが・・・・


あと、初心者的な質問で申し訳ないのですが
>     Set txtRange = WebBrowser1.Document.selection.createRange()
>     txtRange.Text
>     txtRange.htmlText
この場合、txtRangeはどう指定すればいいのでしょうか?

今は
Dim txtRange As Variant(強引で申し訳ない)
で指定していますが

Dim txtRange As MSHTML.HTMLDocument
Dim txtRange As IHTMLDocument2
でも型が違いますといわれてしまいます。

以上よろしくお願いします

[ツリー表示へ]
タイトルRe^4: WebBrowserコントロールとMicrosoft HTML Object Library
記事No12711
投稿日: 2008/07/05(Sat) 11:38
投稿者花ちゃん
> Dim txtRange As MSHTML.HTMLDocument
> Dim txtRange As IHTMLDocument2
> でも型が違いますといわれてしまいます。

調べ方その1
Google で createRange をキーに検索してみる(他の人がどのように使っているか調べる)

その2
取敢えず Dim txtRange As Object で宣言して、代入後に TypeName(txtRange) で調べる

何かで選択範囲の文字位置が調べられたと思ったのだが....。

[ツリー表示へ]
タイトルRe^5: WebBrowserコントロールとMicrosoft HTML Object Library
記事No12712
投稿日: 2008/07/05(Sat) 12:46
投稿者sayman
返信ありがとうございます。

> 調べ方その1
> Google で createRange をキーに検索してみる(他の人がどのように使っているか調べる)
>
> その2
> 取敢えず Dim txtRange As Object で宣言して、代入後に TypeName(txtRange) で調べる
その2の方法に感動しています。
こんなことができるのですね
ありがとうございました。


いろいろ調べていてこんな方法はどうだろうか
というのがいろいろ出るのですが
(多少強引になりつつあります)

vb6.0からjavascriptの変数の値を取得とかはできるのでしょうか?

たとえば
htmlソースが
<html>
<head>
<script>
function PutData(str){

    var Dstr = str
    alert(Dstr)
}
</script>
</head>
<body>
<span onClick="PutData('<!--&&&COS:1-->あいうえお<!--COE:1-->')">
<!--&&&COS:1-->あいうえお<!--COE-->
</span>


<span onClick="PutData('<!--&&&COS:2-->あいうえお<!--COE:2-->')">
<!--&&&COS:2-->あいうえお<!--COE:2-->
</span>
</body>
</html>
となっていたとすると
WebBrowserコントロールをクリックしたときに
Javascript内のDstr変数の値が取得できたら
クリックされた場所が特定できるのでは
と思ったのですが


> 何かで選択範囲の文字位置が調べられたと思ったのだが....。
それができたらベストなんですが・・・自分でも調べているのですが
全然みつからなくて・・・


※だんだん当初の動作と違ってきた気がします・・・
できないなら他の方法でというのは良いのだと思うのですが
見た目の動作が変わってしまうのは悔しいですね

[ツリー表示へ]
タイトルRe^6: WebBrowserコントロールとMicrosoft HTML Object Library
記事No12713
投稿日: 2008/07/05(Sat) 18:15
投稿者花ちゃん
他にいい方法があるかも知れませんが、選択した文字をそのHTML内に何箇所あるか
調べ(Split 関数等)複数あるなら、txtRange.moveEnd で選択範囲を広げ、一意に
なるようにすれば、あとは、その文字で、Instr 関数等でしらべれば、その最初の
選択した文字の出現位置が特定できます。

[ツリー表示へ]
タイトルRe^7: WebBrowserコントロールとMicrosoft HTML Object Library
記事No12714
投稿日: 2008/07/05(Sat) 22:50
投稿者sayman
返信ありがとうございます。

> 他にいい方法があるかも知れませんが、選択した文字をそのHTML内に何箇所あるか
> 調べ(Split 関数等)複数あるなら、txtRange.moveEnd で選択範囲を広げ、一意に
> なるようにすれば、あとは、その文字で、Instr 関数等でしらべれば、その最初の
> 選択した文字の出現位置が特定できます。

確かにできそうなのですが、処理に時間がかかりそう
(テキストが膨大な場合があり初期で全部サンプルと入っているので)
なのとこの記事を見る前に
JavascriptでクリップボードにコピーしてVBで取得する方法を実装してしまいました。
かなり強引な方法でJavascriptを切ってたらどうするのかという問題点もありますが
以下がソースです

-------------HTML----------------
<html>
<head>
<title>イベント</title>

<script>
function PutData(str){
    var Dstr
    Dstr = document.getElementById('id1').innerHTML;
    clipboardData.setData("Text", Dstr);
}
</script>
</head>

<body>
<span id="id1" onClick="PutData('id1')">
<!--&&&COS:1-->あいうえお<!--COE-->
</span>


<span id="id2" onClick="PutData('id2')">
<!--&&&COS:2-->あいうえお<!--COE:2-->
</span>
</body>
</html>
-----------------------------------------------
---------------------VB側----------------------
Option Explicit
Private WithEvents body As HTMLDocument

Private Function body_onclick() As Boolean
   Debug.Print Clipboard.GetText
End Function

Private Sub Form_Load()
    Me.WebBrowser1.Navigate "C:\test.html"
End Sub

------------------------------------------------
これで何とか・・・ほんとに微妙なところですが
実装出来ました。


あと、WebBrowserコントロールでページを表示するときに、
たまに「実行時エラー -2 fffffffe」
「実行時エラー -6 fffffffa」
「実行時エラー -8 fffffff8」
とかが出るのはしょうがないのでしょうか?
処理が終わる前に別ページに飛ぼうとしたりするとでたりするのもなのでしょうか?

「実行時エラー -2 fffffffe」
はdoeventsだったりon error resume next
だったりを入れて出なくなった?
のですが
「実行時エラー -6 fffffffa」
「実行時エラー -8 fffffff8」
はどう回避すればいいのかわかりません。

早くページの行き来をすると出るみたいなのですが
回避方法はあるのでしょうか?

[ツリー表示へ]
タイトルRe^8: WebBrowserコントロールとMicrosoft HTML Object Library
記事No12723
投稿日: 2008/07/07(Mon) 14:31
投稿者これ
こんにちは。
各TAGにちゃんとIDがセットされているなら
document.parentWindow.event.srcElement.Idで
idが取れます。
で、ClickイベントよりSelectStartの方が都合がいいかな?と思い

Dim srcId As String    'イベント発生ID
Private Function body_onSelectStart() As Boolean
    srcId = body.parentWindow.event.srcElement.Id
    body_onSelectStart = True
End Function
これでローカル変数にidが入るから
HTML側でクリップボードに送らなくてもいいのでは?
複数のTAGにまたがって選択されると 最初しか入りませんが・・・

あと、エラーの詳細は調べてませんが
Navigateした後は ReadyState が READYSTATE_COMPLETE に
なっているのを確認してから 中身を使うようにしたほうが吉かと。

[ツリー表示へ]
タイトルRe^9: WebBrowserコントロールとMicrosoft HTML Object Library
記事No12733
投稿日: 2008/07/08(Tue) 12:01
投稿者sayman
返信ありがとうございます

> こんにちは。
> 各TAGにちゃんとIDがセットされているなら
> document.parentWindow.event.srcElement.Idで
> idが取れます。
> で、ClickイベントよりSelectStartの方が都合がいいかな?と思い
>
> Dim srcId As String    'イベント発生ID
> Private Function body_onSelectStart() As Boolean
>     srcId = body.parentWindow.event.srcElement.Id
>     body_onSelectStart = True
> End Function
> これでローカル変数にidが入るから
> HTML側でクリップボードに送らなくてもいいのでは?
> 複数のTAGにまたがって選択されると 最初しか入りませんが・・・
なるほど、idさえ取れれば場所はわかるのでこれでいけそうですね。
さっそく試してみます。

> あと、エラーの詳細は調べてませんが
> Navigateした後は ReadyState が READYSTATE_COMPLETE に
> なっているのを確認してから 中身を使うようにしたほうが吉かと。
ありがとうございます。
なんとかエラー回避できました


あれだけ悩んでいたのに、やってみると案外簡単な処理でできたりしますよね。

[ツリー表示へ]
タイトル追加:WebBrowserコントロールでスクロールするとエラー
記事No12736
投稿日: 2008/07/08(Tue) 20:44
投稿者sayman
追加質問になってしまい申し訳ないですが

やはりエラーが直りません

WebBrowserコントロールにスクロールが付いているのですが
スクロールを触るとエラーがでます。
もしくは、WebBrowserコントロール事態をクリック時に発生します

Navigateしたときに下記の処理だけでは不十分なのでしょうか?

WebBrowser.Navigate "test.html"
Do While WebBrowser.Busy
    DoEvents
Loop
Do While WebBrowser.Document.ReadyState <> "complete"
    DoEvents
Loop

エラー内容は
実行時エラー -4 (fffffffc)
です。

エラー事態は出たりでなかったりします。

原因がわからずに困っています

なにか御存じの方がいましたらよろしくお願いします

[ツリー表示へ]
タイトルRe: 追加:WebBrowserコントロールでスクロールするとエラー
記事No12738
投稿日: 2008/07/08(Tue) 22:46
投稿者魔界の仮面弁士
> Navigateしたときに下記の処理だけでは不十分なのでしょうか?

プロパティの変化を、ループで何度も何度も問い合わせる手法は避けてください。

替わりに、読みこみ完了時に呼ばれる「DocumentComplete イベント」で
document の処理を始めるようにした方が安全かと思います。


なお、frameset を組んでいるページの場合、それぞれの子フレームに対しても
読みこみ完了の通知が発生する点には注意が必要です。

http://support.microsoft.com/kb/180366/ja
http://croissant3.blog66.fc2.com/blog-entry-51.html

[ツリー表示へ]
タイトル【解決】追加:WebBrowserコントロールでスクロールするとエラー
記事No12752
投稿日: 2008/07/11(Fri) 20:44
投稿者sayman
返信ありがとうございます

> プロパティの変化を、ループで何度も何度も問い合わせる手法は避けてください。
>
> 替わりに、読みこみ完了時に呼ばれる「DocumentComplete イベント」で
> document の処理を始めるようにした方が安全かと思います。
ご指摘ありがとうございます。
ご指摘していただいたように組みかえました。
しかし、まだ、たまーにエラーが出ます。
出たりでなかったりするので、訳が分かりません。
まだ、いろいろと試してみます。

当初の目的は達成できたので、解決とさせていただきます。

皆様ご親切にしていただきありがとうございました。
またわからないこと、もしくは自分が分かることでお役にたてることがあれば
投稿させて頂きます

それでは、ありがとうございました。

[ツリー表示へ]