WebBrowserの<Title>の取得について

タグの編集
投稿者 ebifurai55  (社会人) 投稿日時 2009/5/29 09:54:07
です。

現在WebBrowserを使っていて、あるページのタイトルを取得したいのですが、できません。
明日仕事なので詳しい内容はかけないのですが、VB6でこの様な事は可能でしょうか?
WebbrowserコンポーネントはVB6では標準のコントロールではないのでヘルプも見つかりません。
どこかリファレンスが載ってるページはないでしょうか?

よろしくお願いします。

それと普通のアプリケーションにあるようなボタンに絵を表示して、マウスオーバーでハイライト、
押下で凹む。といったツールバーは作るのにはどうしたら良いのでしょうか?自前で作らないといけない
のでしょうか?

VB初心者なのですいません。
それでは失礼します。
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2009/5/29 12:28:27
> あるページのタイトルを取得したいのですが、できません。
Private Sub WebBrowser1_TitleChange(ByVal Text As String)
    Me.Caption = Text
End Sub



> ヘルプも見つかりません。
> どこかリファレンスが載ってるページはないでしょうか?

WebBrowser コントロールの日本語版ヘルプファイルは、Webrowse.hlp です。
(今となっては、入手困難かも)

ですが、情報が十数年間更新されていないので、Platform SDK もしくは
オンライン版の MSDN ライブラリを見た方が良いでしょう。和訳されていないのが難点ですが。
http://msdn.microsoft.com/en-us/library/aa752043.aspx


> マウスオーバーでハイライト、押下で凹む。
> といったツールバーは作るのにはどうしたら良いのでしょうか?
VB6 付属の ツール バー (Toolbar) コントロール [MSCOMCTL.OCX] をフォームに貼り付け、
『プロパティ ページ』ダイアログで、ボタンの追加/画像の割り当てができます。
必要に応じて、Style プロパティも設定しておくとよいでしょう。

あるいは、Coolbar コントロール や SoftButton コントロールを使う手法もあります。
これらは、Visual Basic の「オーナーズ エリア」というMicrosoft 上のサイトから入手できました。
ただし、2001 年を過ぎた頃から、オーナーズ エリアも閉鎖されてしまいましたが…。
http://www.int21.co.jp/pcdn/vb/vb5/pcdn_msdnol.html
投稿者 ebifurai55  (社会人) 投稿日時 2009/5/31 12:59:58
返信ありがとうございます。仕事が一段落ついたので返信を。

WebBrowserのTitle取得できました。イベントプロシージャーにあったとは盲点でした。
てっきりメソッドにあると思っていたのですが・・・・。お蔭様でTitleをLabelに出せました。
この場を借りてお礼を申し上げます。


また、追加の書き込みで非常に丁寧なご回答を貰ったのですが、

>VB6 付属の ツール バー (Toolbar) コントロール [MSCOMCTL.OCX] をフォームに貼り付け、
>『プロパティ ページ』ダイアログで、ボタンの追加/画像の割り当てができます。
>必要に応じて、Style プロパティも設定しておくとよいでしょう。

私が作ろうとしているのは、プログラムと同じパスにあるindex.htmlを読み込んで
それ単体で動くプログラムなのです><
OCXってスタティックリンクできませんよね?
Coolbar コントロール や SoftButton コントロールがそれに該当するといいんですが、、、、
とりあえず調べてみます。

ありがとうございました。
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2009/6/1 00:39:15
> OCXってスタティックリンクできませんよね?
VB はもともと、そういう物なのです。別に OCX に限った話ではありません。
MSVBVM60.DLL や VB6JP.DLL だってスタティックではありませんし、
何より、今回使おうとしている WebBrowser も外部コンポーネントですよね。

WebBrowser は VB6 の一部では無いため、たとえば、IEのバージョンによって
イベント等が変化したりもしますし、IE 未インストールの Win95 上で動かそうとすれば、
OLE の更新と IE のインストールを行わない限り、今回の VB6 アプリは動かないでしょう。

もしもスタティックリンクを求めるのであれば、別の開発言語を使う事を検討してください。
投稿者 (削除されました)  () 投稿日時 2009/6/9 08:02:11
(削除されました)
投稿者 ebifurai55  (社会人) 投稿日時 2009/6/9 16:45:52
すいませんあれから続けてプログラミングをしているのですが、

・リンクをクリックしたらwavを鳴らす
・リンクをクリックしてそれがjpg,gif,png画像ファイルだったら別なウィンドウを発生させる

と言った使い方はできないでしょうか?
やりたい事はCD-Rで使えるIEのブラウザを作りたいのですが、前述でも書いた通り、OCXを
使うと独立して使えないので四苦八苦しています。
どのタイミングでVB6SP2ランタイムはインストールされるのでしょうか~?

よろしくお願いします。
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2009/6/9 19:27:27
> ・リンクをクリックしたらwavを鳴らす
wav ファイルを鳴らす方法については、Visual Basic 中学校で既に紹介されていますね。
http://homepage1.nifty.com/rucio/main/Samples/s_mm1.htm

