CEF4Delphi

Descripción

CEF4Delphi es un proyecto de código abierto creado por Salvador Díaz Fau para incluir navegadores basados en Chromium dentro de aplicaciones realizadas con Delphi o Lazarus/FPC para Windows, Linux y MacOS.

Introducción

CEF4Delphi se basa en DCEF3 y fpCEF3 pero dichos proyectos usan ramas anticuadas de CEF. Para poder añadir pestañas de navegador web basadas en Chromium en BriskBard es necesario utilizar la última rama estable de CEF y disponer de actualizaciones con regularidad. Dado que esos proyectos ya no reciben actualizaciones se decidió crear un proyecto nuevo.

El objetivo principal de CEF4Delphi es simplificar en lo posible el trabajo necesario para adaptarlo a las nuevas versiones de CEF. Para ello fue necesario tomar las siguientes medidas :

  • Se han eliminado redundancias. El componente OSR se fusionó con TChromium.
  • Se han borrado los comentarios copiados del código de CEF. Los comentarios en CEF se actualizan con la misma frecuencia que el código y se pueden sustituir por una referencia al archivo de CEF donde se encuentran.
  • Se ha repartido el código en muchas más unidades de menor tamaño.
  • Se han añadido comentarios con las equivalencias de clases y tipos entre CEF4Delphi y CEF.

La última versión de CEF4Delphi usa la rama 4430 de CEF. En concreto se usa la versión CEF 90.6.5 que incluye Chromium 90.0.4430.93

CEF4Delphi se ha desarrollado en Delphi 10.4.2 y también se ha probado en Delphi 7, Delphi XE, Delphi 10, Delphi 10.2, Delphi 10.3 y Lazarus 2.0.12 con FPC 3.2.0. CEF4Delphi incluye componentes VCL, FireMonkey (FMX) y Lazarus de 32 y 64 bits.

Si desea probar CEF4Delphi puede descargar gratuitamente la última versión de Delphi Community Edition desde Embarcadero.

También es posible probar CEF4Delphi descargando gratuitamente Lazarus/FPC.

Esquema

Antes de usar CEF4Delphi con una aplicación hecha con Delphi o Lazarus es necesario comprender que CEF4Delphi es una capa (wrapper) que usa la API C de CEF. A su vez, CEF aisla al usuario de las complejidades de Chromium y Blink.

Esquema de CEF4Delphi

Versiones estables

La rama master del repositorio está considerada como una rama en desarrollo y puede tener errores. Use la última versión publicada si necesita un componente estable.

Enlaces

Proyecto CEF4Delphi :

Proyecto Chromium Embedded Framework (CEF) :

Archivos binarios de CEF usados por CEF4Delphi :

Proyecto OldCEF4Delphi :

Compatibilidad

CEF4Delphi se puede usar en aplicaciones VCL, FMX y LCL con Delphi o Lazarus/FPC.

Lea esta página wiki para obtener más información sobre CEF4Delphi en Lazarus.

Windows

Google anunció en 2015 que Chrome no seguiría siendo compatible con Windows XP. La última rama de CEF compatible con Windows XP fue la rama 2623, publicada en 2016.

Dado que CEF4Delphi usa la rama más reciente de CEF, no es compatible con Windows XP, Windows Vista, Windows Server 2003 y Windows Server 2008.

CEF4Delphi necesita Windows 7, 8, 8.1, 10 o posterior para funcionar pero si se desea probar alguna otra versiĆ³n de Windows solo hay que descargar e intentar ejecutar la aplcación de ejemplo de CEF (Sample Application en inglés) desde la página de descargas del proyecto CEF.

Si necesita que su aplicación funcione en Windows XP o Vista use OldCEF4Delphi.

Linux

Linux está totalmente soportado por CEF4Delphi con Lazarus/FPC en CPUs x86 y ARM. La demo de Linux hecha con Firemonkey se encuentra en estado experimental en este momento.

En el caso de aplicaciones para Linux, CEF requiere tener instalado Ubuntu 16.04 o una versión posterior.

MacOS

MacOS también está totalmente soportado por CEF4Delpi con Lazarus/FPC en CPUs x86. También debería ser posible añadir soporte de Delphi FMX en MacOS pero no está implementado en este momento.

CEF4Delphi no se ha probado en MacOS con CPUs ARM. CEF requiere MacOS 10.11 o posterior para funcionar.

Instalación

Para compilar e instalar CEF4Delphi en la última versión de Delphi hay que seguir los siguientes pasos :

  1. Descargar la última versión de CEF4Delphi desde GitHub.
  2. Descomprimir CEF4Delphi en un directorio y asegúrese de que su usuario tiene privilegios de escritura en ese directorio.
  3. Ejecutar Delphi.
  4. Añadir el directorio source de CEF4Delphi al library path en Delphi dentro del menú Tools→Options. En la ventana Options hay que hacer clic sobre Environment Options→Delphi Options→Library, seleccionar la plataforma de 32 o 64 bits y añadir el directorio en Library path.
  5. Abrir el archivo CEF4Delphi.dproj desde Delphi si solo quiere componentes VCL. Si quiere intalar los componentes FireMonkey (FMX) y VCL abra CEF4Delphi_FMX.dproj.
  6. Hacer clic con el botón derecho del ratón sobre el icono de CEF4Delphi.bpl dentro del panel del Project manager y seleccionar la opción Build.
  7. Hacer clic con el botón derecho del ratón sobre el icono de CEF4Delphi.bpl dentro del panel del Project manager y seleccionar la opción Install.

Para compilar e instalar CEF4Delphi en Delphi 7 hay que seguir los siguientes pasos :

  1. Descargar la última versión de CEF4Delphi desde GitHub.
  2. Descomprimir CEF4Delphi en un directorio y asegúrese de que su usuario tiene privilegios de escritura en ese directorio.
  3. Ejecutar Delphi.
  4. Añadir el directorio source de CEF4Delphi al library path en Delphi dentro del menú Tools→Environment options. En la ventana Environment Options hay que seleccionar la pestaña Library y añadir el directorio en Library path.
  5. Abrir el archivo CEF4Delphi_D7.dpk desde Delphi.
  6. Hacer clic en el botón Compile.
  7. Hacer clic en el botón Install.

