WebBrowserコントロールからHTMLソースを保存する方法について、魔界の仮面弁士様が以前回答されています。
http://madia.world.coocan.jp/cgi-bin/VBBBS/wwwlng.cgi?print+200312/03120094.txt
http://madia.world.coocan.jp/cgi-bin/VBBBS2/wwwlng.cgi?print+200312/03120090.txt
http://madia.world.coocan.jp/cgi-bin/VBBBS/wwwlng.cgi?print+200310/03100017.txt
このうち、最後の記事に書かれているコードを元にして実装したのですが、
persistFile.saveの実行後、WebBrowserオブジェクト側のURLプロパティの値が、保存先のディレクトリに変化してしまいます。
(http://hoge/index.html というページをC:\に保存すると、URLの値がftp://c:\index.html などとなる)
アドレスバーの表示は変わりませんが、オブジェクトのプロパティ、および相対パスを判断するための内部の値が変わっているようです。
すいませんが、対策方法についてご教示いただければと思います。
> persistFile.saveの実行後、WebBrowserオブジェクト側のURLプロパティの値が、保存先のディレクトリに変化してしまいます。
WebBrowser コントロールに URL プロパティはありません。
IHTMLDocument2 インターフェイスの Url プロパティの間違いではありませんか?
代案として、LocationURL プロパティを使ってみるのは如何でしょうか。
Debug.Print "URL="; WebBrowser1.Document.URL
Debug.Print "LocationURL="; WebBrowser1.LocationURL
> URLの値がftp://c:\index.html などとなる
http プロトコルから、ftp プロトコルに書き換えられたのですか?
file プロトコルではなく?
ご回答、ありがとうございます。
>IHTMLDocument2 インターフェイスの Url プロパティの間違いではありませんか?
ご指摘の通り、IHTMLDocument2インターフェイスのUrlプロパティでした。(正確には、それを実装したHTMLDocumentのUrlプロパティ)
勘違いすいません。
>代案として、LocationURL プロパティを使ってみるのは如何でしょうか。
この場合、ボタンで操作している箇所(Javascriptを呼んでいる箇所)では、ファイル検索の基準パスが変更されているので、適切な.jsを見つけられずエラーになるかと思います。
よって、どうしてもURLを変更せず処理する必要があるかと思います。
(HTMLDocument.Urlを直接書き換えるやり方では、リロードが発生するためダメでした)
>http プロトコルから、ftp プロトコルに書き換えられたのですか?
こちらもご指摘の通り、fileプロトコルとなります。勘違い、申し訳ありません。
> どうしてもURLを変更せず処理する必要があるかと思います。
手元の環境では、IPersistFile.Save に True / False のいずれを
渡すかによって、元の URL のままとなるのか、ローカルパスになるのかが
変化しました。
ただし先の DispCallFunc API を使う方法では無く、
下記のタイプライブラリを用いて実行した場合の話です。
http://www.mvps.org/emorcillo/en/code/vb6/index.shtml
Option Explicit
Private Sub Command1_Click()
WebBrowser1.Navigate2 "http://www.yahoo.co.jp/"
End Sub
Private Sub Command2_Click()
Dim psf As olelib.IPersistFile
Set psf = WebBrowser1.Document
psf.Save "C:\Folder1\Sample2.html", False
End Sub
Private Sub Command3_Click()
MsgBox WebBrowser1.Document.URL
End Sub
5
]
> DispCallFunc API を使う方法では無く、
DispCallFunc関数は引数の型(VARTYPE)にうるさい。
IPersistFile::Saveメソッドの第2引数の型はBOOL。
VB系のBooleanとは異なりますね。
False → 0&
> IPersistFile::Saveメソッドの第2引数の型はBOOL。
> VB系のBooleanとは異なりますね。
なので、あの当時は
http://madia.world.coocan.jp/cgi-bin/VBBBS/wwwlng.cgi?print+200310/03100017.txt
の中で、BOOL値を渡すために
>> lngBool = IIf(fRemember, 1&, 0&)
という変換を行っていたのですが、それだけでは駄目だったようです。
…もっとも今見直してみると、API 宣言も
Private Declare Function DispCallFunc Lib "oleaut32" _
(ByVal pvInstance As Long, _
ByVal oVft As Long, _
ByVal CallConv As Integer, _
ByVal vtReturn As Integer, _
ByVal cActuals As Long, _
ByRef prgvt As Integer, _
ByRef prgpvarg As Long, _
ByRef pvargResult As Variant _
) As Long
になっていたので、少なくとも第3引数の型が違っているような気もします。
CALLCONV は、v1_enum な列挙型らしいので、32bit整数型では無いかな…。
それで解決するかどうかは別として。
リンク先を確認して参りましたが、ParamArrayに変数が渡されると(値に対して)
VARIANTに「VT_BYREF」フラグが付きます。
つまり参照渡しの動作になりますね。
DispCallFunc関数はそれを「アドレス」として認識するのでしょうね。
その逆のパターンも存在しまして、VT_BYREFが必要なのに消える場合もあります。
そんな事で私は自作Invoke_関数のような処理は好んでませんが。
ご提示クラスPersistFileで修正するのであれば、Saveメソッド中の
lngBoolが「値」として渡るように調整すればいいと思います。
例えば、lngBool → (lngBool)
> その逆のパターンも存在しまして、VT_BYREFが必要なのに消える場合もあります。
失礼。これはParamArrayとは関係ありません。
ご回答、ありがとうございます。
Abyss様ご指摘の通り、SaveメソッドからInvoke_を呼んでいる部分を、以下のように直すことで期待通りの動作となりました。(まさか、ParamArrayの内部仕様起因とは・・・・)
ありがとうございました。
hResult = Invoke_(mlpPersistFile, comIPersistFile_Save, _
VarPtr(bytFileName(0)), (lngBool))
魔界の仮面弁士様ご指摘の通り、DispCallFuncの宣言もやや疑わしいですが、元々の質問事項は解決しておりますので解決にマークさせていただきます。
こちらもありがとうございました。
ツイート | ![]() |