WebBrowser に表示された HTML ドキュメントのクリックは、onclick イベントで取得できます。
http://msdn.microsoft.com/en-us/library/ms536913.aspx
http://support.microsoft.com/kb/246247/ja

上記では document オブジェクトの onclick をとらえていますが、A オブジェクトの場合にも応用できるはずです。

なお、クリック以外あるいは A タグ以外のページ遷移にも対応させたければ、BeforeNavigate2 イベントを利用できます。
http://msdn.microsoft.com/en-us/library/aa768326.aspx


> ・リンクをクリックしてそれがjpg,gif,png画像ファイルだったら別なウィンドウを発生させる
少々面倒ですが、こんな手順で実装できるかと思います。

 (1) BeforeNavigate2 イベントで URL を拾う。

 (2) ServerXMLHttpRequest オブジェクトで、その URL をバックグラウンドでリクエスト。

 (3) 返却された結果が画像かどうかを調べる。
  → Content-Type ヘッダで判断するか、実際に受け取ったバイナリの内容から調査。

 (4) 画像では無い場合、そのまま BeforeNavigate2 イベントを Exit Sub する。

 (5) 画像だった場合、WebBrowser を貼った別フォームを New で生成し、空ページを表示。
  → Navigate "about:blank" させた後、読み込み完了まで待つ。

 (6) 自ウィンドウで開かれてしまうのを防ぐため、BeforeNavigate2 イベントの
  Cancel 引数に True を代入しておく。

 (7) (5) の WebBrowser の Document プロパティを、IPersistStreamInit 型の変数に Set する。
  → IPersistStreamInit は、下記の OLELIB.TLB を参照設定すると使えます。
   http://www.mvps.org/emorcillo/en/code/vb6/index.shtml

 (8) (7) の変数を通じて、IPersistStreamInit の Load メソッドを呼び出し、
  その Load メソッド引数に、(2) の ServerXMLHttpRequest の responseStream プロパティを渡す。

 (9) 最後に、(5) で生成したフォームを Show メソッドで表示させて完成。
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2009/6/9 22:25:15
別の実装パターンを思いついたので。


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)
    If pDisp.Document Is Nothing Then
        Exit Sub
    End If
    
    ' この画像判定メソッドは、自力で実装する必要があります。 
    If Not IsPicture(URL, Flags, TargetFrameName, PostData, Headers) Then
        Exit Sub
    End If
    
    ' A タグの場合、target="_blank" の属性を指定する。 
    Dim element As Object
    Set element = pDisp.Document.activeElement
    If element.tagName = "A" And element.Target <> "_blank" Then
        element.Target = "_blank"
        WebBrowser1.PutProperty "targetAnchor", Array(element)
        
        '一度キャンセルしてから、タイマー経由で呼びなおす。 
        Cancel = True
        Timer1.Interval = 55
        Timer1.Enabled = True
    End If
End Sub

Private Sub Timer1_Timer()
    Timer1.Enabled = False
    Dim v As Variant
    v = WebBrowser1.GetProperty("targetAnchor")
    WebBrowser1.PutProperty "target", Empty
    If IsArray(v) Then
        ' A タグをクリックする。 
        v(0).Click
        Erase v
    End If
End Sub

Private Sub WebBrowser1_NewWindow2(ppDisp As Object, Cancel As Boolean)
    ' 新たな別ウィンドウとして、Form2 上の WebBrowser を指定 
    Dim f As Form2
    Set f = New Form2
    f.WebBrowser1.RegisterAsBrowser = True
    Set ppDisp = f.WebBrowser1.Object
    f.Show
End Sub
投稿者 ebifurai55  (社会人) 投稿日時 2009/6/14 07:19:32
魔界の仮面弁士さん

お疲れ様です。

すごく詳細な記事を書いてもらい大変感激です。今まで見ていたのですが、
あまりにも過大な情報だったのでいままでレスしませんでした。

しかし、実際にコードを見ても何の事かわかりません。判るところだけ、

webbrowser1.docmentと
webbrowser1.A
というオブジェクトがあるのでしょうか?私は<A Herf>のリンクが押されれば
良いと思っているのですが、JavascriptやFlashのリンクに対応させるならば
BeforeNavigate2を使うという事なのでしょうか?

ちなみにDocumentのOnClickイベントだとページをどこでも押すたびに
メッセージボックスが流れるので想定した仕様に合っていません。

また、これから記事を読むのですが、判らない事だらけで多分また質問します。
そのときはどうかよろしくお願いします。
投稿者 ebifurai55  (社会人) 投稿日時 2009/6/14 09:01:59
先程のコードを自分でやってみた結果、一先ずできました。
ところが、3つほど判らない事が・・・

IsPictureとは何ですか?
画像判別の通常のリンクと画像のリンクの分岐でしょうか?

