- PR -

WebBrowserコントロールのカスタマイズ

1
投稿者投稿内容
YAS
ベテラン
会議室デビュー日: 2006/02/15
投稿数: 59
投稿日時: 2006-02-15 00:27
VBレスキュー(花ちゃん)の掲示板で質問させていただいたのですが,
レスがつかず,自力解決もできませんでした。
マルチポストとなりますが,お許しください。

VB2005にてWebBrowserコントロールのカスタマイズに挑戦しています。
まずはキーボードショートカットのカスタマイズをしようと,
http://msdn2.microsoft.com/ja-jp/system.windows.forms.webbrowser.createwebbrowsersitebase.aspx

http://d.hatena.ne.jp/santamarta/searchdiary?word=%2a%5bAxWebBrowser%5d
を参考に以下の用に組んで見たのですが,機能しません。
ヘルプの言うようにしたつもりなのですが...
IDocHostUIHandlerインターフェイスの実装が呼ばれないのです。
ご存じの方がいらっしゃいましたらご教授をお願いいたします。

(Microsoft HTML Object Library(MSHTML)を参照設定)
コード:
Imports System.Runtime.InteropServices

Imports mshtml

Public Class Form1
WithEvents Browser As New ExWebBrowser
Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
Me.Browser.Dock = DockStyle.Fill
Me.Controls.Add(Browser)
Browser.GoHome()
End Sub
End Class

Public Class ExWebBrowser
Inherits WebBrowser

Sub New()
MyBase.New()
End Sub

Protected Overrides Function CreateWebBrowserSiteBase() _
As System.Windows.Forms.WebBrowserSiteBase
Return New ExWebBrowserSite(Me)
End Function

Protected Class ExWebBrowserSite
Inherits WebBrowser.WebBrowserSite
Implements IDocHostUIHandler

Sub New(ByVal host As WebBrowser)
MyBase.New(host)
End Sub

Public Sub EnableModeless(ByVal fEnable As Integer) _
Implements IDocHostUIHandler.EnableModeless

End Sub

Public Function FilterDataObject( _
ByVal pDO As System.Windows.Forms.IDataObject) _
As System.Windows.Forms.IDataObject _
Implements IDocHostUIHandler.FilterDataObject
Return pDO
End Function

Public Function GetDropTarget( _
ByVal pDropTarget As System.Windows.Forms.IDropTarget) _
As System.Windows.Forms.IDropTarget _
Implements IDocHostUIHandler.GetDropTarget
Return pDropTarget
End Function

Public Function GetExternal() As Object _
Implements IDocHostUIHandler.GetExternal
Return Nothing
End Function

Public Sub GetHostInfo(ByRef theHostUIInfo As DOCHOSTUIINFO) _
Implements IDocHostUIHandler.GetHostInfo

End Sub

Public Sub GetOptionKeyPath(ByRef pchKey As String, _
ByVal dw As Integer) Implements IDocHostUIHandler.GetOptionKeyPath

End Sub

Public Sub HideUI() Implements IDocHostUIHandler.HideUI

End Sub

Public Sub OnDocWindowActivate(ByVal fActivate As Integer) _
Implements IDocHostUIHandler.OnDocWindowActivate

End Sub

Public Sub OnFrameWindowActivate(ByVal fActivate As Integer) _
Implements IDocHostUIHandler.OnFrameWindowActivate

End Sub

Public Sub ResizeBorder(ByRef prcBorder As mshtml.tagRECT, _
ByVal pUIWindow As Integer, ByVal fFrameWindow As Integer) _
Implements IDocHostUIHandler.ResizeBorder

End Sub

Public Function ShowContextMenu(ByVal dwID As Integer, _
ByRef ppt As mshtml.tagPOINT, ByVal pcmdtReserved _
As IOleCommandTarget, ByVal pdispReserved As Object) _
As Integer Implements IDocHostUIHandler.ShowContextMenu

End Function

Public Sub ShowUI(ByVal dwID As Integer, _
ByRef pActiveObject As Object, _
ByRef pCommandTarget As IOleCommandTarget, _
ByRef pFrame As Object, ByRef pDoc As Object) _
Implements IDocHostUIHandler.ShowUI

End Sub

Public Function TranslateAccelerator(ByRef lpMsg As tagMSG, _
ByRef pguidCmdGroup As System.Guid, ByVal nCmdID As Integer) _
As Integer Implements IDocHostUIHandler.TranslateAccelerator
Const WM_KEYDOWN As Integer = &H100
Const S_FALSE As Integer = &H1
Const S_OK As Integer = &H0
If lpMsg.message = WM_KEYDOWN Then
If (Control.ModifierKeys And Keys.Control) = Keys.Control Then
Dim keyCode As Byte = CByte(lpMsg.wParam And &HFF)
If keyCode = Keys.N Then
Debug.Print("Ctrl-Nが押された")
Return S_OK
End If
End If
End If
Return S_FALSE
End Function

Public Function TranslateUrl(ByVal dwTranslate As Integer, _
ByVal pchURLIn As Integer) As Integer _
Implements IDocHostUIHandler.TranslateUrl

