2011-12-19 25 views
9

Tôi đang gặp một số vấn đề với xử lý lỗi javascript trong WebBrowser trên Delphi 2010.Làm cách nào để TWebBrowser tiếp tục chạy JavaScript sau một lỗi?

Tôi đang sử dụng WebBrowser với thuộc tính im lặng được bật. Có vẻ OK, nhưng có một vấn đề trên các trang web có các script lỗi: có vẻ như một phần của tập lệnh sau khi lỗi không thực thi. Kết quả của một số kịch bản hơi khác với IE.

Bạn có biết cách giải quyết vấn đề này không?

Trả lời

12

Bạn có thể sử dụng IOleCommandTarget và trong phương thức IOleCommandTarget.Exec của chúng tôi bắt lệnh OLECMDID_SHOWSCRIPTERROR.

Trong ví dụ sau tôi đã sử dụng lớp xen kẽ nên nếu bạn đặt mã này vào đơn vị của mình, chỉ những trình duyệt web trên biểu mẫu hoặc các trình duyệt được tạo trong đơn vị này sẽ có hành vi này.

uses 
    SHDocVw, ActiveX; 

type 
    TWebBrowser = class(SHDocVw.TWebBrowser, IOleCommandTarget) 
    private 
    function QueryStatus(CmdGroup: PGUID; cCmds: Cardinal; prgCmds: POleCmd; 
     CmdText: POleCmdText): HRESULT; stdcall; 
    function Exec(CmdGroup: PGUID; nCmdID, nCmdexecopt: DWORD; 
     const vaIn: OleVariant; var vaOut: OleVariant): HRESULT; stdcall; 
    end; 

implementation 

function TWebBrowser.QueryStatus(CmdGroup: PGUID; cCmds: Cardinal; 
    prgCmds: POleCmd; CmdText: POleCmdText): HRESULT; stdcall; 
begin 
    Result := S_OK; 
end; 

function TWebBrowser.Exec(CmdGroup: PGUID; nCmdID, nCmdexecopt: DWORD; 
    const vaIn: OleVariant; var vaOut: OleVariant): HRESULT; stdcall; 
begin 
    // presume that all commands can be executed; for list of available commands 
    // see SHDocVw.pas unit, using this event you can suppress or create custom 
    // events for more than just script error dialogs, there are commands like 
    // undo, redo, refresh, open, save, print etc. etc. 
    // be careful, because not all command results are meaningful, like the one 
    // with script error message boxes, I would expect that if you return S_OK, 
    // the error dialog will be displayed, but it's vice-versa 
    Result := S_OK; 

    // there's a script error in the currently executed script, so 
    if nCmdID = OLECMDID_SHOWSCRIPTERROR then 
    begin 
    // if you return S_FALSE, the script error dialog is shown 
    Result := S_FALSE; 
    // if you return S_OK, the script error dialog is suppressed 
    Result := S_OK; 
    end; 
end; 
+0

Phương pháp này cũng ngăn chặn tất cả các cửa sổ bật lên javascript. – TipTop

+0