Aタグの_blank固定は何故?
普通にクリックされたら音がなりリンク先にナビゲートして欲しいです。ここはセレクト文にしたいです。


タイマーイベントを設定するのは何故?リンク先に行くのをすぐに
行かず、周期的にリンクのクリックを判定するため?


また画像判定は時間がかかりそうなので、辞めておきます。
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2009/6/15 12:29:57
> あまりにも過大な情報だった
過大…でしたかね。ごめんなさい。

# 思いつく範囲で、できるかぎり単純な方法を模索したつもりだったのですが…。


> webbrowser1.docmentと
> webbrowser1.A
> というオブジェクトがあるのでしょうか?
実際、そのようなコードを書いてもエラーになってしまいますよね。

WebBrowser.Document から返される「document オブジェクト」は、
HTML を JavaScript から制御するときに使う document オブジェクトと同一です。

(WebBrowser.Document を扱う際には、DHTML の操作方法がそのまま使えますので、、
「DHTML」に関する基礎知識を身につけておくと、役に立ちますよ)


そして A オブジェクトは、<A> タグを表すオブジェクトです。

目的のタグを取得する方法は幾通りもありますが、たとえば、
getElementsByTagName を使って、目的のタグを得る方法があります。

Dim doc As MSHTML.HTMLDocument
Set doc = WebBrowser1.Document

Dim tags As MSHTML.IHTMLElementCollection
Set tags = doc.getElementsByTagName("A")   '<A>タグの一覧を取得 

If tags.length > 0 Then   '<A>タグが見つかった場合 
    Dim a As MSHTML.HTMLAnchorElement
    Set a = tags(0)       '最初の(0番目の)<A>タグを取得する 
    Debug.Print a.outerHTML    '確認用 
End If


このコードを実行する場合には、先に紹介した
>> http://support.microsoft.com/kb/246247/ja
に書かれているように、参照設定に『Microsoft HTML Object Library』を
加えておいてください。(参照設定せずに、As Object な変数で受けても呼べますが、
慣れないうちは、参照設定を行った方が分かりやすいかと思います。)


> 私は<A Herf>のリンクが押されれば良いと思っているのですが、
その場合、リンクを押すのは誰でしょうか?

ユーザーが押すのであれば、プログラム側からは特に何もする必要はありませんが、
プログラムから自動的に、リンクを押したことにしたいのであれば、
 (1) 複数ある A タグのうち、どれを対象にするのかを決める。
 (2) 対象となる A オブジェクトの click メソッドを呼び出す。
といった手順になるかと思います。


> JavascriptやFlashのリンクに対応させるならば
> BeforeNavigate2を使うという事なのでしょうか?

BeforeNavigate2 は、ページが遷移する直前に発生するイベントです。
これを使えば、どの URL にジャンプしようとしているのかを把握できます。


> ちなみにDocumentのOnClickイベントだとページをどこでも押すたびに
> メッセージボックスが流れるので想定した仕様に合っていません。
Document.OnClick 内で、「今押されたのがリンクかどうか」を調べるという
実装手法もあるにはありますが、先の回答にて
>>> 上記では document オブジェクトの onclick をとらえていますが、A オブジェクトの場合にも応用できるはずです。
と書いたように、「(document ではなく)A の onclick イベント」を使うこともできます。

A の onclick イベントを拾う場合には、イベント変数宣言を
Private WithEvents doc As HTMLDocument
Private WithEvents a As HTMLAnchorElement
のようにし、この変数 a に、操作対象の A オブジェクトを Set すれば OK です。


ただし、取得対象の A タグが複数あった場合には、onclick を拾う方法だと
管理が大変だと思います。なので、BeforeNavigate2 を使った方法の方が楽でしょう。


> JavascriptやFlashのリンクに対応させるならば
ちなみに、<A> タグは「HTML」の一部であり、これは DHTML で制御できる範囲ですが、
<OBJECT> タグなどで埋め込まれた ActiveX コンテンツ内の要素は、アドインによって
処理されています。そのため、DHTML からは直接制御できません。

Flash 内のリンクであれば、Flash Player 経由での操作となりますし、
PDF 内のリンクであれば、Adobe Reader 経由での操作となりますし、
自作の ActiveX Document であれば、そのコンポーネント経由での操作となります。

そして、これらのコンテンツ内のリンクをプログラムから制御できるかどうかは
それぞれの ActiveX コンポーネントによって異なります。


Option Explicit

Private Sub Form_Load()
    WebBrowser1.Navigate "http://www.adobe.com/jp/products/flashplayer/"
End Sub