End Function

Public Sub UpdateUI() Implements IDocHostUIHandler.UpdateUI

End Sub

End Class
End Class

<StructLayout(LayoutKind.Sequential)> _
Public Structure DOCHOSTUIINFO

Public cbSize As Integer
Public dwFlags As Integer
Public dwDoubleClick As Integer
<MarshalAs(UnmanagedType.BStr)> Public pchHostCss As String
<MarshalAs(UnmanagedType.BStr)> Public pchHostNS As String

End Structure

<StructLayout(LayoutKind.Sequential, Pack:=4)> _
Public Structure tagMSG

Public hwnd As IntPtr
Public message As Integer
Public wParam As Integer
Public lParam As Integer
Public time As Integer
Public pt As tagPOINT

End Structure

<ComImport(), _
ComVisible(False), _
Guid("BD3F23C0-D43E-11CF-893B-00AA00BDCE1A"), _
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> _
Public Interface IDocHostUIHandler

<PreserveSig()> Function ShowContextMenu( _
ByVal dwID As Integer, _
ByRef ppt As tagPOINT, _
ByVal pcmdtReserved As IOleCommandTarget, _
<MarshalAs(UnmanagedType.IDispatch)> ByVal pdispReserved As Object _
) As Integer

Sub GetHostInfo(ByRef theHostUIInfo As DOCHOSTUIINFO)

Sub ShowUI(ByVal dwID As Integer, _
ByRef pActiveObject As Object, _
ByRef pCommandTarget As IOleCommandTarget, _
ByRef pFrame As Object, _
ByRef pDoc As Object)

Sub HideUI()
Sub UpdateUI()
Sub EnableModeless(ByVal fEnable As Integer)
Sub OnDocWindowActivate(ByVal fActivate As Integer)
Sub OnFrameWindowActivate(ByVal fActivate As Integer)
Sub ResizeBorder(ByRef prcBorder As tagRECT, _
ByVal pUIWindow As Integer, ByVal fFrameWindow As Integer)

<PreserveSig()> Function TranslateAccelerator( _
ByRef lpMsg As tagMSG, _
ByRef pguidCmdGroup As Guid, _
ByVal nCmdID As Integer _
) As Integer

Sub GetOptionKeyPath(<MarshalAs(UnmanagedType.BStr)> _
ByRef pchKey As String, ByVal dw As Integer)

Function GetDropTarget(ByVal pDropTarget As IDropTarget) As IDropTarget

Function GetExternal() As <MarshalAs(UnmanagedType.IDispatch)> Object

Function TranslateUrl(ByVal dwTranslate As Integer, _
ByVal pchURLIn As Integer) As Integer

Function FilterDataObject(ByVal pDO As IDataObject) As IDataObject

End Interface

<ComImport(), _
ComVisible(False), _
Guid("b722bccb-4e68-101b-a2bc-00aa00404770"), _
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> _
Public Interface IOleCommandTarget

<PreserveSig()> Function QueryStatus( _
ByVal pguidCmdGroup As Guid, _
ByVal cCmds As Integer, _
<MarshalAs(UnmanagedType.LPArray, SizeParamIndex:=1)> _
ByRef prgCmds As OLECMD(), _
ByRef CmdText As OLECMDTEXT _
) As Integer

<PreserveSig()> Function Exec( _
ByRef pguidCmdGroup As Guid, _
ByVal nCmdId As Integer, _
ByVal nCmdExecOpt As Integer, _
ByRef pvaIn As Object, _
ByRef pvaOut As Object _
) As Integer

End Interface

<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)> _
Public Structure OLECMDTEXT

Public cmdtextf As Integer
Public cwActual As Integer
Public cwBuf As Integer
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=100)> Public rgwz As Char

End Structure

<StructLayout(LayoutKind.Sequential)> _
Public Structure OLECMD

Public cmdID As Integer
Public cmdf As Integer

End Structure


  

[ メッセージ編集済み 編集者: YAS 編集日時 2006-02-15 00:30 ]

[ メッセージ編集済み 編集者: YAS 編集日時 2006-02-15 00:32 ]

[ メッセージ編集済み 編集者: YAS 編集日時 2006-02-15 08:33 ]

[ メッセージ編集済み 編集者: YAS 編集日時 2006-02-15 08:33 ]

[ メッセージ編集済み 編集者: YAS 編集日時 2006-02-15 08:36 ]

[ メッセージ編集済み 編集者: YAS 編集日時 2006-02-15 09:01 ]
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-02-15 02:03
引用:

YASさんの書き込み (2006-02-15 00:27) より:

IDocHostUIHandlerインターフェイスの実装が呼ばれないのです。


どうやって確認されたかわかりませんが、
基底クラスの呼び出しがまったくないのって問題になりませんか?

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
YAS
ベテラン
会議室デビュー日: 2006/02/15
投稿数: 59
投稿日時: 2006-02-15 08:48
引用:
基底クラスの呼び出しがまったくないのって問題になりませんか?



