2017-02-02 4 views
2

J'utilise TWebBrowser dans DesignMode (Doc.DesignMode: = 'On') pour composer un document HTML. Il n'y a aucun document (fichier HTML sur le disque) chargé dans TWebBrowser. Je crée le document à partir de zéro directement dans TWebBrowser. Le code html sera extrait de TWebBrowser et enregistré en tant que c: /MyProjects/SomeHtmlName.html.Comment afficher les images de chemin relatif dans TWebBrowser?

Le problème est qu'il ne montrera pas les images que j'insère si elles ont un chemin relatif.

Plus exactement, si je coller ce code dans le navigateur Web, il affiche instantanément l'image:

<IMG src="file:///c:/MyProjects/resources/R.PNG"> 

Cependant, si je rentre:

<IMG border=0 src="resources\R.PNG"> 
<IMG border=0 src="resources/R.PNG"> <---- preferred so it will work on Linux 

il affiche un espace réservé d'image au lieu de l'image réelle.

J'ai besoin de chemins relatifs pour que le site fonctionne toujours si je change le chemin racine OU si je le télécharge sur FTP.


procedure TForm1.Button1Click(Sender: TObject); 
begin 
    LoadDummyPage; 
    SetHtmlCode('<img src="resources/test_img.PNG">'); 
    Memo1.Text:= GetHtmlCode; 
end; 



function TForm1.LoadDummyPage: Boolean; 
const FileName: string= 'c:\MyProject\_ONLINE WEB SITE\dummy.html'; 
begin 
    if not Assigned(wbBrowser.Document) 
    then wbBrowser.Navigate('about:blank'); 

    Result := FileExists(FileName); 
    if Result 
    then wbBrowser.Navigate('file://' + FileName) 
    else Caption:= 'file not found'; 
end; 



procedure TForm1.SetHtmlCode(const HTMLCode: string); 
var 
    Doc: Variant; 
begin 
    if not Assigned(wbBrowser.Document) 
    then wbBrowser.Navigate('about:blank'); 

    Doc := wbBrowser.Document; 
    Doc.Write(HTMLCode); 
    Doc.Close; 
    Doc.DesignMode := 'On'; 

    WHILE wbBrowser.ReadyState < READYSTATE_INTERACTIVE 
    DO Application.ProcessMessages; 

    Doc.body.style.fontFamily := 'Arial'; 
    Doc.Close; 
end; 


function TForm1.GetHtmlCode: string;    { Get the HTML code from the browser } 
var 
    Doc: IHTMLDocument2; 
    BodyElement: IHTMLElement; 
begin 
    if Assigned(wbBrowser.Document) and (wbBrowser.Document.QueryInterface(IHTMLDocument2, Doc) = S_OK) then 
    begin 
    BodyElement := Doc.body; 
    if Assigned(BodyElement) then 
     Result := BodyElement.innerHTML; 
    end; 

    if Result > '' 
    then Result := StringReplace(Result, '="about:', '="', [rfReplaceAll, rfIgnoreCase]); { Fix the 'How stop TWebBrowser from adding 'file:///' in front of my links' bug } 
end; 
+0

Cela fonctionne-t-il si le répertoire de travail actuel de l'exécutable est c:/MyProjects /? – mjn42

+0

Le 'hack' que je pourrais utiliser serait de post-traiter le HTML et supprimer le 'fichier: /// c:/MyProjects /' – Ampere

+0

@ mjn42 - non. probablement parce que les images sont dans le dossier 'Ressources'? De plus, je pense que le dossier 'root' de TWebBrowser est le dossier racine par défaut d'Internet Explorer (quel qu'il soit) et non le dossier de l'application. – Ampere

Répondre

4

Vous devez précharger une chaîne/un flux HTML "modèle" valide, y compris la balise BASE où vous définissez le chemin souhaité (avec une barre oblique), par ex. "file:///c:/MyProjects/".

Passez en mode édition, où vos images SRC doivent être relatives, par ex. "resources/R.PNG". Votre dernière édition de HTML ater édité devrait être le body.innerHTML ou body.outerHTML (tout ce dont vous avez besoin). Vous pouvez même prendre toute la source du document (google it).