Para compilar e instalar CEF4Delphi en Lazarus hay que instalar el paquete DCPCrypt usando el Online Package Manager. Después hay que seguir los siguientes pasos :

  1. Descargar la última versión de CEF4Delphi desde GitHub.
  2. Descomprimir CEF4Delphi en un directorio y asegúrese de que su usuario tiene privilegios de escritura en ese directorio.
  3. Ejecutar Lazarus.
  4. Abrir el archivo cef4delphi_lazarus.lpk desde el menú Package→Open Package File (*.lpk)....
  5. Hacer clic en el botón Compile en la ventana del paquete.
  6. Hacer clic en el botón Use y seleccionar la opción Install.

Construyendo la primera demo

Antes de seguir con más detalles vamos a compilar una de las demostraciones para ver como funciona un navegador CEF.

Windows

Construya esta demo dependiendo del IDE que use :

  • Lazarus : Lazarus_Windows/MiniBrowser
  • Delphi : Delphi_VCL/MiniBrowser
  • Delphi 7 : Delphi_VCL/SimpleBrowser2

En unos segundos verá un nuevo ejecutable dentro del directorio CEF4Delphi/bin llamado MiniBrowser.exe o SimpleBrowser2.exe pero si intenta ejecutarlo verá un mensaje de error con una lista de archivos de CEF que no se pudieron encontrar.

Necesita copiar los archivos binarios de CEF en el directorio CEF4Delphi/bin que previamente tiene que descargar desde estos enlaces :

Una vez que ha descargado y descomprimido el paquete de archivos debe copiar el contenido de los directorios Release and Resources dentro del directorio CEF4Delphi/bin.

La disposición final es esta :

Disposición final de los archivos de la distribución binaria de CEF junto a la aplicación.
Fíjese que los archivos cef_sandbox.lib y libcef.lib se pueden omitir.

Si todo está en su lugar debería ser capaz de ejecutar la demo.

Linux

Construya la demo Lazarus_Linux/MiniBrowser y verá un ejecutable nuevo en el directorio CEF4Delphi/bin llamado MiniBrowser.

De igual manera que las demos de Windows, es necesario descargar los arhivos binarios de CEF usando estos enlaces :

Descomprima el paquete correspondiente y copie el contenido de los directorios Release and Resources dentro del directorio CEF4Delphi/bin.

La disposición final es esta :

Disposición final de los archivos de la distribución binaria de CEF junto a la aplicación.

Fíjese que el archivo libcef.so es enorme porque contiene los símbolos de depurado. Al ejecutar la demo notará que tarda unos segundos debido al tamaño de libcef.so. Para acelerar este proceso y reducir su tamaño puede eliminar los símbolos de depurado con el siguiente comando :

strip libcef.so

Si los archivos binarios de CEF están en el lugar adecuado debería ser capaz de ejecutar la demo ahora.

MacOS

Construya las demos Lazarus_Mac/ExternalPumpBrowser y Lazarus_any_OS/AppHelper.

En este momento debería ver 2 nuevas aplicaciones en el directorio CEF4Delphi/bin correspondientes a esas 2 demos.

Descargue el paquete de archivos binarios de CEF usando este enlace : MacOS x86 (64 bit)

Las aplicaciones de MacOS deben tener unos contenidos y una estructura de directorios muy precisa. En este caso debe descomprimir el paquete de archivos binarios de CEF y copiar los contenidos del directorio Release/Chromium Embedded Framework.framework dentro del directorio ExternalPumpBrowser.app/Contents/Frameworks/Chromium Embedded Framework.framework/

La aplicación AppHelper debe añadirse dentro de la aplicación ExternalPumpBrowser y para hacer eso es necesario ejecutar Lazarus_any_OS/AppHelper/create_mac_helper_apps.sh con la ruta completa de ExternalPumpBrowser.app como argumento.

La disposición final es esta :

ExternalPumpBrowser.app/ Contents/ Frameworks/ Chromium Embedded Framework.framework/ Chromium Embedded Framework Resources/ cef.pak, devtools_resources.pak, ... icudtl.dat natives_blob.bin, snapshot_blob.bin en.lproj/, ... ExternalPumpBrowser Helper.app/ Contents/ Info.plist MacOS/ ExternalPumpBrowser Helper Pkginfo ExternalPumpBrowser Helper (GPU).app/ Contents/ Info.plist MacOS/ ExternalPumpBrowser Helper (GPU) Pkginfo ExternalPumpBrowser Helper (Plugin).app/ Contents/ Info.plist MacOS/ ExternalPumpBrowser Helper (Plugin) Pkginfo ExternalPumpBrowser Helper (Renderer).app/ Contents/ Info.plist MacOS/ ExternalPumpBrowser Helper (Renderer) Pkginfo Info.plist MacOS/ ExternalPumpBrowser Pkginfo Resources/ binding.html, ...

Si los archivos binarios de CEF están correctamente copiados dentro de la aplicación ExternalPumpBrowser y create_mac_helper_apps.sh se ha ejecutado sin errores debería ser capaz de ejecutar ExternalPumpBrowser.

Primeros pasos

Antes de usar CEF4Delphi por primera vez es muy recomendable leer la información sobre CEF y los documentos sobre el diseño de Chromium.

La documentacion de la API de CEF está disponible en magpcss.org y hay muchísima información sobre el uso de CEF en los comentarios de su código fuente.

Como se puede ver en la documentación, por defecto CEF usa multiples hilos y procesos para proteger a la aplicación de posibles errores del motor de renderizado.

Con el proposito de crear esos procesos, CEF puede ejecutar de nuevo el mismo ejecutable de la aplicación o también se puede configurar para que use un ejecutable diferente.

Por defecto CEF usará el mismo ejecutable pero esto puede causar problemas si la aplicación tiene una inicialización compleja o el sistema operativo tiene otros requerimientos.

CEF4Delphi simplifica toda la inicialización de CEF gracias a GlobalCEFApp, el cual es una instancia de la clase TCEFApplication.

Windows

Las aplicationes de Windows pueden configurar CEF para usar un archivo EXE para todos los procesos o un EXE diferente para los subprocesos de CEF.

Si decide usar el mismo EXE para todos los procesos entonces necesita modificar el archivo del proyecto (*.DPR en Delphi y *.LPR en Lazarus) para crear GlobalCEFApp, asignar sus propiedades y llamar GlobalCEFApp.StartMainProcess antes que realizar la llamada a Application.Initialize.

Comencemos usando un proyecto de Delphi ya que los archivos de proyecto en Lazarus son casi idénticos.

Las aplicaciones de Delphi suelen tener este código en el archivo DPR :

program Project1; uses Vcl.Forms, Unit1 in 'Unit1.pas' {Form1}; {$R *.res} begin Application.Initialize; Application.MainFormOnTaskbar := True; Application.CreateForm(TForm1, Form1); Application.Run; end.