Private Sub Command1_Click()
    Dim doc As MSHTML.HTMLDocument
    Set doc = WebBrowser1.Document
    
    Dim obj As MSHTML.HTMLObjectElement
    Set obj = doc.getElementById("flashplayer-marquee")
    Debug.Print obj.outerHTML
    Debug.Print TypeName(obj.object)

    'ここから先は、Flash のコンポーネントに対する操作 

    '下記の変数宣言のために、[Flash10b.ocx] を参照設定する必要があります 
    'Dim swf As ShockwaveFlashObjects.ShockwaveFlash 
    'Set swf = obj.object 
    'Debug.Print swf.IsPlaying()     '再生中か否か 
    'Debug.Print swf.TotalFrames     '動画の総フレーム数 
    
End Sub
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2009/6/15 13:02:14
> IsPictureとは何ですか?
コメント文にも書きましたが、「リンク先が画像かどうかを判定するメソッド」を想定しています。

> 画像判別の通常のリンクと画像のリンクの分岐でしょうか?
画像以外がクリックされた時には、通常のリンク動作を行うために即座に Exit Sub し、
画像がクリックされた場合には、今回の目的である
>>> ・リンクをクリックしてそれがjpg,gif,png画像ファイルだったら別なウィンドウを発生させる
の動作のため、「別ウィンドウ」を開くための target="_blank" を追加するための判定です。

これは、先の投稿における
>> (3) 返却された結果が画像かどうかを調べる。
>>  → Content-Type ヘッダで判断するか、実際に受け取ったバイナリの内容から調査。
に相当する判定処理です。


しかし、画像の判別は意外と面倒です。

たとえば URL の末尾が .jpg だったからといって、相手が JPEG 画像とは限りませんよね。
それが画像を返すかどうかは、実際にダウンロードしてみるまで分からないわけです。

簡易的な方法としては、先に書いた「Content-Type ヘッダで判断」が楽ですが、
Content-Type ヘッダの値が必ずしも信頼できるわけではありません。サーバーから
実際に返されたデータを見て、それが jpg/gif/png のバイナリであるかどうかを
判断した方が確実だと思います。


いずれにせよ、クリックする前には、リンク先が画像であるかどうかを
確実に調べることはできません。実際にダウンロードしてみる必要がありますので、
>> (2) ServerXMLHttpRequest オブジェクトで、その URL をバックグラウンドでリクエスト。
といった対処が必要になってくるでしょう。


参考までに、Content-Type を得る方法を記述しておきます。
参照設定に [Microsoft XML, vX.X]を加えておいてください。