Bạn có trang mẫu nào hoạt động theo cách này không? Xem bài viết ['this'] (http://support.microsoft.com/kb/261003). Bạn có chắc chắn không có lỗi trước khi cửa sổ bật lên được hiển thị không? IMHO nó sẽ chỉ chặn các lỗi, nhưng tôi có thể xem xét ... – TLama

+0

@TipTop, nói chung, mã không có gì để làm với các cửa sổ bật lên được gọi JavaScript. Nếu bạn gặp sự cố với mã, tôi nghĩ giá trị trả lại mặc định không được là S_OK, nhưng OLECMDERR_E_NOTSUPPORTED. – stanleyxu2005

4

Dưới đây là khuyến nghị thực hiện của tôi.

uses 
    SHDocVw, ActiveX; 

type 
    TWebBrowser = class(SHDocVw.TWebBrowser, IOleCommandTarget) 
    private 
    function QueryStatus(CmdGroup: PGUID; cCmds: Cardinal; prgCmds: POleCmd; 
     CmdText: POleCmdText): HRESULT; stdcall; 
    function Exec(CmdGroup: PGUID; nCmdID, nCmdexecopt: DWORD; 
     const vaIn: OleVariant; var vaOut: OleVariant): HRESULT; stdcall; 
    end; 

implementation 

function TWebBrowser.QueryStatus(CmdGroup: PGUID; cCmds: Cardinal; 
    prgCmds: POleCmd; CmdText: POleCmdText): HRESULT; stdcall; 
begin 
    // MSDN notes that a command target must implement this function; E_NOTIMPL is not a 
    // valid return value. Be careful to return S_OK, because we notice that context menu 
    // of Web page "Add to Favorites..." becomes disabled. Another MSDN document shows an 
    // example with default return value OLECMDERR_E_NOTSUPPORTED. 
    // http://msdn.microsoft.com/en-us/library/bb165923(v=vs.80).aspx 
    Result := OLECMDERR_E_NOTSUPPORTED; 
end; 

function TWebBrowser.Exec(CmdGroup: PGUID; nCmdID, nCmdexecopt: DWORD; 
    const vaIn: OleVariant; var vaOut: OleVariant): HRESULT; stdcall; 
var 
    ShowDialog, InterpretScript: Boolean; 
begin 
    if CmdGroup = nil then 
    begin 
    Result := OLECMDERR_E_UNKNOWNGROUP; 
    Exit; 
    end; 

    // MSDN notes that a command target must implement this function; E_NOTIMPL is not a 
    // valid return value. Be careful to return S_OK, because we notice some unhandled 
    // commands behave unexpected with S_OK. We assumed that a return value 
    // OLECMDERR_E_NOTSUPPORTED means to use the default behavior. 
    Result := OLECMDERR_E_NOTSUPPORTED; 

    if IsEqualGUID(CmdGroup^, CGID_DocHostCommandHandler) then 
    begin 
    // there's a script error in the currently executed script, so 
    if nCmdID = OLECMDID_SHOWSCRIPTERROR then 
    begin 
     ShowDialog := True; 
     InterpretScript := False; 

     // Implements an event if you want, so that your application is able to choose the way of handling script errors at runtime. 
     if Assigned(OnNotifyScriptError) then 
     OnNotifyScriptError(Self, ShowDialog, InterpretScript); 

     if ShowDialog then 
     Result := S_FALSE 
     else 
     Result := S_OK; 
     vaOut := InterpretScript; // Without setting the variable to true, further script execution will be cancelled. 
    end; 
    end; 
end; 
+0

"vaOut: = InterpretScript;" Ít nhất đây là một gợi ý có giá trị. Tôi đọc msdn nhiều lần, tôi đồng ý với bạn, rằng những giá trị trả về * * sẽ là S_OK. Nhưng theo kinh nghiệm của tôi trong ứng dụng thực tế, tôi phải đặt chúng thành OLECMDERR_E_NOTSUPPORTED, nếu không nó hoạt động bất ngờ. – stanleyxu2005

+0

Vui lòng xem lại mã của bạn và đảm bảo bạn biết những gì bạn nói trước khi bạn biểu thị * so sánh bài đăng của tôi với một bài đăng khác, tôi có nội dung có giá trị. * Bạn đã tìm thấy giá trị 'vaOut' là boolean ở đâu? Làm thế nào để bạn biết kết quả của lệnh hiện đang được thực hiện sẽ là boolean và sẽ có nghĩa là True để thực thi? Tiếp theo, bạn đang trộn các giá trị kết quả, tôi đã nói với bạn trước đây, 'IOleCommandTarget :: QueryStatus' không có giá trị kết quả' OLECMDERR_E_NOTSUPPORTED' ... Tiếp theo, tại sao bạn thử nghiệm trình xử lý sự kiện cho con trỏ tới con trỏ? Chỉ cần kiểm tra 'if Assigned (OnNotifyScriptError) thì OnNotifyScriptError (...)' – TLama

+0

... hãy xem VCL được viết như thế nào, đó là nguồn tốt nhất bạn có thể nhận được. Các dòng với 'IsEqualGUID' tôi không nhận được ở tất cả. Kết luận cá nhân của tôi, nếu bạn đã nghiêm túc này sau đó cố gắng đọc các tài liệu cẩn thận hơn (nếu bạn đã nhận nó từ một tài liệu không chính thức, sau đó rời khỏi nó). Tôi rất vui nếu một người nào đó xem lại bài đăng của tôi và cho tôi biết ý kiến ​​của riêng mình, nhưng không phải theo cách này. Nếu bạn chỉ cần xem lại mã của riêng mình, thì bạn có thể để lại nhận xét và tôi có thể giúp bạn với nhận xét, ví dụ: qua email. – TLama

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