我正在尝试使用.NET WebBrowser类型的Close事件,这似乎不是开箱即用的。 (编辑:在浏览器中运行的脚本中发出window.close()
调用时会发出此事件。)
我见过的一个解决方案是extend the WebBrowser
class and override
the WndProc
method。
我的扩展程序代码如下:
type internal ExtendedBrowser () = class
inherit System.Windows.Forms.WebBrowser()
let WM_PARENTNOTIFY : int = 0x0210
let WM_DESTROY : int = 0x0002
let closed : Event<unit> = new Event<unit>()
do ()
[<System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")>]
override this.WndProc (msg : Message byref) =
match msg.Msg with
| wm when wm = WM_PARENTNOTIFY ->
if (not base.DesignMode) && (msg.WParam.ToInt32() = WM_DESTROY)
then closed.Trigger()
base.DefWndProc(ref msg)
| _ ->
base.WndProc(ref msg)
member this.Closed = closed.Publish
end
这最终导致在访问该类型的实例时抛出异常:
Unhandled Exception: System.Reflection.TargetInvocationException: Unable to get the window handle for the 'ExtendedBrowser' control. Windowless ActiveX controls are not supported. ---> System.ComponentModel.Win32Exception: Error creating window handle.
at System.Windows.Forms.NativeWindow.CreateHandle(CreateParams cp)
at System.Windows.Forms.Control.CreateHandle()
at System.Windows.Forms.Control.get_Handle()
at System.Windows.Forms.WebBrowserBase.DoVerb(Int32 verb)
at System.Windows.Forms.WebBrowserBase.TransitionFromRunningToInPlaceActive()
--- End of inner exception stack trace ---
at System.Windows.Forms.WebBrowserBase.TransitionFromRunningToInPlaceActive()
at System.Windows.Forms.WebBrowserBase.TransitionUpTo(AXState state)
at System.Windows.Forms.WebBrowser.get_AxIWebBrowser2()
at System.Windows.Forms.WebBrowser.PerformNavigate2(Object& URL, Object& flag
s, Object& targetFrameName, Object& postData, Object& headers)
at System.Windows.Forms.WebBrowser.Navigate(String urlString)
at [PRODUCT].Application.WebBrowser..ctor() in C:\[PATH]\WebBrowser.fs:line 107
at Program.Main.main(String[] args) in C:\[PATH]\Program.fs:line 79
Press any key to continue . . .
目前,在调用Navigate("about:blank")
(实例构建后第一次访问)时发生错误。我可以注释掉WndProc
覆盖,并且工作正常(除了错过关闭事件)。
有人说你必须put the security attribute on the WndProc
override所以我这样做了,并没有解决问题。
有人说你可以disable the DEP,但是我试过了,并没有让我免除EXE。
正在浏览器的包装器(也称为WebBrowser)中创建扩展的实例,并且正在我的main
中创建一个实例,该实例在[STAThread]中运行(也似乎被要求)。
有谁知道会出现什么问题?
(我真正想要的是获取近距离事件通知的一种方式,所以如果有人知道另一条路线,我很乐意听到它。)
答案 0 :(得分:1)
如果您希望在WebBrowser
控件关闭时收到通知,您可以创建普通WebBrowser
类的实例,并为HandleDestroyed
事件添加事件处理程序 - 当包含WebBrowser
实例的表单/控件关闭时,它会被触发。
如果这不起作用,您可以尝试将Parent
属性转换为Form
并挂钩FormClosing
事件;请参阅此处以获取两种技术的示例:HandleDestroyed event in userControl
答案 1 :(得分:1)
我找到了一个帖子,其他人有同样的problem overriding the WndProc method in F#,其解决方案对我有用;工作代码如下:
type ExtendedWebBrowser () = class
inherit System.Windows.Forms.WebBrowser()
let WM_PARENTNOTIFY : int = 0x0210
let WM_DESTROY : int = 0x0002
let closed : Event<unit> = new Event<unit>()
do ()
override this.WndProc (msg : Message byref) =
match msg.Msg with
| wm when wm = WM_PARENTNOTIFY ->
if (not base.DesignMode) && (msg.WParam.ToInt32() = WM_DESTROY)
then closed.Trigger()
base.DefWndProc(&msg)
| _ ->
base.WndProc(&msg)
member this.Closed = closed.Publish
end
似乎F#对待ref
的方式与C#略有不同:在Parameters and Arguments in F#上做一些阅读 - 请参阅按引用传递部分 - 似乎{ {1}}调用复制其参数并将该副本用作参照单元格的值;所以,我传递的是一个参考单元格,其中包含ref
内容的副本,而不是对原始内容的引用。 address-of运算符(msg
)获取值的地址,这就是&
和DefWndProc
方法的参数所需的内容,而不是将它们包装在{{1}中}第