Para incluir CEF4Delphi necesitaría modificarlo de esta manera :

program Project1; uses Vcl.Forms, WinApi.Windows, uCEFApplication, Unit1 in 'Unit1.pas' {Form1}; {$R *.res} {$SetPEFlags IMAGE_FILE_LARGE_ADDRESS_AWARE} begin GlobalCEFApp := TCefApplication.Create; if GlobalCEFApp.StartMainProcess then begin Application.Initialize; Application.MainFormOnTaskbar := True; Application.CreateForm(TForm1, Form1); Application.Run; end; GlobalCEFApp.Free; end.

Las diferencias son :

  • La clausula uses tiene una referencia a uCEFApplication.
  • En caso de que su aplicación sea de 32 bits tendrá que añadir la directiva SetPEFlags con IMAGE_FILE_LARGE_ADDRESS_AWARE, el cual permite usar hasta 3GB de RAM a los procesos de 32 bit. Esto no es necesario para las aplicaciones de 64 bits.
  • GlobalCEFApp se crea al comienzo del archivo de proyecto. Se pueden asignar sus propiedades aquí, antes de la llamada a GlobalCEFApp.StartMainProcess.
  • La llamada a GlobalCEFApp.StartMainProcess es la codición de una clausula if..then antes de que Application se inicialice y ejecute.
  • GlobalCEFApp se destruye en la última linea del archivo del proyecto.

El proceso principal ejecutará el código del archivo de proyecto siguiendo estos pasos :

  • Se ejecutan las secciones de initialization de todas las unidades declaradas en la clausula uses.
  • Se crea GlobalCEFApp.
  • Se ejecuta GlobalCEFApp.StartMainProcess y devuelve TRUE rápidamente, lo cual permite que Application se inicialice y ejecute.
  • Se ejecuta Application.Run y la ejecución del programa permanece dentro de ese paso hasta que el usuario cierra la aplicación.
  • Se destruye GlobalCEFApp.
  • Se ejecutan las secciones finalization de todas las unidades declaradas en la clausula uses.

Sin embargo, los subprocesos de CEF ejecutarán el código del archivo de proyecto siguiendo estos pasos :

  • Se ejecutan las secciones de initialization de todas las unidades declaradas en la clausula uses.
  • Se crea GlobalCEFApp.
  • Se ejecuta GlobalCEFApp.StartMainProcess y la ejecución del programa permanece dentro de este paso hasta que Chromium decida cerrar este proceso.
  • GlobalCEFApp.StartMainProcess devuelve FALSE cuando Chromium cierra este proceso, con lo que se evita inicializar y ejecutar Application.
  • Se destruye GlobalCEFApp.
  • Se ejecutan las secciones finalization de todas las unidades declaradas en la clausula uses.

Si está añadiendo un navegador CEF a una aplicación ya existente necesita decidir si se puede usar el mismo EXE o hay que usar otro diferente para los subprocesos de CEF para lo que será necesario comprobar el código presente en el archivo de proyecto de la aplicación y en las secciones de initialization y finalization porque se ejecutarán en todos los procesos de CEF.

Si no es posible sacar todo el código de las secciones de initialization y finalization, y mover el código del archivo de proyecto es demasiado complicado o no está permitido entonces puede uasr un EXE diferente para los subprocesos de CEF.

En ese caso puede crear GlobalCEFApp en cualquier momento de la vida de su aplicación.

Usar un archivo EXE diferente le permite inicializar CEF solo cuando el usuario necesita ver un navegador web pero recuerde que CEF solo se puede inicializar una vez por proceso. Esta es una caraterística de CEF que no se puede evitar.

Eche un vistazo a estas demostraciones para conocer todos los detalles :

  • Delphi_VCL/SimpleBrowser2 : Esta es una demo de Delphi que usa un EXE para todos los procesos de CEF.
  • Lazarus_Windows/SimpleBrowser2 : Esta es una demo de Lazarus que usa un EXE para todos los procesos de CEF.
  • Delphi_VCL/Subprocess : Esta es una demo de Delphi que usa un EXE diferente para los subprocesos de CEF.
  • Lazarus_Windows/Subprocess : Esta es una demo de Lazarus que usa un EXE diferente para los subprocesos de CEF.
Linux

Usar CEF4Delphi en Linux tiene pocas diferencias con Windows y se puede reutilizar casi todo el código. Lea las instrucciones para Windows antes de leer esta sección.

Las demos de Lazarus deben añadir UseCthreads a las opciones personalizadas dentro de la ventana de las opciones del proyecto.

Todas las demostraciones de Lazarus usan GTK 2 mientras que la de Delphi usa GTK 3. QT no está soportado por el momento.

Chromium debería inicializarse en un proceso con un solo hilo y esto puede causar problemas algunas veces porque GTK crea algunos hilos cuando se inicializa.

Lazarus inicializa GTK en la sección de Initialization de la unidad Interfaces y Delphi inicializa GTK en la sección de Initialization de la unidad FMX.Platform.

Las secciones de Initialization se ejecutan antes que el código del archivo de proyecto y esto puede generar problemas con CEF.

Las demos de Lazarus pueden evitar este problema de dos maneras :

  • Crear una unidad Interfaces personalizada que saque la inicialización de GTK de la sección de Initialization.
  • Crear una unidad que cree GlobalCEFApp en su sección de Initialization y añadirla a la clausula de uses antes que la unidad de Interfaces.

Las demos de Delphi usan FMXLinux y antes de la versión 1.56 solo se podía crear una unidad personalizada que cree GlobalCEFApp en su sección de Initialization y añadirla a la clausula uses en primera posición.

Con FMXLinux 1.56 y posteriores se puede añadir la unidad FMUX.Config la la unidad personalizada comentada previamente y asignar un valor de TRUE a la variable DoNotCallFmuxInit. Entonces se puede llamar a FmuxInit despues de GlobalCEFApp.StartMainProcess. Lea esto para obtener más información sobre esta solución.

Eche un vistazo a estas demostraciones para obtener más detalles :

  • Lazarus_Linux/SimpleBrowser2 : Esta es una demo de Lazarus que usa un ejecutable para todos los procesos de CEF.
  • Lazarus_Linux/Subprocess : Esta es una demo de Lazarus que usa un ejecutable diferente para los subprocesos de CEF.
  • Delphi_FMX_Linux/FMXExternalPumpBrowser2 : Esta demostración de Delphi usa un ejecutable diferente para los subprocesos de CEF. En este momento está en estado experimental.
