Bonjour,
Voici un petit tutorial expliquant comment
intégrer le navigateur Chromium (Chrome) directement dans les fenêtres Windev, en lieu et place d'Internet Explorer et de l'activeX Shell.Explorer.
Cela est rendu possible par l'utilisation de la librairie CefSharp (pour Chromium Embedded Framework) (
https://github.com/cefsharp/CefSharp) et d'un champ Windev de type .NET 2.0 (WinForm).
Les possibilités sont nombreuses et je ne présente donc ici que les fonctionnalités de base.
1/Fichiers nécessaires
Les sources pour
Chromium en version 45 sont disponibles ici :
https://mon-partage.fr/f/W22nIf8c/.
Il faut copier tous les éléments dans le répertoire de votre exécutable, et dans le répertoire "Exe" de votre projet Windev pour le mode test.
La dll WindevNet a été compilée par moi même pour permettre la récupération du résultat d'appels Javascript.
Les autres dlls sont issues d'un projet
Visual Studio (Community) de test de CefSharp, compilé avec la dernière version des packages disponibles.
Des explications simples pour tester CefSharp avec Visual Studio sont disponibles ici :
http://www.codeproject.com/Articles/...using-CefSharp.
2/Intégration dans Windev
Dans Windev, cliquez sur le menu Atelier/.NET/Utiliser un assemblage .NET dans votre projet.
Dans la fenêtre listant les assemblages disponibles, cliquez sur le bouton "Parcourir" et sélectionnez les dlls
"CefSharp.Core.dll",
"CefSharp.WinForms.dll",
"WDNetHelpers.dll" et
"WindevNet.dll", présentes dans le répertoire "Exe" de votre projet.
Dans la liste des assemblages, sélectionnez aussi l'assemblage
"System.Windows.Forms".
Cliquez sur le bouton de validation pour importer les dlls dans votre projet.
2.1/Ajout du champ .NET 2.0 pour affichage du navigateur
Insérez sur votre fenêtre Windev un champ .NET 2.0 (WinForm)
Dans la description du champ, onglet "Général", sélectionnez la classe
"System.Windows.Forms.Panel".
2.2/Code d'initialisation de la fenêtre
Dans le traitement d'initialisation de la fenêtre qui contient le champ .NET 2.0, ajoutez le code suivant, qui va permettre d'initialiser Cef et d'intercepter les événements du navigateur dans des procédures Windev.
La liste des événements gérés n'est pas exhaustive, mais j'ai souhaité dans un premier temps mettre en place l'interception de ceux qui me paraissaient les plus importants.
L'objet oWDJavascript va permettre d'intercepter l'événement de fin d'exécution asynchrone d'un code Javascript.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
SI PAS Cef.IsInitialized ALORS
Cef.Initialize()
FIN
goBrowser est un ChromiumWebBrowser("http://google.com")
goBrowser.add_AddressChanged(DotNetDélégué(AdressChanged,"EventHandler<CefSharp.AddressChangedEventArgs>"))
goBrowser.add_ConsoleMessage(DotNetDélégué(ConsoleMessage,"EventHandler<CefSharp.ConsoleMessageEventArgs>"))
goBrowser.add_IsBrowserInitializedChanged(DotNetDélégué(IsBrowserInitializedChanged,"EventHandler<CefSharp.IsBrowserInitializedChangedEventArgs>"))
goBrowser.add_FrameLoadStart(DotNetDélégué(FrameLoadStart,"EventHandler<CefSharp.FrameLoadStartEventArgs>"))
goBrowser.add_FrameLoadEnd(DotNetDélégué(FrameLoadEnd,"EventHandler<CefSharp.FrameLoadEndEventArgs>"))
goBrowser.add_LoadError(DotNetDélégué(LoadError,"EventHandler<CefSharp.LoadErrorEventArgs>"))
goBrowser.add_LoadingStateChanged(DotNetDélégué(LoadingStateChanged,"EventHandler<CefSharp.LoadingStateChangedEventArgs>"))
goBrowser.add_StatusMessage(DotNetDélégué(StatusMessage,"EventHandler<CefSharp.StatusMessageEventArgs>"))
goBrowser.add_TitleChanged(DotNetDélégué(TitleChanged,"EventHandler<CefSharp.TitleChangedEventArgs>"))
oWDJavascript est un WindevNet.WDJavascript
oWDJavascript:add_EvaluateJsDone(DotNetDélégué(EvaluateJsDone,"EventHandler<EvaluateJsDoneEventArgs>"))
CAS EXCEPTION:
Erreur(ExceptionInfo(errComplet)) |
2.3/Procédures de gestion des événements
Dans la fenêtre Windev, il faut maintenant créer les procédures correspondantes à celles déclarées dans la fonction DotNetDélégué() de l'étape 2.2 soit :
AdressChanged
1 2 3 4 5 6
|
PROCEDURE AdressChanged(_oBrowser est un ChromiumWebBrowser,_oArgs est CefSharp.AddressChangedEventArgs <utile>)
Trace("------------------------------")
Trace(dbgInfo(dbgTraitement))
Trace(_oBrowser:get_Address()) |
ConsoleMessage
1 2 3 4 5 6 7
|
PROCEDURE ConsoleMessage(_oBrowser est un ChromiumWebBrowser,_oArgs est CefSharp.ConsoleMessageEventArgs <utile>)
Trace("------------------------------")
Trace(dbgInfo(dbgTraitement))
Trace(_oBrowser:get_Address())
Trace(_oArgs.Line+" : "+_oArgs.Message) |
IsBrowserInitializedChanged
1 2 3 4 5 6
|
PROCEDURE IsBrowserInitializedChanged(_oBrowser est un ChromiumWebBrowser,_oArgs est CefSharp.IsBrowserInitializedChangedEventArgs <utile>)
Trace("------------------------------")
Trace(dbgInfo(dbgTraitement))
Trace(_oBrowser:get_Address()) |
FrameLoadStart
1 2 3 4 5 6
|
PROCEDURE FrameLoadStart(_oBrowser est un ChromiumWebBrowser,_oArgs est CefSharp.FrameLoadStartEventArgs <utile>)
Trace("------------------------------")
Trace(dbgInfo(dbgTraitement))
Trace(_oBrowser:get_Address()) |
FrameLoadEnd
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
PROCEDURE FrameLoadEnd(_oBrowser est un ChromiumWebBrowser,_oArgs est CefSharp.FrameLoadEndEventArgs <utile>)
Trace("------------------------------")
Trace(dbgInfo(dbgTraitement))
Trace(_oBrowser:get_Address())
bMainFrame est un booléen
bMainFrame = _oArgs.Frame.IsMain
SI bMainFrame ALORS
Trace("#############################")
FIN
Trace("Main Frame ? : "+bMainFrame)
Trace("Frame Url ? : "+_oArgs.Url) |
LoadError
1 2 3 4 5 6
|
PROCEDURE LoadError(_oBrowser est un ChromiumWebBrowser,_oArgs est CefSharp.LoadErrorEventArgs <utile>)
Trace("------------------------------")
Trace(dbgInfo(dbgTraitement))
Trace(_oBrowser:get_Address()) |
LoadingStateChanged
1 2 3 4 5 6 7 8 9 10 11
|
PROCEDURE LoadingStateChanged(_oBrowser est un ChromiumWebBrowser,_oArgs est CefSharp.LoadingStateChangedEventArgs <utile>)
//https://github.com/cefsharp/CefSharp/blob/master/CefSharp/LoadingStateChangedEventArgs.cs
Trace("------------------------------")
Trace(dbgInfo(dbgTraitement))
Trace(_oBrowser:get_Address())
bIsLoading est un booléen
bIsLoading = _oArgs.get_IsLoading()
Trace("Loading : "+bIsLoading) |
StatusMessage
1 2 3 4 5 6
|
PROCEDURE StatusMessage(_oBrowser est un ChromiumWebBrowser,_oArgs est CefSharp.StatusMessageEventArgs <utile>)
Trace("------------------------------")
Trace(dbgInfo(dbgTraitement))
Trace(_oBrowser:get_Address()) |
TitleChanged
1 2 3 4 5 6
|
PROCEDURE TitleChanged(_oBrowser est un ChromiumWebBrowser,_oArgs est CefSharp.TitleChangedEventArgs <utile>)
Trace("------------------------------")
Trace(dbgInfo(dbgTraitement))
Trace(_oBrowser:get_Address()) |
EvaluateJsDone
1 2 3 4
|
PROCEDURE EvaluateJsDone(_oWDJavascript est un WindevNet.WDJavascript <utile>,_oArgs est WindevNet.EvaluateJsDoneEventArgs)
Info(_oArgs.sResult) |
2.4/Fin d'initialisation de la fenêtre
Dans le traitement de fin d'initialisation, copier le code suivant (WinForm1 est le nom du champ .NET 2.0) :
1 2 3 4 5
|
goBrowser.Dock = DockStyle.Fill
//WinForm1 est le nom du champ .NET 2.0
WDHelpers.AddControlToControlCollection(goBrowser,WinForm1.Controls)
MaFenêtre..Titre += " : "+Cef.ChromiumVersion +"-"+ Cef.CefVersion+"-"+Cef.CefSharpVersion |
2.5/Fermeture de la fenêtre
Cef.Shutdown()
3/Fonctions diverses
Charger une URL :
1 2
|
goBrowser.Load("http://google.com") |
Il est aussi possible d'
accéder au DOM des documents et de le modifier à l'aide d'appels Javascript.
1 2 3 4 5 6 7 8 9
|
sJavascript est une chaîne = [
document.forms["%1"].submit();
]
sFormNom est une chaîne
sFormNom = "myform"
sJavascript = ChaîneConstruit(sJavascript,sFormNom)
WebBrowserExtensions.ExecuteScriptAsync(goBrowser,sJavascript) |
Récupérer le résultat d'une fonction Javascript :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
|
sJavascript est une chaîne
sVal est une chaîne
//Récupérer le contenu de la balise 'html' du document
sJavascript = [
document.getElementsByTagName('html')[0].innerHTML;
]
EvaluateJsAsync(goBrowser,sJavascript)
//La procédure Windev de gestion d'événement "EvaluateJsDone" est déclenchée lorsque le résultat est prêt.
//Récupérer le contenu de tous les formulaires du document
sJavascript = [
(function() {
var elements = document.getElementsByTagName('form');
var elementsList = '';
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
elementsList += element.innerHTML;
if (i < elements.length-1)
{
elementsList += '<RC>';
}
}
return elementsList; })();
]
EvaluateJsAsync(goBrowser,sJavascript)
//La procédure Windev de gestion d'événement "EvaluateJsDone" est déclenchée lorsque le résultat est prêt. |
La procédure Windev "
EvaluateJsAsync" :
1 2 3 4 5
|
PROCEDURE EvaluateJsAsync(_oBrowser est un ChromiumWebBrowser, LOCAL _sJavascript est une chaîne)
oFrame est CefFrameWrapper dynamique <- WebBrowserExtensions.GetMainFrame(_oBrowser)
oWDJavascript:EvaluateJsAsync(oFrame,_sJavascript,0) |
La procédure Windev "
EvaluateJsDone" :
1 2 3 4
|
PROCEDURE EvaluateJsDone(_oWDJavascript est un WindevNet.WDJavascript <utile>,_oArgs est WindevNet.EvaluateJsDoneEventArgs)
Info(_oArgs.sResult) |
Code C# de la dll WindevNet :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
|
using CefSharp;
using System;
using System.Threading.Tasks;
namespace WindevNet
{
public class EvaluateJsDoneEventArgs : EventArgs
{
public int iID { get; set; }
public string sResult { get; set; }
public Task<JavascriptResponse> JavascriptResponse;
}
public class WDJavascript
{
public event EventHandler<EvaluateJsDoneEventArgs> EvaluateJsDone;
protected virtual void OnEvaluateJsDone(EvaluateJsDoneEventArgs e)
{
EventHandler<EvaluateJsDoneEventArgs> handler = EvaluateJsDone;
if (handler != null)
{
handler(this, e);
}
}
public void EvaluateJsAsync(IFrame f, string sJavascript,int iID=0)
{
f.EvaluateScriptAsync(sJavascript).ContinueWith(t =>
{
var Response = t.Result;
EvaluateJsDoneEventArgs args = new EvaluateJsDoneEventArgs();
args.iID = iID;
args.sResult = (string)Response.Result.ToString();
args.JavascriptResponse = t;
OnEvaluateJsDone(args);
});
}
}
} |
Code C# de test de CefSharp :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
|
using System;
using System.Windows.Forms;
using CefSharp;
using CefSharp.WinForms;
namespace CefTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
InitBrowser();
}
public ChromiumWebBrowser browser;
public void InitBrowser()
{
Cef.Initialize(new CefSettings());
browser = new ChromiumWebBrowser("www.google.com");
browser.IsBrowserInitializedChanged -= new EventHandler<CefSharp.IsBrowserInitializedChangedEventArgs>(IsBrowserInitialized);
browser.IsBrowserInitializedChanged += new EventHandler<CefSharp.IsBrowserInitializedChangedEventArgs>(IsBrowserInitialized);
browser.FrameLoadEnd -= new EventHandler<CefSharp.FrameLoadEndEventArgs>(FrameLoadEnd);
browser.FrameLoadEnd += new EventHandler<CefSharp.FrameLoadEndEventArgs>(FrameLoadEnd);
browser.ConsoleMessage -= new EventHandler<CefSharp.ConsoleMessageEventArgs>(ConsoleMessage);
browser.ConsoleMessage += new EventHandler<CefSharp.ConsoleMessageEventArgs>(ConsoleMessage);
this.Controls.Add(browser);
browser.Dock = DockStyle.Fill;
}
private void IsBrowserInitialized(object sender, IsBrowserInitializedChangedEventArgs e)
{
if (e.IsBrowserInitialized)
{
//Do something here
}
}
public string EvaluateJsResponse;
public void EvaluateJs(IFrame f, string Js)
{
f.EvaluateScriptAsync(Js).ContinueWith(x =>
{
var response = x.Result;
if (response.Success && response.Result != null)
{
EvaluateJsResponse = (string)response.Result.ToString();
//Do something here (To interact with the UI you must call BeginInvoke)
}
});
}
public void FrameLoadEnd(object sender, FrameLoadEndEventArgs e)
{
if (e.Frame.IsMain)
{
//string sJs = "document.getElementsByTagName('html')[0].innerHTML;";
string sJs = "(function() { var body = document.body, html = document.documentElement; return Math.max( body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight ); })();";
EvaluateJs(e.Frame, sJs);
}
}
public void ConsoleMessage(object sender, ConsoleMessageEventArgs e)
{
Console.WriteLine(e.Message);
}
}
} |
En cas de problèmes d'intégration dans Windev, la solution peut être souvent de supprimer le répertoire .NET de votre projet, de vider son répertoire de compilation <NomProjet>.cpl et de recompiler le projet.
Merci aux intervenants de ce fil :
http://www.developpez.net/forums/d14...cation-windev/ et à ochoteau en particulier pour les sources.
Bonne prog

Partager