Public Function IsPicture(ByVal URL As StringAs Boolean
    'Content-Type法 
    Dim req As MSXML2.IServerXMLHTTPRequest
    Set req = New MSXML2.ServerXMLHTTP
    req.open "HEAD", URL, False
    req.send

    Dim contentType As String
    contentType = req.getResponseHeader("Content-Type")
    If contentType Like "image/*" Then
        IsPicture = True
    Else
        IsPicture = False
    End If
End Function



> Aタグの_blank固定は何故?
固定ではありません。画像のときのみ、別ウィンドウ表示のために _blank となりますが、
それ以外ではtarget は変化させません。

> 普通にクリックされたら音がなりリンク先にナビゲートして欲しいです。
「普通」と「普通ではない」場合とのクリックの違いが、どのような物であるのか曖昧ですが、
先のコードでも、画像なら、リンク先の画像に別ウィンドウでナビゲートしますし、
画像以外なら、同じウィンドウ(もしくは、元のHTML で指定されたウィンドウ)に、
ナビゲートされますよ。

なお、音を鳴らす処理はご自身で組み込んでみてください。


> ここはセレクト文にしたいです。
どうぞ。


> タイマーイベントを設定するのは何故?リンク先に行くのをすぐに
> 行かず、周期的にリンクのクリックを判定するため?
処理をワンテンポ遅らせるための遅延処理です。

メッセージ処理の関係上、イベント処理中にページ遷移されると都合が悪いため、
実際のページ遷移が、イベント処理が終わった後(Exit Sub/End Sub後)に行われるよう、
一呼吸おいてから Click させています。

先のサンプルにおいては、55ミリ秒後にタイマーを稼働させ、その Timer イベント内で、
Click を呼び出しています。また、タイマーによる遅延呼び出しは一回だけで良いので、
タイマー周期的に呼ばれてしまうことが無いよう、Timer が発生するとすぐに、
Enabled = False でタイマーを停止させています。
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2009/6/15 13:31:51
>> ・リンクをクリックしてそれがjpg,gif,png画像ファイルだったら別なウィンドウを発生させる
> 参考までに、Content-Type を得る方法を記述しておきます。

今度は、画像のバイナリから判定する場合の実装例です。
先頭の数バイトだけを見て画像判定を行っています。

Public Function IsPicture(ByVal URL As StringAs Boolean
    '画像ヘッダ判定 
    Dim req As MSXML2.IServerXMLHTTPRequest
    Set req = New MSXML2.ServerXMLHTTP
    req.open "GET", URL, False
    req.setRequestHeader "Range""bytes=0-7"   '(可能であれば)先頭8バイトだけをダウンロード 
    req.send

    Dim img() As Byte
    img = req.responseBody  

    IsPicture = False

    If UBound(img) >= 1 Then
        If img(0) = &HFF And img(1) = &HD8 Then
            IsPicture = True        'JPEG 
            Exit Function
        End If
    End If

    If UBound(img) >= 3 Then
        If img(0) = &H89 And StrConv(MidB(img, 2, 3), vbUnicode) = "PNG" Then
            IsPicture = True        'PNG 
            Exit Function
        End If
    End If

    If UBound(img) >= 5 Then
        If StrConv(LeftB(img, 6), vbUnicode) Like "GIF8[79]a" Then
            IsPicture = True        'GIF 
            Exit Function
        End If
    End If
End Function
投稿者 ebifurai55  (社会人) 投稿日時 2009/6/17 16:08:33
魔界の仮面弁士さん。ありがとうございます。

仕事の方が忙しいのでまだ全部チェックしてませんが、内容がわかり次第また返信します。
それではー
投稿者 ebifurai55  (社会人) 投稿日時 2009/6/19 05:42:01
返信ありがとうございます。
ActivXのコントロールの仕方やファイルのヘッダの確認方法まで書いてくださり、
大変ためになりました。が、しかし、問題が生じました。

普通のAタグも新しいウィンドウ(_blank)で開いてしまうのですが、ご提示して頂いた
コードを見ると

    ' A タグの場合、target="_blank" の属性を指定する。  
    Dim element As Object
    Set element = pDisp.Document.activeElement
    If element.tagName = "A" And element.Target <> "_blank" Then
        element.Target = "_blank"
        WebBrowser1.PutProperty "targetAnchor", Array(element)


は”Aかつ_blankじゃなかったら_blankを指定する”になっている様な気がしますが、
いかがでしょうか?PutPropertyの値はURLをその様に書き換える様に見えますが・
この指定だと通常のウィンドウを開かないリンクも_blank指定になって新しいウィンドウが
開いてしまう事になってしまう様な気がします。前述に変わるコードを考えたいのですが、
1,2日待ってもらえないでしょうか?返信は必ずします。もしかしたら解決策が見つかって
この記事も削除されるかもしれません。

それでは失礼します。
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2009/6/19 07:10:05
> Aかつ_blankじゃなかったら_blankを指定する”になっている様な気がしますが、
その通りです。そしてその前に、画像判定のメソッドが置かれているため、これは
「画像のリンクは、すべて別ウィンドウで開く」という動作を行う事になります。


> この指定だと通常のウィンドウを開かないリンクも_blank指定になって新しいウィンドウが
> 開いてしまう事になってしまう様な気がします。
あれ?? 質問内容は、(jpg,gif,png画像へのリンクのときに)「別なウィンドウを発生させる」ことでしたよね?

>>>・リンクをクリックしてそれがjpg,gif,png画像ファイルだったら別なウィンドウを発生させる
投稿者 ebifurai55  (社会人) 投稿日時 2009/6/19 10:32:24
> Aかつ_blankじゃなかったら_blankを指定する”になっている様な気がしますが、
>その通りです。そしてその前に、画像判定のメソッドが置かれているため、これは
>「画像のリンクは、すべて別ウィンドウで開く」という動作を行う事になります。
pDispだとその様な指定ができるのですね。ちなみに私が使っているのはなのですが、
その辺確認いただけないでしょうか?
>>>・リンクをクリックしてそれがjpg,gif,png画像ファイルだったら別なウィンドウを発生させる 
こういうのもあるわけでして・・・
>>・リンクをクリックしたらwavを鳴らす

リンクを普通にクリックしたら音声が鳴ってそのページに遷移して
、かつそれが画像だったら別ウィンドウに・・・という意味合いだったのですが、
言葉足らずだったようですね。申し訳ありません。


通常のリンクのクリックは自分でコードを書いてないので、
魔界の仮面弁士さんの2009/06/09 13:25:15 の書込みのソースを追加すると
、Aタグ全て新しいウィンドウで開いてしまいます。

結局、編集を続けて
続けてみて以下の様なコードが自分の仕様になりました。
拝見していただけると幸いです。※文字数を超えてしまったので省略して書きます。
Private Declare Function GetPrivateProfileString Lib "kernel32" Alias "GetPrivateProfileStringA" (ByVal lpApplicationName As StringByVal lpKeyName As Any, ByVal lpDefault As StringByVal lpReturnedString As StringByVal nSize As LongByVal lpFileName As StringAs Long
Private Declare Function PlaySound Lib "winmm.dll" Alias "PlaySoundA" (ByVal lpszName As StringByVal hModule As LongByVal dwFlags As LongAs Long
Private Const SND_ASYNC = &H1
<INI読み込み省略>
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)
    If pDisp.Document Is Nothing Then
        Exit Sub
    End If
    
'    If Not IsPicture(URL, Flags, TargetFrameName, PostData, Headers) Then 
'        Exit Sub 
'    End If 
    
    Dim element As Object
        On Error Resume Next
        Set element = pDisp.Document.activeElement
            If Err Then
    Exit Sub
    End If

    On Error Resume Next
    If element.tagName = "A" And element.Target = "_blank" Then
        element.Target = "_blank"
    If Err Then
    Exit Sub
    End If
        WebBrowser1.PutProperty "targetAnchor", Array(element)
        Cancel = True
        Timer1.Interval = 55
        Timer1.Enabled = True
    End If
    WebBrowser1.PutProperty "targetAnchor", Array(element)
    Call PlaySound("clicklink.wav", 0, SND_ASYNC)
'            Cancel = False 
'        Timer1.Interval = 55 
'        Timer1.Enabled = True 
End Sub

Private Sub Timer1_Timer()
    Timer1.Enabled = False
    Dim v As Variant
    v = WebBrowser1.GetProperty("targetAnchor")
    WebBrowser1.PutProperty "target", Empty
    If IsArray(v) Then
        v(0).Click
        Erase v
    End If
End Sub

Private Sub WebBrowser1_NewWindow2(ppDisp As Object, Cancel As Boolean)
    Dim f As Form2
    Set f = New Form2
    f.WebBrowser1.RegisterAsBrowser = True
    Set ppDisp = f.WebBrowser1.Object
    f.Show
End Sub
<Form_Load省略>
Private Sub Toolbar1_ButtonClick(ByVal Button As MSComctlLib.Button)
    Select Case Button.KEY
        Case "B_Preview"
            On Error Resume Next
            Call PlaySound("moveback.wav", 0, SND_ASYNC)
            WebBrowser1.GoBack
            If Err Then
                Exit Sub
            End If
            
        Case "B_Forward"
            On Error Resume Next
            Call PlaySound("moveforward.wav", 0, SND_ASYNC)
            WebBrowser1.GoForward
            If Err Then
            Exit Sub
            End If
            
        Case "B_refresh"
            Call PlaySound("refresh.wav", 0, SND_ASYNC)
            WebBrowser1.Refresh
            
        Case "B_HOME"
            On Error Resume Next
            Call PlaySound("returnhome.wav", 0, SND_ASYNC)
            WebBrowser1.Navigate (FileLocation)
            If Err Then
            Exit Sub
            End If
    End Select
End Sub


これでもまだ音が鳴るときと鳴らないとき、進むボタンを押したときBeforeNavigate2の音声が
再生されてしまいます。またいくつかのページでスクリプトエラーになってしまう(youtube等)
問題がありますが、一先ず形にはなったので、今回はこれで〆ます。
まだVB初めて1,2ヶ月なので魔界の仮面弁士さんのおっしゃってる事が7割以上わかりません。
これから勉強する余裕があれば画像の新しいリンクの方も実装してみます。
頭の整理がついてからやりたいと思います。



ありがとうございました。
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2009/6/19 19:05:45
> pDispだとその様な指定ができるのですね。
イベント引数が ByVal pDisp As Object の場合、pDisp と WebBrowser1 は
同じオブジェクトを指します。

イベント引数が (ByRef) pDisp As Object の場合、pDisp と WebBrowser1 は
同じオブジェクトを指すことが出来ますし、別の WebBrowser を Set することもできます。

> ちなみに私が使っているのはなのですが、
はい。それは最初の質問にも書かれていましたね。

> その辺確認いただけないでしょうか?
??「その辺」とは、何を指していますか?

> かつそれが画像だったら別ウィンドウに・・・という意味合いだったのですが、
リンクからブラウザに表示された画像はそのままにして、それとは別のウィンドウで、
同じ画像をもうひとつ開きたいという意味合いでしょうか?

だとしたら、_blank で制御するのではなく、先のいずれかの方法で画像判定を行った後、
IServerXMLHTTPRequest から responseBody ないしは responseStream で画像のバイナリ
(もしくはストリーム)を得た後、それを PictureBox あるいは Form ないしは WebBrowser に
表示するという手順を踏むのが妥当な線かもしれません。


> ' If Not IsPicture(URL, Flags, TargetFrameName, PostData, Headers) Then 
おぉっと。ここをコメントにしてしまっていたのですか。それでは確かに
>> 普通のAタグも新しいウィンドウ(_blank)で開いてしまうのですが、
になってしまっていたでしょうね。


> Sub Toolbar1_ButtonClick
戻る/進むボタンを加えるときには、Sub WebBrowser1_CommandStateChange の
イベントプロシージャも組み込むようにしてください。このイベントの
Command 引数と Enabled 引数を見ることで、ボタンの使用可否を制御できます。
なお、Command は CSC_NAVIGATEFORWARD / CSC_NAVIGATEBACK / CSC_UPDATECOMMANDS の
いずれかの定数値となります。


> 進むボタンを押したときBeforeNavigate2の音声が
> 再生されてしまいます。
進むボタンを押したかどうかを変数に保持しておき、それによって、
 Call PlaySound("clicklink.wav", 0, SND_ASYNC)
の行を実行させるかどうかを切り替えてみては如何でしょう。
投稿者 (削除されました)  () 投稿日時 2009/6/29 17:19:38
(削除されました)
投稿者 ebifurai55  (社会人) 投稿日時 2009/6/29 18:47:20
おはようございます、ebifurai55です。

質問を返します。

>> その辺確認いただけないでしょうか?
>??「その辺」とは、何を指していますか?

その辺とは仮面弁士さんもVB6もVBを使っているか?
です。バージョンが違ってるとまずいですよね・・・

>> ' If Not IsPicture(URL, Flags, TargetFrameName, PostData, Headers) Then 
>おぉっと。ここをコメントにしてしまっていたのですか。それでは確かに
>>> 普通のAタグも新しいウィンドウ(_blank)で開いてしまうのですが、
>になってしまっていたでしょうね。
これなんですが、引数の数が足りてないような気がします。
JPG,GIF,PNGの判定ファンクションで
>Public Function IsPicture(ByVal URL As String) As Boolean
となってますが、
ByValとは何でしょうか?、これが先に判らない事で、また
URLが引数でブーリアン値を設定しているように見えますが、
上のIf Not ~だと複数の引数が設定されてますよね?
If Not ~をコメント解除するとエラーになってしまいます。これも上に
書いたVBのバージョン違いなのではないか?と思ったしだいです。
また推測で書きますが、If Not ~はIsPictureがTrueじゃなかったら
BeforeNavigate2をExit subをするという事でよろしいでしょうか?
つまり画像じゃなかったらBeforeNavigate2を出て、
画像だったらTarget=_blankを指定して、声クリックも判定させる。
でもそうすると、通常のリンクで声クリックが出せないような気が
するのですが、この処理の流れは合っているのでしょうか?
VB歴が少ないので処理の流れがわかりません。すいません。
僕の環境だと、Timer1_timerにCall PlaySoundを指定すると音が鳴らず、
BeforeNavigate2に置くと音が鳴ります。


>> Sub Toolbar1_ButtonClick
>戻る/進むボタンを加えるときには、Sub WebBrowser1_CommandStateChange の
>イベントプロシージャも組み込むようにしてください。このイベントの
>Command 引数と Enabled 引数を見ることで、ボタンの使用可否を制御できます。
>なお、Command は CSC_NAVIGATEFORWARD / CSC_NAVIGATEBACK / CSC_UPDATECOMMANDS の
>いずれかの定数値となります。

やってみた事はないのですが、
そこまで必要じゃないのですが、検討しておきます。

>
>> 進むボタンを押したときBeforeNavigate2の音声が
>> 再生されてしまいます。
>進むボタンを押したかどうかを変数に保持しておき、それによって、
> Call PlaySound("clicklink.wav", 0, SND_ASYNC)
>の行を実行させるかどうかを切り替えてみては如何でしょう。 

先ほどテストしてみた限り、ちょっとタイミングが遅れたり、聞こえなかったり
するのですが、しばらくすると聞こえるようになるので良しとします。


また、このトピック段々タイトルと話しが違ってきている様なので
必要ならば新しくトピックを立てます。質問したい事はたくさんあります。
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2009/6/29 20:07:10
>>> その辺確認いただけないでしょうか?
>>??「その辺」とは、何を指していますか?
> その辺とは仮面弁士さんもVB6もVBを使っているか?
> です。バージョンが違ってるとまずいですよね・・・
大丈夫です。見ての通り、もちろん VB6 として回答していますよ。

VB6 と VB.NET では、構文がいろいろと異なります。
もしも私が VB.NET で検証したコードを回答していたのだとすれば、
>> Private Sub Command1_Click()
というイベント構文にはなりませんし、
>> Set req = New MSXML2.ServerXMLHTTP
のように「Set ステートメント」も登場しません。
これらが登場している時点で、先のコードは  の物であると言えます。


> これなんですが、引数の数が足りてないような気がします。
(中略)
> 上のIf Not ~だと複数の引数が設定されてますよね?
すみません、混乱させてしまったようですね。

[2009/06/15 4:02:14]や[2009/06/15 4:31:51]で記載した例では、実装を単純化して
 If Not IsPicture(URL) Then
の構文で使う事を想定したコードにしています。
もし、対象フレームやリクエストボディなども必要なページの場合、
 If Not IsPicture(URL, Flags, TargetFrameName, PostData, Headers) Then
で呼ぶために、
 Public Function IsPicture(ByVal URL As VariantByVal Flags As VariantByVal TargetFrameName As VariantByVal PostData As VariantByVal Headers As VariantAs Boolean
といった実装が必要になるかも知れません。しかし殆どの場合は、URL のみで足りるかと思います。


> ByValとは何でしょうか?
このサイト(Visual Basic 中学校)の Visual Basic 6.0 初級講座『第17回 関数2』でも
少し解説されていますが、ByVal とは「値渡し」のためのキーワードです。
これと対になるのが ByRef「参照渡し」です。

ByVal/ByRef キーワードを省略した場合、VB6 では ByRef 扱いとなりますが、
カプセル化という観点から言えば、特に理由が無い限りは、ByVal を使う方が望ましいです。

'ByVal と ByRef の動作の違いについて 
Option Explicit

Sub Test1(ByRef x As String)
    x = "123"
End Sub

Sub Test2(ByVal y As String)
    y = "123"
End Sub

Private Sub Command1_Click()
    Dim v1 As Variant, v2 As Variant
    Dim s1 As String, s2 As String

    'Test1 v1    'コンパイルエラー[ByRef 引数の型が一致しません。] 
    'Debug.Print "v1="; v1 

    Test2 v2
    Debug.Print "v2=["; v2; "]"   'ByVal の時は、引数が書き変わらない事が保証される。 

    Test1 s1
    Debug.Print "s1=["; s1; "]"   'ByRef だと、プロシージャによって値が書き換えられる。 

    Test2 s2
    Debug.Print "s2=["; s2; "]"   'ByVal の時は、引数が書き変わらない事が保証される。 
End Sub


発展情報
http://support.microsoft.com/kb/161308/ja



> また推測で書きますが、If Not ~はIsPictureがTrueじゃなかったら
> BeforeNavigate2をExit subをするという事でよろしいでしょうか?
その通りです。


> つまり画像じゃなかったらBeforeNavigate2を出て、
> 画像だったらTarget=_blankを指定して、声クリックも判定させる。
声クリックという表現が初めて出てきましたが、これは
 [2009/06/09 7:45:52]『リンクをクリックしたらwavを鳴らす』
 [2009/06/19 1:32:24]『クリックしたら音声が鳴って』
の事でしょうか。

だとしたら、wav の再生処理については
 [2009/06/15 4:02:14]『なお、音を鳴らす処理はご自身で組み込んでみてください。』
と書きましたように、私のサンプルにはその処理を含めていません。


> でもそうすると、通常のリンクで声クリックが出せないような気が
> するのですが、この処理の流れは合っているのでしょうか?
画像の時のみ鳴らしたいのか、画像以外の時にも鳴らしたいのかによっても
組み込み方が変わるので、私のコードでは特に言及していませんでした。
ebifurai55 さんにとって都合の良い位置に組み込んでみてください。

ちなみにコントロール パネルの[サウンドとオーディオ デバイス]のプロパティを使うと、
IE の標準ナビゲーション サウンドを変更することができます。再生する wav ファイルがが
固定的であるならば、VB6 で組み込まずとも、この設定を今回の目的に利用できるかも知れません。

もしもこの設定をプログラムから制御する場合には、レジストリの
 HKEY_CURRENT_USER\AppEvents\Schemes\Apps
を操作することになります。また、PlaySound API に SND_ALIAS を指定することで、
これらのシステム サウンドを呼び出す事も出来ます。


> 僕の環境だと、Timer1_timerにCall PlaySoundを指定すると音が鳴らず、
> BeforeNavigate2に置くと音が鳴ります。
まず、Timer1_Timer のプロシージャが実行されているかどうかを確認してください。

もし、Timer イベントは発生しているのに、PlaySound が鳴らないのだとしたら、
その時点で「既に何らかのサウンドが再生されていないか」を確認してみてください。

PlaySound は複数の音を同時に呼び出せないため、たとえば上記のシステム サウンドが
再生している最中に呼び出した場合、後から呼び出した方は無視されてしまいます。


> また、このトピック段々タイトルと話しが違ってきている様なので
細かい事ですが、「話しが」→「話が」だと思います。

> 必要ならば新しくトピックを立てます。質問したい事はたくさんあります。
> 仮面弁士さんが付き合ってくれるならば・・・・ですが。 
内容によっては、私以外の方の回答も来るかも知れませんが、
私も可能な範囲でお付き合いしますよ。
投稿者 ebifurai55  (社会人) 投稿日時 2009/7/5 09:18:15
久しぶりです。質問です。


[code]Public Function IsPicture(ByVal URL As String) As Boolean[/code]

[code]If Not IsPicture(URL) Then[/code]

の二つを実装してみたのですが、
Pubulic Function IsPicture
のところでエラーが出て黄色い線がハイライトされ、
req As MSXML2.IServerXMLHTTPRequest
の所が選択状態になってしまいます。

果たしてこの状況は一体なんでしょうか?
WindowsXPSP3ですけど、足らないコンポーネントがあるんでしょうか?

ご教示お願いします。

投稿者 魔界の仮面弁士  (社会人) 投稿日時 2009/7/6 02:48:53
追加の『参照設定』が必要となります。

先の投稿より引用:(2009/06/15 4:02:14)
> 参考までに、Content-Type を得る方法を記述しておきます。
> 参照設定に [Microsoft XML, vX.X]を加えておいてください。