MacOS

Las aplicaciones de MacOS con navegadores CEF deben incluir 4 paquetes de aplicaciones asistentes (Helper app bundles) para los subprocesos. Chromium los busca internamente cuando necesita crear un nuevo subproceso. Lea esto para más información.

No es necesario modificar el archivo LPR en MacOS porque CEF se puede inicializar en otra unidad. Es el mismo caso que las aplicaciones de Windows y Linux que usan un ejecutable diferente para los subprocesos de CEF.

Los 4 Helper deben estar en el directorio <nombredelaaplicacion>.app/Contents/Frameworks con estos nombres :

  • <nombredelaaplicacion> Helper.app
  • <nombredelaaplicacion> Helper (GPU).app
  • <nombredelaaplicacion> Helper (Plugin).app
  • <nombredelaaplicacion> Helper (Renderer).app

Los 4 Helper son copias identicas con un nombre diferente y solo necesitan crear GlobalCEFApp, llamar GlobalCEFApp.InitLibLocationFromArgs y GlobalCEFApp.StartSubProcess, y por último destruir GlobalCEFApp.

Vea las demos Lazarus_Mac/ExternalPumpBrowser y Lazarus_any_OS/AppHelper para más detalles.

Configuraciones del navegador web

CEF se puede configurar para crear navegadores web con diferentes modos de funcionamiento :

  • Navegadores en modo normal o en ventana : CEF creará un control hijo para dibujar los contenidos web por si mismo y muchas otras características y eventos también los controla CEF intérnamente.
  • Navegadores en modo renderizado fuera de pantalla u OSR usando las siglas en inglés : CEF ofrecerá un buffer de píxeles con los contenidos web. La aplicación será la responsable de dibujar el contenido del buffer en un control y también gestionará todos los eventos.

El modo normal requiere mucho menos código y es mucho más rápido que el modo OSR pero el modo OSR ofrece a la aplicación un control mucho mayor sobre del navegador.

Puede comparar estos dos modos con las demos SimpleBrowser2 y SimpleOSRBrowser.

Hilos de CEF y el bucle de mensajes del navegador

Otra de las configuraciones de CEF que merece la pena mencionar es el uso del bucle de mensajes multi-hilo.

Por defecto, CEF tiene esta opción activada y usará un hilo de fondo para ejecutar el bucle de mensajes del navegador para mejorar el rendimiento. Como consecuencia de ello, todos los eventos de CEF se ejecutan en un hilo de CEF que es diferente del hilo principal de la aplicación.

No es seguro manipular los controles de Windows y Linux en hilos que no sean el principal de la aplicación y debe evitar crear, destruir o modificar controles dentro de los eventos de CEF si está configurado para usar el bucle de mensajes multi-hilo.

Algunas demostraciones ignoran esto porque están simplificadas al máximo con el propósito de mantener el código tan simple y fácil de entender como sea posible, pero debería mover todo el código que manipula el interfaz de usuario a un procedimiento que se ejecute en el hilo principal de la aplicación.

Si se configura CEF para desactivar el bucle de mensajes multi-hilo entonces todos los eventos de CEF se ejecutan en el hilo principal de la aplicación pero el rendimiento del navegador no es tan bueno.

Los navegadores CEF en MacOS siempre tienen que tener desactivado el bucle de mensajes multi-hilo.

Puede comparar el código de las demostraciones SimpleBrowser2 y ExternalPumpBrowser para conocer todos las diferencias de implementación cuando se activa o no esta opción.

Componentes de CEF4Delphi

CEF4Delphi incluye muchas clases y componentes VCL, FMX y LCL para añadir un navegador web con todas las configuraciones de CEF posibles.

TCEFApplication

La principal clase usada para simplificar la inicialización y destrucción de CEF es TCEFApplication y la mayor parte de las demostraciones crean GlobalCEFApp como una instancia de TCEFApplication.

La demostración SubProcess es una excepción a esta regla para evitar problemas con MS Office y usa TCEFApplicationCore en su lugar.

TCEFApplication crea automáticamente algunos handlers de CEF únicamente si se necesitan. Esos handlers son CefApp, CefBrowserProcessHandler, CefRenderProcessHandler, CefResourceBundleHandler y CefLoadHandler.

Lea esto para obtener más información sobre esta clase.

TChromium / TFMXChromium

Este es el componente que reune todos los procedimientos, funciones, propiedades y eventos del navegador en un solo lugar. Tiene todo lo necesario para crear, modificar y destruir un navegador web.

Las aplicaciones VCL y LCL usan TChromium pero las aplicaciones FireMonkey usan TFMXChromium. Ambos componentes heredan de TChromiumCore, el cual tiene la mayor parte del código pero verá referencias a TChromium en el foro por simplificar.

TChromiumCore también crea muchos handlers de CEF en caso de que se necesiten, como CefClient, CefResourceRequestHandler, etc.

Lea esto para obtener más información sobre este componente.

TCEFWindowParent / TFMXWindowParent

El componente TCEFWindowParent se usa en aplicaciones VCL y LCL junto al componente TChromium para empotrar un navegador web en modo normal.

Tal como se comentó anteriormente, los navegadores en modo normal permiten que CEF cree algunos controles hijo nativos para mostrar los contenidos web en ellos. TCEFWindowParent hereda de TCEFWinControl y se usa como padre de dichos controles. TCEFWindowParent también controla el tamaño de esos controles automáticamente. Vea la demostración SimpleBrowser2 para conocer más detalles.

TFMXWindowParent es un componente FireMonkey con el mismo uso que TCEFWindowParent pero debido a la estructura del código de FMX hereda de TCommonCustomForm.

TFMXWindowParent se usa junto a TFMXChromium y se debe crear en tiempo de ejecución. Vea la demostración SimpleFMXBrowser para conocer los detalles.

TCEFLinkedWindowParent

Este componente se puede usar en aplicaciones VCL y LCL. Tiene el mismo uso que TCEFWindowParent pero incluye una propiedad Chromium para enlazarlo directamente con un componente TChromium.

TCEFLinkedWindowParent cambia el tamaño de los controles creados por CEF en navegadores en modo normal y asigna el foco usando el componente que se ha enlazado.

TCEFWindowParent y TCEFLinkedWindowParent funcionan correctamente en Windows y se pueden usar indistintamente pero en Linux o MacOS no se puede usar TCEFWindowParent.

TBufferPanel / TFMXBufferPanel

