2013-01-09 45 views
5

Tôi đang cố gắng truy cập vào sự kiện Đóng của loại .NET WebBrowser, điều này dường như không hoạt động. (EDIT: Sự kiện này được phát ra khi cuộc gọi window.close() được phát hành trong một tập lệnh đang chạy trong trình duyệt.)Ngoại lệ được ném khi WndProc bị quá tải

Một giải pháp mà tôi đã xem là extend the WebBrowser class and override the WndProc method.

đang mở rộng của tôi là như sau:

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 

này kết thúc lên làm một ngoại lệ được ném ra khi một thể hiện của các loại được truy cập:

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 . . . 

Hiện nay nó erroring trên một cuộc gọi đến Navigate("about:blank") (quyền truy cập đầu tiên của cá thể sau khi xây dựng). Tôi có thể nhận xét số ghi đè WndProc và mọi thứ hoạt động tốt (bên cạnh việc thiếu sự kiện đóng).

Có người cho biết bạn đã phải put the security attribute on the WndProc override vì vậy tôi đã làm điều đó và nó không khắc phục được sự cố.

Người khác nói bạn có thể disable the DEP, nhưng tôi đã thử và không cho phép tôi miễn EXE.

Một phiên bản của tiện ích đang được tạo trong trình bao bọc cho trình duyệt (còn gọi là Trình duyệt Web) và một phiên bản này đang được tạo trong main, chạy trong [STAThread] (cũng có vẻ là bắt buộc).

Có ai biết điều gì có thể xảy ra không?

(Những gì tôi đang thực sự sau khi là một cách để có được thông báo về sự kiện gần, vì vậy nếu ai đó biết một tuyến đường thay thế để mà tôi muốn được hạnh phúc khi nghe nó.)

Trả lời

0

Tôi tìm thấy một bài đăng mà một người khác đã có cùng một problem overriding the WndProc method in F# và giải pháp có hiệu quả đối với tôi; đang làm việc là như sau:

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 

Dường như F # xử lý ref một chút khác biệt so với C#: Làm một số đọc trên Parameters and Arguments in F# - xem Passing bởi Reference phần - có vẻ như rằng ref bản gọi của nó đối số và sử dụng bản sao đó làm giá trị cho ô tham chiếu; vì vậy, những gì tôi đã vượt qua là một ô tham chiếu chứa một bản sao nội dung của msg thay vì tham chiếu đến bản gốc. Toán tử địa chỉ (&) lấy địa chỉ của giá trị, vì vậy đó là những gì cần thiết cho các đối số cho các phương thức DefWndProcWndProc thay vì gói chúng trong ref s.

1

Nếu bạn muốn trở thành được thông báo khi điều khiển WebBrowser bị đóng, bạn có thể tạo một phiên bản của lớp WebBrowser bình thường và thêm trình xử lý sự kiện vào sự kiện HandleDestroyed - nó được kích hoạt khi biểu mẫu/kiểm soát chứa phiên bản WebBrowser của bạn bị đóng.

Nếu điều đó không hiệu quả, bạn có thể thử truyền thuộc tính Parent tới Form và gắn kết sự kiện FormClosing; xem ở đây để biết ví dụ về cả hai kỹ thuật: HandleDestroyed event in userControl

+0

Đáng buồn thay, biểu mẫu gốc sẽ không đóng khi sự kiện này được phát ra - Tôi đang tìm cách chụp một cuộc gọi trong trình duyệt tới phương thức 'window.close()', sau đó tôi sẽ xóa trình duyệt ví dụ từ biểu mẫu. Tôi sẽ tìm kiếm và xem có điều gì khác trên con đường này có thể được sử dụng hay không; cám ơn vì sự gợi ý! – paul

+0

Không sao cả. Bạn cũng có thể thử phương pháp dựa trên 'Timer' được gợi ý ở đây: [window.close() đóng băng .NET 2.0 WebBrowser Control trong ứng dụng Windows Form] (https://blogs.msdn.com/b/jpsanders/archive/2008/ 04/23/window-close-freezes-net-2-0-webbrowser-control-in-windows-form-application.aspx? Redirected = true). Đó là bài đăng tiếp theo cho phương pháp tiếp cận dựa trên "tiện ích mở rộng" mà bạn đã liên kết trong câu hỏi của mình. –

+0

Tôi đã tìm thấy vấn đề là gì! (Xem câu trả lời của tôi.) - Tôi đã nhìn thấy bài viết về cách tiếp cận dựa trên bộ đếm thời gian nhưng nó đã không xảy ra với tôi để sử dụng nó vì tôi không sử dụng .NET 2.0 và không bị đóng băng. Cảm ơn một lần nữa cho đầu vào của bạn! – paul

Các vấn đề liên quan