申し訳ありません。「基底クラスの呼び出し」ということが何をすることなのか
知識不足で理解できませんでした。

下記のIDocHostUIHandlerのリファレンスによると「Called by MSHTML」とあるのでMSHTMLから必要に応じて呼び出されるのかと思っていました。
http://msdn.microsoft.com/library/default.asp?url=/workshop/browser/hosting/reference/ifaces/idochostuihandler/idochostuihandler.asp

オーバーライドしたCreateWebBrowserSiteBase()はExWebBrowserクラスの
インスタンスを生成したときに呼び出されているのは確認しています。

基底クラスのインターフェイスをオーバーライドするだけでは動作しないのでしょうか?
何か重大な勘違いや,根本的な理解不足があるに違いないのですが,
CreateWebBrowserSiteBaseやWebBrowser.WebBrowserSiteBaseのヘルプを
よく読み,またGoogleでも検索をしたのですが,わかりませんでした。

さらにご助言をいただければありがたいです。よろしくお願いいたします。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-02-15 09:13
引用:

YASさんの書き込み (2006-02-15 08:48) より:

申し訳ありません。「基底クラスの呼び出し」ということが何をすることなのか
知識不足で理解できませんでした。


「実装が呼ばれないのです」と仰ってましたよね。
それを、どうやってご確認されましたか?
ブレークポイントで待ち構えたりしたのですか? (全部?)

Implements IDocHostUIHandler なメソッドが全く呼ばれないのか、
呼ばれた結果、期待通りの動作をしたいのかが判らなかったわけです。
MyBase.xxx な呼び出しが特に記述されていなかったものですから。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
YAS
ベテラン
会議室デビュー日: 2006/02/15
投稿数: 59
投稿日時: 2006-02-15 11:21
じゃんぬねっと様,ご返答ありがとうございます。

実装が呼ばれているかはIDocHostUIHandlerのメソッド全部に
Debug.Print("呼ばれたよ")
を追加してみました。
その結果,イミディエイトウィンドウに"呼ばれたよ"は1度も表示されなかったので,IDocHostUIHandlerのメソッドはMSHTMLから呼ばれていないと考えました。

「基底クラスの呼び出し」については意味を理解できました。ありがとうございました。各メソッドで基底クラスを呼び出していないのは以下の理由のためです。

各メソッドをOverridesでオーバーライドしようとすると
「sub xxx はベースclassのsubをオーバーライドしないため'Overrides'として宣言することはできません。」とIDEに怒られます。
そのためMyBase.xxxのxxxにはIDocHostUIHandlerのメソッドは使えません。
(xxxはNewやDisposeのような共通のメソッドしかIDE上では表示されません。)

私のコードではWebBrowserSiteBaseのメソッドをオーバーライドしたことに
なっていないのだと思うのですが,ではどうしたら基底クラスのメソッドを
オーバーライド出来るのかがわからないのです。


[ メッセージ編集済み 編集者: YAS 編集日時 2006-02-15 11:22 ]
YAS
ベテラン
会議室デビュー日: 2006/02/15
投稿数: 59
投稿日時: 2006-02-16 16:33
IDocHostUIHandlerの実装については未だわかりませんが,別の方法でキーボードショー
トカットをカスタマイズできました。

WebBrowserクラスを継承して,PreProcessMessageメソッドをオーバーライドすることで
解決することが出来ました。
WebBrowserBase.PreProcessMessageメソッドのヘルプに「独自に作成したコードから直
接使用するためのものではありません。」と書かれていたので使ってはいけないんだと
思い,気づくのに時間がかかりました。

以下の様なコードでWebBrowserコントロールのCtrl-NやCtrl-Pを無効にすることができました。

じゃんぬねっと様,ご助言いただきましてありがとうございました。

なお,VBレスキュー(花ちゃん)の掲示板にもマルチポストさせていただきました。

コード:

Public Class Form1

WithEvents Browser As New ExWebBrowser

Private Sub Form1_Load( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs _
) Handles MyBase.Load
Me.Browser.Dock = DockStyle.Fill
Me.Controls.Add(Browser)
Me.Browser.GoHome()
End Sub

End Class

Class ExWebBrowser
Inherits WebBrowser

Public Overrides Function PreProcessMessage( _
ByRef msg As System.Windows.Forms.Message _
) As Boolean
Const WM_KEYDOWN As Integer = &H100
If msg.Msg = WM_KEYDOWN Then
Dim keyCode As Keys = CType(msg.WParam, Keys) And Keys.KeyCode
If My.Computer.Keyboard.CtrlKeyDown Then
Select Case keyCode
Case Keys.N
Debug.Print("Ctrl-Nが押された")
Return True
Case Keys.P
Debug.Print("Ctrl-Pが押された")
Return True
End Select
End If
End If
Return MyBase.PreProcessMessage(msg)
End Function

End Class



[ メッセージ編集済み 編集者: YAS 編集日時 2006-02-16 16:37 ]
1

スキルアップ/キャリアアップ(JOB@IT)