TBufferPanel se usa en aplicaciones VCL y LCL con navegadores en modo OSR para dibujar los contenidos web. TFMXBufferPanel tiene el mismo propósito per se usa en aplicaciones FireMonkey.

Vea la demostración SimpleOSRBrowser para obtener más detalles.

TCEFWorkScheduler / TFMXWorkScheduler

TCEFWorkScheduler se usa en aplicaciones VCL y LCL con navegadores CEF que han desactivado el bucle de mensajes multi-hilo. TFMXWorkScheduler tiene el mismo propósito pero se usa en aplicaciones FireMonkey.

Estos componentes gestionan las llamadas a GlobalCEFApp.DoMessageLoopWork usando el parámetro delayMs del evento GlobalCEFApp.OnScheduleMessagePumpWork.

Las aplicaciones VCL y LCL deben crear GlobalCEFWorkScheduler como una instancia de TCEFWorkScheduler antes de crear GlobalCEFApp.

Las aplicaciones FMX deben crear GlobalFMXWorkScheduler como una instancia de TFMXWorkScheduler antes de crear GlobalCEFApp.

También es necesario destruir GlobalCEFApp antes de destruir GlobalCEFWorkScheduler o GlobalFMXWorkScheduler.

Vea las demostraciones ExternalPumpBrowser y FMXExternalPumpBrowser para saber más detalles sobre su uso.

TChromiumWindow

TChromiumWindow se creó para añadir navegadores web extremádamente simples de una manera un poco más sencilla que usando una pareja de TChromium y TCEFWindowParent.

TChromiumWindow se puede usar en aplicaciones VCL y LCL con navegadores en modo normal pero si se usan muchos eventos o procedimientos de TChromium deberí sopesar usar los otros componentes.

Vea la demostración SimpleBrowser para saber más detalles.

TBrowserWindow / TOSRBrowserWindow

TBrowserWindow es un componente LCL que simplifica la creación de aplicaciones multi-plataforma con navegadores web en modo normal. TOSRBrowserWindow tiene el mismo propósito pero usa navegadores en modo OSR.

Si utiliza el mismo código fuente para contruir con Lazarus las versiones de Windows, Linux y MacOS de su aplicación entonces se recomienda usar estos componentes.

TBrowserWindow y TOSRBrowserWindow fueron creados por Martin_fr, también conocido como User4martin. Martin_fr es uno de los administradores del proyecto Lazarus.

Todas las demostraciones del directorio Lazarus_any_OS muestran como usar estos componentes.

TCEFServerComponent

TCEFServerComponent le permite crear un pequeño servidor HTTP y WebSocket en aplicaciones VCL, LCL y FMX.

Se puede usar para implementar un sistema de comunicación entre procesos (IPC) que comunique una aplicación con un servidor local.

Vea la demostración SimpleServer para saber como usarlo.

TCEFURLRequestClientComponent

TCEFUrlRequestClientComponent le permite realizar peticiones URL sin relación con ningún navegador desde una aplicación VCL, LCL o FMX.

Vea la demostración URLRequest para saber más detalles sobre su funcionamiento.

TCEFSentinel

TCEFSentinel se usa como un temporizador que comprueba el número de procesos CEF en ejecución cuando se cierran todos los navegadores antes de cerrar la aplicación totalmente.

Este componente solo se usa como último recurso cuando hay algún problema sin resolver en CEF o CEF4Delphi que genera excepciones cuando se cierra la aplicación.

Chromium Views Framework

Todos los componentes de la pestaña Chromium Views Framework permiten usar artilugios (widgets) y gestores de disposición (layout managers) de Views/Aura en aplicaciones VCL y LCL.

CEF usa este mismo framework de interfaz de usuario internamente en Windows, Linux y MacOS para crear navegadores.

Vea la demostración ToolBoxBrowser2 y lea este documento para conocer más detalles sobre estos componentes.

Creación de navegadores web

Cuando se deja GlobalCEFApp con los valores por defecto CEF tiene activado el bucle de mensajes multi-hilo y se inicializa en un hilo de fondo tras la llamada a GlobalCEFApp.StartMainProcess.

Los navegadores de CEF solo pueden crearse cuando la inicialización de CEF se ha completado y esto puede causar una condición de carrera si la aplicación intenta crear un navegador cuando la ventana principal de la aplicación se muestra por primera vez.

Casi todas las demostraciones usan un simple TTimer para reintentar la llamada a TChromium.CreateBrowser tras unos pocos milisegundos pero también es posible usar el evento TCEFApplication.OnGlobalContextInitialized para enviar un mensaje a la ventana principal con el fin de crear el navegador web.

Las aplicaciones de Lazarus que usan los componentes TBrowserWindow o TOSRBrowserWindow gestionan todo esto automáticamente.

Cierre de la aplicación

Chromium requiere que todos los navegadores se la aplicación se cierren correctamente antes de destruir GlobalCEFApp, lo cual sucede en las últimas lineas del archivo del proyecto.

Los navegadores CEF deben seguir estos pasos para cerrarlos apropiadamente :

  1. Llamar a TChromium.CloseBrowser.
  2. Esperar a que se ejecute el evento TChromium.OnClose.
  3. Esperar a que se ejecute el evento TChromium.OnBeforeClose.

Cada demostración tiene una secuencia de destrucción en los comentarios del código porque cada configuración del navegador puede añadir u omitir algún paso pero en general, la aplicación debería esperar hasta que todos los eventos TChromium.OnBeforeClose se han ejecutado antes de proseguir cerrando la aplicación.

Lea los comentarios del código de la demostración que usó como plantilla para su aplicación para saber todos los detalles.

CEF4Delphi y FireMonkey

FireMonkey es una interfaz de usuario gráfica muy poderosa capaz de crear aplicaciones para Windows, MacOS, Linux, iOS y Android con el mismo código pero esa capa de abstracción puede dificultar un poco las cosas porque CEF necesita acceso a algunas características de APIs de nivel más bajo.

Por ejemplo, algunas demostraciones de Windows usan una clase personalizada que implementa el interfaz IFMXApplicationService para acceder a los mensajes de Windows. Otras demostraciones usan un procedimiento WndProc personalizado por la misma razón.

Si necesita añadir un navegador CEF con CEF4Delphi en una aplicación FireMonkey tiene que añadir el codicional $(FrameworkType) en las opciones del proyecto.

