2011-12-19 16 views
9

Tengo algunos problemas con el manejo de errores de JavaScript en WebBrowser en Delphi 2010.¿Cómo hago que TWebBrowser siga ejecutando JavaScript después de un error?

Estoy usando WebBrowser con propiedad habilitada silenciosa. Parece correcto, pero hay un problema en los sitios con scripts defectuosos: parece que parte del script después de que el error no se ejecuta. Los resultados de algunos guiones difieren ligeramente de IE.

¿Tiene alguna idea de cómo se puede resolver este problema?

Respuesta

12

Puede usar el IOleCommandTarget y en su método IOleCommandTarget.Exec tomar el comando OLECMDID_SHOWSCRIPTERROR.

En el siguiente ejemplo, he usado la clase interpuesta así que si coloca este código en su unidad, solo aquellos navegadores web en el formulario o aquellos creados en esta unidad dinámicamente obtendrán este comportamiento.

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

Este método también suprime todas las ventanas emergentes de JavaScript. – TipTop

+0

¿Tiene alguna página de muestra que se comporte de esta manera? Vea el artículo ['this'] (http://support.microsoft.com/kb/261003). ¿Estás seguro de que no hay ningún error antes de que aparezca la ventana emergente? En mi humilde opinión, debería suprimir solo los errores, pero puedo echar un vistazo ... – TLama

+0

@TipTop, en general, el código no tiene nada que ver con las ventanas emergentes que se invocan con JavaScript. Si tiene un problema con el código, creo que el valor de retorno predeterminado no debería ser S_OK, sino OLECMDERR_E_NOTSUPPORTED. – stanleyxu2005

4

Aquí están mis recomendaciones de implementación.

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;" Al menos esta es una pista valiosa. Leí msdn muchas veces, estoy de acuerdo con usted, que estos valores de retorno * deberían * ser S_OK. Pero de acuerdo con mi experiencia en la aplicación real, tengo que configurarlos en OLECMDERR_E_NOTSUPPORTED, de lo contrario, se comporta de forma inesperada. – stanleyxu2005

+0

Revise su código y asegúrese de saber lo que dice antes de manifestarse para * comparar mi publicación con otra, tengo algo valioso. * ¿Dónde encontró que el valor 'vaOut' es booleano? ¿Cómo sabe que el resultado del comando ejecutado actualmente será booleano y significará Verdadero para ejecutarse? A continuación, está mezclando los valores de los resultados, ya lo he dicho, el 'IOleCommandTarget :: QueryStatus' no tiene el valor del resultado' OLECMDERR_E_NOTSUPPORTED' ... A continuación, ¿por qué está probando el controlador de eventos para el puntero al puntero? Simplemente pruebe 'si Assigned (OnNotifyScriptError) then OnNotifyScriptError (...)' – TLama

+0

... observe cómo se escribe VCL, es la mejor fuente que puede obtener. La línea con 'IsEqualGUID' no la obtengo en absoluto. Mi conclusión personal, si te tomaste esto en serio, entonces intenta leer la documentación con más cuidado (si la obtuviste de otra documentación no oficial, entonces déjalo). Me alegro si alguien revisa mi publicación y me dice su opinión, pero no de esta manera. Si solo necesita revisar su propio código, entonces puede dejarme un comentario y podría ayudarlo, por ejemplo. a través de correo electrónico. – TLama

Cuestiones relacionadas