■99868 |
Re[9]: IHTMLDocumentオブジェクトの取得に関して |
□投稿者/ 魔界の仮面弁士 -(2022/06/13(Mon) 20:19:43)
| 以下、蛇足情報。
解決済みチェックは付けたままにしておきます。
■No99864 (はなみ さん) に返信
>> IHTMLDocument 〜 IHTMLDocument8 の各インターフェイスの定義は、こちらを参照してみてください。
>> https://docs.microsoft.com/ja-jp/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa752574%28v%3dvs.85%29
>
> 先日ご紹介いただいた docs.microsoft.comのページを見ていた際に、
> IHTMLDocument8のみが IUnknownから継承されていて、他は IDispatchから継承と
> 書かれており、IDispatchは IUnknownから継承とあったので
すべての COM インターフェイスは IUnknown を継承しています。
IHTMLDocument8 もそうですし、IDispatch や IDispatchEx もそうです。
《OAIdl.h》より抜粋
MIDL_INTERFACE("00020400-0000-0000-C000-000000000046")
IDispatch : public IUnknown
《DispEx.h》より抜粋
MIDL_INTERFACE("A6EF9860-C720-11d0-9337-00A0C90DCAA9")
IDispatchEx : public IDispatch
> 「逆なのでは?」と疑問に感じました。
いずれもデュアルインターフェイスですね。
IHTMLDocument8 もまた、他と同様にディスパッチインターフェイスを持ちます。
宣言を見る限り、IHTMLDocument2 だけは IHTMLDocument から引き継がれるようですが。
ちなみにマネージの System.Windows.Forms.HtmlDocument クラスも、
内部では COM の IHTMLDocument2 インターフェイスを利用しています。
《MsHTML.h》もしくは《Mshtmlc.h》より抜粋
MIDL_INTERFACE("626FC520-A41E-11cf-A731-00A0C9082637")
IHTMLDocument : public IDispatch
MIDL_INTERFACE("332c4425-26cb-11d0-b483-00c04fd90119")
IHTMLDocument2 : public IHTMLDocument
MIDL_INTERFACE("3050f485-98b5-11cf-bb82-00aa00bdce0b")
IHTMLDocument3 : public IDispatch
MIDL_INTERFACE("3050f69a-98b5-11cf-bb82-00aa00bdce0b")
IHTMLDocument4 : public IDispatch
MIDL_INTERFACE("3050f80c-98b5-11cf-bb82-00aa00bdce0b")
IHTMLDocument5 : public IDispatch
MIDL_INTERFACE("30510417-98b5-11cf-bb82-00aa00bdce0b")
IHTMLDocument6 : public IDispatch
MIDL_INTERFACE("305104b8-98b5-11cf-bb82-00aa00bdce0b")
IHTMLDocument7 : public IDispatch
MIDL_INTERFACE("305107d0-98b5-11cf-bb82-00aa00bdce0b")
IHTMLDocument8 : public IDispatch
完全に蛇足ですが、 VB.NET の CallByName は DispId 呼び出しに対応しています。
Dim doc As Object = GetHTMLDocument(hWnd_IE_Server)
'Option Strict Off なら、オブジェクトのメンバーに実行時にアクセスできる
Debug.WriteLine( doc.location.href )
'Option Strict Off では、IHTMLLocation の Default Method を呼び出すために、このような書き方ができる
Debug.WriteLine( CObj(doc.location)() )
'Option Strict On でも、CallByName を使えばディスパッチインターフェイスで呼び出せる
Debug.WriteLine(CallByName(CallByName(doc, "location", CallType.Get), "href", CallType.Get))
Debug.WriteLine(CallByName(CallByName(doc, "location", CallType.Get), "", CallType.Get))
'DispId で呼び出すこともできる
Debug.WriteLine(CallByName(CallByName(doc, "[DispID=1026]", CallType.Get), "[DispId=0]", CallType.Get))
そして上記の DispID は《MsHtmdid.h》にて得ることができます。
#define DISPID_NORMAL_FIRST 1000
#define DISPID_OMDOCUMENT DISPID_NORMAL_FIRST
#define DISPID_IHTMLDOCUMENT2_LOCATION DISPID_OMDOCUMENT+26
#define DISPID_IHTMLLOCATION_HREF DISPID_VALUE
> これです! このイメージでした!
> …ただ StrPtr(IID_IHTMLDocumentX) と指定している部分を AddrOfPinnedObjectで
> 取得したアドレスに置き換えようとしましたが、
その対応が間違っていると思います。
VBA における VarStr と StrPtr の違いは御存知なのですよね。
LPCSTR と LPCOLESTR の違いは把握されていますか?
http://hanatyan.sakura.ne.jp/logbbs1/wforum.cgi?mode=allread&no=1785&page=0#1805
TextOutA API などの LPCSTR であれば、VBA からは ByVal As String で渡せば良いですが、
CLSIDFromString が求める LPCOLESTR の場合は、StrPtr を使って渡すことになります。
さて、.NET から呼び出す場合はどうかというと…属性指定するのが一般的です。
http://www5b.biglobe.ne.jp/~yone-ken/VBNET/special/sp06_GetPrivateProfileString.html
https://docs.microsoft.com/en-us/dotnet/framework/interop/marshalling-strings
https://docs.microsoft.com/en-us/dotnet/framework/interop/default-marshalling-for-strings
https://docs.microsoft.com/en-us/dotnet/standard/native-interop/best-practices#string-parameters
というわけで、CLSIDFromString の VB.NET からの宣言例はこんな感じになります。
<DllImport("ole32.dll")>
Private Function CLSIDFromString(<MarshalAs(UnmanagedType.BStr)> ByVal lpsz As String, <Out> ByRef guid As Guid) As Integer
' 実際には Guid.ParseExact / Guid.Parse メソッドを使った方が手っ取り早い
End Function
どうしても明示的に BSTR を IntPtr として扱う必要がある場合は、
GCHandle クラスではなく Marshal クラスを使ってみてください。
BSTR の場合はこのあたりです。
Marshal.StringToBSTR メソッド
Marshal.PtrToStringBSTR メソッド
Marshal.FreeBSTR メソッド
C 形式の文字列の場合はこのあたりです。
Marshal.StringToHGlobalAnsi/Auto/Uni メソッド
Marshal.StringToCoTaskMemAnsi/Auto/Uni/UTF8 メソッド
Marshal.PtrToStringAnsi/Auto/Uni/UTF8 メソッド
Marshal.FreeHGlobal メソッド
Marshal.FreeCoTaskMem メソッド
注).NET Framework は UTF8 系メソッドをサポートしていません。 |
|