Para hacer esto abra el menú Project y haga clic en Options.... Después seleccione la opción Building→Delphi Compiler en la parte izquierda, seleccione All configurations en la casilla de Target y teclee $(FrameworkType) en la casilla de Conditional defines.

También puede usar FMX sin las comillas en lugar de $(FrameworkType) si el condicional no funciona en ese proyecto.

Demostraciones de CEF4Delphi

El directorio CEF4Delphi\demos tiene varios subdirectorios con demostraciones para Delphi y Lazarus :

  1. Delphi_FMX_Linux
    • FMXExternalPumpBrowser2
      Navegador en modo OSR que usa un surtidor de mensajes externo con un ejecutable diferente para los subprocesos.
      Está en estado experimental.
  2. Delphi_FMX_Windows
    • FMXExternalPumpBrowser
      Navegador en modo OSR que usa un surtidor de mensajes externo.
    • FMXTabbedBrowser
      Múltiples navegadores en pestañas en modo normal.
    • FMXTabbedOSRBrowser
      Múltiples navegadores en pestañas en modo OSR.
    • FMXToolBoxBrowser
      Navegador en una ventana hija en modo normal.
    • SimpleFMXBrowser
      Navegador simple en modo normal.
  3. Delphi_VCL
    • ConsoleBrowser
      Navegador en modo OSR en una DLL cargada desde una aplicación de consola.
    • ConsoleBrowser2
      Aplicación de consola que crea un navegador OSR en un hilo y toma una captura de pantalla.
    • CookieVisitor
      Navegador que usa TCefCookieManagerRef para leer todas las cookies.
    • CustomResourceBrowser
      Un navegador simple que muestra recursos y páginas web personalizadas en lugar de sitios web en Internet.
    • DLLBrowser
      Un navegador web creado desde una DLL.
    • DOMVisitor
      Uso básico de las clases de CEF para buscar nodos y recorrer el arbol de nodos DOM.
    • EditorBrowser
      Editor HTML usando TChromium y TCEFWindowParent.
    • Extensions
      • HelloWorldExt
        Carga la típica extensión Hello World con la que se dan los primeros pasos.
      • PageColorExt
        Carga la extensión Set Page Color que permite cambiar el color de fondo de página web activa.
    • ExternalPumpBrowser
      Navegador hecho con los componentes TChromium y TCEFWindowParent usando un surtidor de mensajes externo.
    • FullScreenBrowser
      Navegador web simple a pantalla completa que usa TChromium y TCEFWindowParent. Utiliza la tecla ESC para salir.
    • JavaScript
      • CustomTitleBar
        Navegador que usa una extensión JS para controlar la ventana hecha en Delphi.
      • JSDialog
        Demostración que muestra como usar ventanas de dialogo de JS personalizadas.
      • JSEval
        Esta demostración evalua código JavaScript usando el V8Context.
      • JSExecutingFunctions
        Esta demostración muestra como registrar y ejecutar functiones de JAvaScript personalizadas con implementaciones nativas.
      • JSExtension
        Demostración que muestra como registrar una extensión de JavaScript básica con una función y como enviar información entre procesos.
      • JSExtensionWithFunction
        Demostración que muestra como registrar una extensión de JavaScript con una función que devuelve un valor.
      • JSExtensionWithObjectParameter
        Demostración que muestra como registrar una extensión de JavaScript con una función que tiene un parámetro.
      • JSRTTIExtension
        Esta demostración es similar a JSExtension pero usa RTTI para registrar la extensión.
      • JSSimpleExtension
        Demostración que registra una extensión que asigna un valor a una variable.
      • JSSimpleWindowBinding
        Esta demostración muestra como asignar valores al objeto window del frame.
      • JSWindowBindingSubProcess
        Esta demostración es similar a JSSimpleWindowBinding pero usando un ejecutable diferente para los subprocesos.
      • JSWindowBindingWithArrayBuffer
        Esta demostración es similar a JSSimpleWindowBinding pero asigna un valor con un buffer que contiene un array.
      • JSWindowBindingWithFunction
        Demostración que vincula una función al objeto window.
      • JSWindowBindingWithObject
        Esta demostración es similar a JSSimpleWindowBinding pero asigna un valor con un objeto.
    • KioskOSRBrowser
      Navegador web de quiosco a pantalla completa en modo OSR con un teclado virtual que se muestra automáticamente cuando el usuario hace clic en un elemento HTML editable. El menú contextual también incluye opciones para ocultar o mostrar el teclado. Hay que pusar la tecla ESC para salir.
    • MDIBrowser
      Multiples componentes TChromium en una aplicación MDI.
    • MDIExternalPumpBrowser
      Multiples componentes TChromium en una aplicación MDI usando un surtidor de mensajes externo.
    • MediaRouter
      Demostración que muesta como descubrir dispositivos multimedia en la red local y como enviar mensajes.
    • MiniBrowser
      Un navegador web que usa los componentes TChromium y TCEFWindowParent. Tiene menú contextual personalizado, interfaz de navegador básica, herramientas de desarrollo, zoom, impresión, configuración de proxy y algunas funciones extra para copiar el HTML e imprimir desde JavaScript.
    • OAuth2Tester
      Autenticación de usuarios con OAuth 2.0 y peticiones a REST API usando los componentes TCEFServerComponent y TCEFUrlRequestClientComponent.
    • OSRExternalPumpBrowser
      Navegador en modo OSR que usa un surtidor de mensajes externo.
    • PopupBrowser
      Esta demostración muestra como usar forms personalizados con las ventanas emergentes en modo OSR.
    • PopupBrowser2
      Esta demostración muestra como usar forms personalizados con las ventanas emergentes en modo normal.
    • PostInspectorBrowser
      Navegador web con un inspector de los datos de peticiones POST.
    • ResponseFilterBrowser
      Un navegador hecho con los componentes TChromium y TCEFWindowParent usando un filtro de respuestas personalizado.
    • SchemeRegistrationBrowser
      Registro de un esquema de URL que muestra páginas web personalizadas.
    • SimpleBrowser
      El navegador web más simple hecho con CEF4Delphi. Utiliza un componente TChromiumWindow.
    • SimpleBrowser2
      El navegador web más simple hecho con CEF4Delphi. Utiliza una combinación de dos componentes : TChromium y TCEFWindowParent.
    • SimpleExternalPumpBrowser
      Navegador hecho con el componente TChromiumWindow que usa un surtidor de mensajes externo.
    • SimpleOSRBrowser
      Un navegador web que usa TChromium en modo OSR en caso de que necesite renderizado fuera de pantalla.
    • SimpleServer
      Servidor HTTP y websockets hecho con el componente TCEFServerComponent para la comunicación entre aplicaciones locales.
    • SubProcess
      Navegador que usa un ejecutable diferente para los subprocesos de CEF.
    • TabbedBrowser
      Multiples componentes TChromium y TCEFWindowParent en pestañas.
    • TabbedBrowser2
      Multiples componentes TChromium y TCEFWindowParent dentro de un TFrame y con pestañas.
    • TinyBrowser
      Un minúsculo navegador creado con Views Framework sin usar VCL ni FMX.
    • TinyBrowser2
      Navegador extremadamente simple similar a cefsimple en el proyecto CEF.
    • ToolBoxBrowser
      Multiples componentes TChromium en una aplicación usando ventanas de tipo ToolBox.
    • ToolBoxBrowser2
      Un navegador simple en una ventana secundaria creados con Views Framework.
    • ToolBoxSubProcessBrowser
      Demostración similar a ToolBoxBrowser pero usando un ejecutable diferente para los subprocesos de CEF.
    • URLRequest
      Demostración de uso del componente TCEFUrlRequestClientComponent para realizar peticiones URL.
    • WebpageSnapshot
      Aplicación de escritorio que crea un navegador OSR en un hilo y toma una captura de pantalla.
  4. Lazarus_any_OS
    • AppHelper
      Ejecutable asistente (Helper) usado en las demostraciones de MacOS para los subprocesos de CEF.
    • BrowserWindow
      Demostración de navegador web que usa un componente TBrowserWindow.
    • BrowserWindowDom
      Demostración similar a BrowserWindow pero incluyendo funciones de consulta del DOM.
    • BrowserWindowEx
      Multiples componentes TBrowserWindow en una misma ventana.
    • BrowserWindowOsrDom
      Demostración de navegador web que usa un componente TOsrBrowserWindow y con funciones de consulta del DOM.
    • ExternalPumpBrowser
      Demostración que usa los componentes TChromium y TCEFLinkedWindowParent para todos los sistemas operativos con un surtidor de mensajes externo.
  5. Lazarus_Linux
    • ExternalPumpBrowser
      Navegador realizado con los componentes TChromium y TCEFLinkedWindowParent y con un surtidor de mensajes externo.
    • MiniBrowser
      Navegador web que usa TChromium y TCEFLinkedWindowParent en modo normal. Tiene menú contextual personalizado, interfaz de navegador básica, herramientas de desarrollo, zoom, impresión, etc.
    • OSRExternalPumpBrowser
      Navegador en modo OSR que usa un surtidor de mensajes externo.
    • PopupBrowser2
      Esta demostración muestra como usar forms personalizados con las ventanas emergentes en modo normal.
    • SimpleBrowser
      El navegador web más simple hecho con CEF4Delphi. Utiliza un componente TChromiumWindow.
    • SimpleBrowser2
      El navegador web más simple hecho con CEF4Delphi. Utiliza una combinación de dos componentes : TChromium y TCEFLinkedWindowParent.
    • SimpleOSRBrowser
      Un navegador web que usa TChromium en modo OSR en caso de que necesite renderizado fuera de pantalla.
    • SubProcess
      Navegador que usa un ejecutable diferente para los subprocesos de CEF.
    • TabbedBrowser2
      Multiples componentes TChromium y TCEFLinkedWindowParent dentro de un TFrame y con pestañas.
    • TinyBrowser2
      Navegador extremadamente simple similar a cefsimple en el proyecto CEF.
  6. Lazarus_Mac
    • ExternalPumpBrowser
      Navegador realizado con los componentes TChromium y TCEFLinkedWindowParent y con un surtidor de mensajes externo.
  7. Lazarus_Windows
    • ConsoleBrowser2
      Aplicación de consola que crea un navegador OSR en un hilo y toma una captura de pantalla.
    • CookieVisitor
      Navegador que usa TCefCookieManagerRef para leer todas las cookies.
    • CustomResourceBrowser
      Un navegador simple que muestra recursos y páginas web personalizadas en lugar de sitios web en Internet.
    • DOMVisitor
      Uso básico de las clases de CEF para buscar nodos y recorrer el arbol de nodos DOM.
    • EditorBrowser
      Editor HTML usando TChromium y TCEFWindowParent.
    • ExternalPumpBrowser
      Navegador hecho con los componentes TChromium y TCEFWindowParent usando un surtidor de mensajes externo.
    • FullScreenBrowser
      Navegador web simple a pantalla completa que usa TChromium y TCEFWindowParent. Utiliza la tecla ESC para salir.
    • JavaScript
      • JSDialog
        Demostración que muestra como usar ventanas de dialogo de JS personalizadas.
      • JSEval
        Esta demostración evalua código JavaScript usando el V8Context.
      • JSExecutingFunctions
        Esta demostración muestra como registrar y ejecutar functiones de JAvaScript personalizadas con implementaciones nativas.
      • JSExtension
        Demostración que muestra como registrar una extensión de JavaScript básica con una función y como enviar información entre procesos.
      • JSExtensionWithFunction
        Demostración que muestra como registrar una extensión de JavaScript con una función que devuelve un valor.
      • JSExtensionWithObjectParameter
        Demostración que muestra como registrar una extensión de JavaScript con una función que tiene un parámetro.
      • JSSimpleExtension
        Demostración que registra una extensión que asigna un valor a una variable.
      • JSSimpleWindowBinding
        Esta demostración muestra como asignar valores al objeto window del frame.
      • JSWindowBindingSubProcess
        Esta demostración es similar a JSSimpleWindowBinding pero usando un ejecutable diferente para los subprocesos.
      • JSWindowBindingWithArrayBuffer
        Esta demostración es similar a JSSimpleWindowBinding pero asigna un valor con un buffer que contiene un array.
      • JSWindowBindingWithFunction
        Demostración que vincula una función al objeto window.
      • JSWindowBindingWithObject
        Esta demostración es similar a JSSimpleWindowBinding pero asigna un valor con un objeto.
    • MediaRouter
      Demostración que muesta como descubrir dispositivos multimedia en la red local y como enviar mensajes.
    • MiniBrowser
      Un navegador web que usa los componentes TChromium y TCEFWindowParent. Tiene menú contextual personalizado, interfaz de navegador básica, herramientas de desarrollo, zoom, impresión, configuración de proxy y algunas funciones extra para copiar el HTML e imprimir desde JavaScript.
    • OAuth2Tester
      Autenticación de usuarios con OAuth 2.0 y peticiones a REST API usando los componentes TCEFServerComponent y TCEFUrlRequestClientComponent.
    • OSRExternalPumpBrowser
      Navegador en modo OSR que usa un surtidor de mensajes externo.
    • PopupBrowser
      Esta demostración muestra como usar forms personalizados con las ventanas emergentes en modo OSR.
    • PopupBrowser2
      Esta demostración muestra como usar forms personalizados con las ventanas emergentes en modo normal.
    • PostInspectorBrowser
      Navegador web con un inspector de los datos de peticiones POST.
    • SchemeRegistrationBrowser
      Registro de un esquema de URL que muestra páginas web personalizadas.
    • SimpleBrowser
      El navegador web más simple hecho con CEF4Delphi. Utiliza un componente TChromiumWindow.
    • SimpleBrowser2
      El navegador web más simple hecho con CEF4Delphi. Utiliza una combinación de dos componentes : TChromium y TCEFWindowParent.
    • SimpleExternalPumpBrowser
      Navegador hecho con el componente TChromiumWindow que usa un surtidor de mensajes externo.
    • SimpleOSRBrowser
      Un navegador web que usa TChromium en modo OSR en caso de que necesite renderizado fuera de pantalla.
    • SimpleServer
      Servidor HTTP y websockets hecho con el componente TCEFServerComponent para la comunicación entre aplicaciones locales.
    • SubProcess
      Navegador que usa un ejecutable diferente para los subprocesos de CEF.
    • TabbedBrowser
      Multiples componentes TChromium y TCEFWindowParent en pestañas.
    • TabbedBrowser2
      Multiples componentes TChromium y TCEFWindowParent dentro de un TFrame y con pestañas.
    • TinyBrowser
      Un minúsculo navegador creado con Views Framework sin usar LCL.
    • TinyBrowser2
      Navegador extremadamente simple similar a cefsimple en el proyecto CEF.
    • ToolBoxBrowser
      Multiples componentes TChromium en una aplicación usando ventanas de tipo ToolBox.
    • ToolBoxBrowser2
      Un navegador simple en una ventana secundaria creados con Views Framework.
    • URLRequest
      Demostración de uso del componente TCEFUrlRequestClientComponent para realizar peticiones URL.
    • WebpageSnapshot
      Aplicación de escritorio que crea un navegador OSR en un hilo y toma una captura de pantalla.