Enveloppez la source extraite avec le code HTML/Corps SANS la balise BASE et enregistrez-la sur le disque au c:\MyProjects.

mais le code résultant pour IMG SRC est chemin complet!

Rien de ce que vous pouvez faire à ce sujet. c'est ainsi que les DOM représentent le code HTML - ce n'est pas nécessaire le code source HTML. ce comportement n'est pas cohérent. et aussi dépendre de comment vous insérez des images (je n'utilise pas execCommand et ai ma propre boîte de dialogue et insère mon propre code html). Vous devez remplacer manuellement la source extraite "file:///c:/MyProjects/" par une chaîne vide. au moins, c'est comme ça que je le fais.

Modifier: Vous n'avez pas besoin de Navigate() pour un fichier externe. vous pouvez écrire le "template"/"vide" HTML via document.write(HTML).

Essayez ceci:

const 
    HTML_TEMPLATE = '<html><head><base href="file:///%s"></head><body style="font-family:Arial">%s</body></html>'; 

procedure TForm1.LoadHTML(HTMLCode: string); 
var 
    Doc: Variant; 
    HTML, Path: string; 
begin 
    Path := 'D:\Temp\'; 
    HTML := Format(HTML_TEMPLATE, [Path, HTMLCode]); 
    WebBrowser1.Navigate('about:blank'); 
    Doc := WebBrowser1.Document; 
    Doc.Write(HTML); 
    Doc.Close; 
    Doc.DesignMode := 'On'; 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
begin 
    LoadHTML('<b>Hello</b><img SRC="resources/1.png">'); 
end; 

procedure TForm1.Button2Click(Sender: TObject); 
var 
    Doc: IHTMLDocument2; 
begin 
    Doc := WebBrowser1.Document as IHTMLDocument2; 
    if Assigned(Doc) then 
    begin 
    ShowMessage(Doc.body.innerHTML); 
    end; 
end; 

La sortie est pour moi: <B>Hello</B><IMG src="resources/1.png">. Dans certains cas, le srcpeut contenir le chemin d'accès complet. Je ne peux pas être sûr à 100% quand cela arrive. mais vous devez être prêt à faire face à cette situation en remplaçant manuellement le chemin.il n'y a pas de documentation concluante à ce sujet, donc je traite toujours de cette question dans tous les cas.

+0

"Vous devez remplacer manuellement ..." - Mais c'est ce que je fais déjà (voir le commentaire que j'ai mis sous la question) :) Je fournissais le chemin d'image FULL, puis "post-traitement" le code HTML plein à relatif. Et tout cela sans avoir à utiliser le 'BASE' compliqué. Je considérais cela comme un "hack" et j'espérais que TWeBBrowser pourrait utiliser les chemins relatifs pour de vrai :) – Ampere

+2

@DarkPresidentOfAmerica, "espérait que je pourrais faire en sorte que TWeBBrowser utilise les chemins relatifs pour de vrai". mais * fait * quand vous utilisez la BASE! :) le 'innerHTML' est la représentation de la façon dont le DOM a réellement analysé le code source. Je sais que le remplacement est "hacky" mais il n'y a pas grand-chose que vous pouvez faire à ce sujet AFAIK. – kobik

+0

Ensuite, pour faire face à cela, j'utiliserai simplement les chemins complets jusqu'au bout et post-traiterai le code HTML pour le convertir en relatif. – Ampere

0

Je suggère d'utiliser un petit serveur Web intégré comme Internet Direct (Indy) TIdHttpServer, qui est en mesure de servir toutes les requêtes HTTP de manière standard. Cela supprime tous les problèmes potentiels du système de fichiers.

+0

Merci pour la suggestion mais ce hack est plus extrême que le mien :) Pensez aux implications de l'installation d'un serveur web sur un ordinateur. La plupart des programmes antivirus auront quelque chose à commenter :) – Ampere

+0

Liez-le à localhost (127.0.0.1) seulement alors. De nombreux processus ouvrent des ports locaux et AV ne se plaint pas. Ils peuvent se plaindre sur les analyses de port. – mjn42