Para probar las demostraciones de Windows y Linux siga estos pasos :

  1. Descargar los archivos binarios de CEF usados por CEF4Delphi siguiendo esta guía.
  2. Descomprimir el archivo con los archivos binarios de CEF en un directorio temporal.
  3. Copiar los contenidos de los directorios Release y Resources al directorio BIN de CEF4Delphi.
  4. Compilar la demostración.
  5. Ejecutar la demostración.

Para probar las demostraciones de MacOS siga las instrucciones dadas en la sección de MacOS de Construyendo la primera demo.

Depurado

El uso de múltiples procesos puede dificultar la depuración en Delphi pero en esos casos se pueden usar las siguientes herramientas :

  • Dar valor de True a GlobalCEFApp.SingleProcess antes de la llamada a GlobalCEFApp.StartMainProcess en el archivo DPR. De esta manera solo se usa un proceso y Delphi puede depurarlo sin problemas. Este modo solo debería usarse para depurar y nunca en versiones finales de la aplicación.
  • Ustilizar varios procesos pero usando la opción de Run→Run Without Debugging... en Delphi. Posteriormente seleccionar Run→Attach To Process... y seleccionar el proceso que se desea depurar.
  • Usar el archivo debug.log para registrar mensajes de texto personalizables con la funcion CefLog como se hace en la demo DOMVisitor. Es necesario dar valores a GlobalCEFApp.LogFile y GlobalCEFApp.LogSeverity antes de la llamada a GlobalCEFApp.StartMainProcess en el archivo DPR.
  • En caso de usar javascript se pueden usar las herramientas de depurado DevTools para ver los mensajes de consola y depurar el código javascript. La demo MiniBrowser tiene todo lo necesario para añadir DevTools a una aplicación.

Codecs

Debido a problemas de licencias y a la ley de patentes de EE.UU., los archivos de CEF disponibles en Spotify tienen desactivados los codecs privativos. Si usa esos archivos, los sitios web que ofrezcan multimedia usando H264 no funcionarán.

En el caso de que necesite usar esos codecs puede compilar usted mismo los archivos de CEF siguiendo las instrucciones de este hilo del foro.

Para compilar los archivos de CEF es necesario usar un PC de gran rendimiento. Puede llevar varias horas incluso con una cpu Intel I7 con 16GB de RAM. Se recomienda tener 32GB de RAM y usar una unidad de almacenamiento SSD.

Lea los artículos 'Quick Start', 'Branches And Building' y 'Automated Build Setup' en las páginas Wiki de CEF antes de intentar compilarlos.

Las fuentes de CEF usadas para la compilaci$ón deben tener exactamente la misma versió:n soportada por CEF4Delphi en ese momento.

Una versión reducida de la guía para compilar CEF está disponible en este hilo del foro.

Complementos y extensiones de navegador

El complemento PPAPI de Adobe Flash ya no está soportado. Los complementos NaCl y NPAPI, junto a las extensiones están soportados parcialmente.

Google no soporta complementos NPAPI desde la versión 45 de Chromium, publicada en septiembre de 2015. Solo las ramas anteriores a 2454 de CEF soportan complementos NPAPI para Java, Silverlight o Facebook video.

Sobre el nombre

CEF4Delphi es solo un numerónimo y se debería interpretar como CEF for Delphi, es decir CEF para Delphi en español. No significa que esté basado en CEF4.

Más información en otros idiomas

Cómo ayudar

Si desea ayudar en este proyecto puede realizar una donación pulsando el siguiente botón :

También puede usar Patreon para ayudar a este proyecto :

Patreon

O patrocinar este proyecto en GitHub :

También puede ayudar dando a conocer este proyecto a sus amistades, compartiendo los mensajes de este proyecto en las redes sociales, escribiendo artículos sobre este proyecto en su página web, haciendo sugerencias, informando sobre errores, etc.

Si realiza compras en Internet también puede ayudar usando estos enlaces para sus compras :




Artículo actualizado el 5 de mayo de 2021.


Copyright © 2021  Todos los derechos reservados.
Uso de cookies

Por el hecho de navegar en este sitio acepta usar nuestras cookies. Solo verá este mensaje una vez.
Más información
Cerrar