diff --git a/bin/PopupBrowser.html b/bin/PopupBrowser.html
new file mode 100644
index 00000000..833447cd
--- /dev/null
+++ b/bin/PopupBrowser.html
@@ -0,0 +1,20 @@
+
+
+
+
+The following button opens google.com in a popup window.
+
+
+
+
+
+
\ No newline at end of file
diff --git a/demos/PopupBrowser/00-DeleteDCUs.bat b/demos/PopupBrowser/00-DeleteDCUs.bat
new file mode 100644
index 00000000..dbd008bc
--- /dev/null
+++ b/demos/PopupBrowser/00-DeleteDCUs.bat
@@ -0,0 +1,14 @@
+del /s /q *.dcu
+del /s /q *.exe
+del /s /q *.res
+del /s /q *.log
+del /s /q *.dsk
+del /s /q *.identcache
+del /s /q *.stat
+del /s /q *.local
+del /s /q *.~*
+rmdir Win32\Debug
+rmdir Win32\Release
+rmdir Win32
+rmdir __history
+rmdir __recovery
diff --git a/demos/PopupBrowser/PopupBrowser.dpr b/demos/PopupBrowser/PopupBrowser.dpr
new file mode 100644
index 00000000..bd013623
--- /dev/null
+++ b/demos/PopupBrowser/PopupBrowser.dpr
@@ -0,0 +1,79 @@
+// ************************************************************************
+// ***************************** CEF4Delphi *******************************
+// ************************************************************************
+//
+// CEF4Delphi is based on DCEF3 which uses CEF3 to embed a chromium-based
+// browser in Delphi applications.
+//
+// The original license of DCEF3 still applies to CEF4Delphi.
+//
+// For more information about CEF4Delphi visit :
+// https://www.briskbard.com/index.php?lang=en&pageid=cef
+//
+// Copyright © 2018 Salvador Díaz Fau. All rights reserved.
+//
+// ************************************************************************
+// ************ vvvv Original license and comments below vvvv *************
+// ************************************************************************
+(*
+ * Delphi Chromium Embedded 3
+ *
+ * Usage allowed under the restrictions of the Lesser GNU General Public License
+ * or alternatively the restrictions of the Mozilla Public License 1.1
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
+ * the specific language governing rights and limitations under the License.
+ *
+ * Unit owner : Henri Gourvest
+ * Web site : http://www.progdigy.com
+ * Repository : http://code.google.com/p/delphichromiumembedded/
+ * Group : http://groups.google.com/group/delphichromiumembedded
+ *
+ * Embarcadero Technologies, Inc is not permitted to use or redistribute
+ * this source code without explicit permission.
+ *
+ *)
+
+program PopupBrowser;
+
+{$I cef.inc}
+
+uses
+ {$IFDEF DELPHI16_UP}
+ Vcl.Forms,
+ WinApi.Windows,
+ {$ELSE}
+ Forms,
+ Windows,
+ {$ENDIF }
+ uCEFApplication,
+ uMainForm in 'uMainForm.pas' {MainForm},
+ uChildForm in 'uChildForm.pas' {ChildForm};
+
+{$R *.res}
+
+// CEF3 needs to set the LARGEADDRESSAWARE flag which allows 32-bit processes to use up to 3GB of RAM.
+// If you don't add this flag the rederer process will crash when you try to load large images.
+{$SetPEFlags IMAGE_FILE_LARGE_ADDRESS_AWARE}
+
+begin
+ GlobalCEFApp := TCefApplication.Create;
+ GlobalCEFApp.FlashEnabled := False;
+ GlobalCEFApp.WindowlessRenderingEnabled := True;
+ GlobalCEFApp.EnableHighDPISupport := True;
+ GlobalCEFApp.FastUnload := True;
+ GlobalCEFApp.SitePerProcess := False;
+
+ if GlobalCEFApp.StartMainProcess then
+ begin
+ Application.Initialize;
+ {$IFDEF DELPHI11_UP}
+ Application.MainFormOnTaskbar := True;
+ {$ENDIF}
+ Application.CreateForm(TMainForm, MainForm);
+ Application.Run;
+ end;
+
+ GlobalCEFApp.Free;
+end.
diff --git a/demos/PopupBrowser/PopupBrowser.dproj b/demos/PopupBrowser/PopupBrowser.dproj
new file mode 100644
index 00000000..820c9a89
--- /dev/null
+++ b/demos/PopupBrowser/PopupBrowser.dproj
@@ -0,0 +1,601 @@
+
+
+ {55E00327-9D98-4DA3-A4E1-844942A01C6B}
+ 18.2
+ VCL
+ PopupBrowser.dpr
+ True
+ Debug
+ Win32
+ 1
+ Application
+
+
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=
+ 3082
+ PopupBrowser
+ $(BDS)\bin\delphi_PROJECTICON.ico
+ System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace)
+ .\$(Platform)\$(Config)
+ false
+ false
+ false
+ false
+ false
+
+
+ DBXSqliteDriver;RESTComponents;DataSnapServerMidas;DBXDb2Driver;DBXInterBaseDriver;vclactnband;frxe23;vclFireDAC;emsclientfiredac;DataSnapFireDAC;svnui;tethering;Componentes;FireDACADSDriver;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;svn;Intraweb;DBXOracleDriver;inetdb;Componentes_Int;CEF4Delphi;FmxTeeUI;FireDACIBDriver;fmx;fmxdae;vclib;FireDACDBXDriver;dbexpress;IndyProtocols230;vclx;dsnap;DataSnapCommon;emsclient;FireDACCommon;RESTBackendComponents;DataSnapConnectors;VCLRESTComponents;soapserver;frxTee23;vclie;bindengine;DBXMySQLDriver;FireDACOracleDriver;CloudService;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonDriver;DataSnapClient;inet;bindcompdbx;vcl;DBXSybaseASEDriver;FireDACDb2Driver;dsnapcon;FireDACMSAccDriver;fmxFireDAC;FireDACInfxDriver;vclimg;Componentes_UI;TeeDB;FireDAC;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;FMXTee;soaprtl;DbxCommonDriver;Componentes_Misc;ibxpress;Tee;DataSnapServer;xmlrtl;soapmidas;DataSnapNativeClient;fmxobj;vclwinx;ibxbindings;rtl;FireDACDSDriver;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;vcldsnap;bindcomp;appanalytics;Componentes_RTF;DBXInformixDriver;bindcompvcl;frxDB23;Componentes_vCard;TeeUI;IndyCore230;vclribbon;dbxcds;VclSmp;adortl;FireDACODBCDriver;DataSnapIndy10ServerTransport;IndySystem230;dsnapxml;DataSnapProviderClient;dbrtl;inetdbxpress;FireDACMongoDBDriver;frx23;fmxase;$(DCC_UsePackage)
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
+ true
+ $(BDS)\bin\default_app.manifest
+ 1033
+ CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName);FileDescription=$(MSBuildProjectName);ProductName=$(MSBuildProjectName)
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+ ..\..\bin
+
+
+ DBXSqliteDriver;RESTComponents;DataSnapServerMidas;DBXDb2Driver;DBXInterBaseDriver;vclactnband;vclFireDAC;emsclientfiredac;DataSnapFireDAC;tethering;FireDACADSDriver;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;Intraweb;DBXOracleDriver;inetdb;FmxTeeUI;FireDACIBDriver;fmx;fmxdae;vclib;FireDACDBXDriver;dbexpress;IndyProtocols230;vclx;dsnap;DataSnapCommon;emsclient;FireDACCommon;RESTBackendComponents;DataSnapConnectors;VCLRESTComponents;soapserver;vclie;bindengine;DBXMySQLDriver;FireDACOracleDriver;CloudService;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonDriver;DataSnapClient;inet;bindcompdbx;vcl;DBXSybaseASEDriver;FireDACDb2Driver;dsnapcon;FireDACMSAccDriver;fmxFireDAC;FireDACInfxDriver;vclimg;TeeDB;FireDAC;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;FMXTee;soaprtl;DbxCommonDriver;ibxpress;Tee;DataSnapServer;xmlrtl;soapmidas;DataSnapNativeClient;fmxobj;vclwinx;ibxbindings;rtl;FireDACDSDriver;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;vcldsnap;bindcomp;appanalytics;DBXInformixDriver;bindcompvcl;TeeUI;IndyCore230;vclribbon;dbxcds;VclSmp;adortl;FireDACODBCDriver;DataSnapIndy10ServerTransport;IndySystem230;dsnapxml;DataSnapProviderClient;dbrtl;inetdbxpress;FireDACMongoDBDriver;fmxase;$(DCC_UsePackage)
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)
+ Debug
+ true
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
+ 1033
+ $(BDS)\bin\default_app.manifest
+
+
+ DEBUG;$(DCC_Define)
+ true
+ false
+ true
+ true
+ true
+
+
+ true
+ 1033
+ true
+ true
+ false
+ Debug
+ CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName);FileDescription=$(MSBuildProjectName);ProductName=$(MSBuildProjectName)
+
+
+ true
+ true
+
+
+ false
+ RELEASE;$(DCC_Define)
+ 0
+ 0
+
+
+ true
+ true
+
+
+ true
+ true
+
+
+
+ MainSource
+
+
+
+
+
+
+ dfm
+
+
+ Cfg_2
+ Base
+
+
+ Base
+
+
+ Cfg_1
+ Base
+
+
+
+ Delphi.Personality.12
+ Application
+
+
+
+
+ IP Abstraction Indy Implementation Design Time
+ Microsoft Office 2000 Sample Automation Server Wrapper Components
+ Microsoft Office XP Sample Automation Server Wrapper Components
+
+
+
+
+
+
+ PopupBrowser.exe
+ true
+
+
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ Contents\MacOS
+ 0
+
+
+
+
+ classes
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ library\lib\armeabi
+ 1
+
+
+
+
+ library\lib\mips
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+
+
+ res\drawable-ldpi
+ 1
+
+
+
+
+ res\drawable-mdpi
+ 1
+
+
+
+
+ res\drawable-hdpi
+ 1
+
+
+
+
+ res\drawable-xhdpi
+ 1
+
+
+
+
+ res\drawable-small
+ 1
+
+
+
+
+ res\drawable-normal
+ 1
+
+
+
+
+ res\drawable-large
+ 1
+
+
+
+
+ res\drawable-xlarge
+ 1
+
+
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ 0
+
+
+
+
+ Contents\MacOS
+ 1
+ .framework
+
+
+ 0
+
+
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 0
+ .dll;.bpl
+
+
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 0
+ .bpl
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ Contents\Resources\StartUp\
+ 0
+
+
+ 0
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+
+
+ Contents
+ 1
+
+
+
+
+ Contents\Resources
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ 0
+
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+ Assets
+ 1
+
+
+ Assets
+ 1
+
+
+
+
+ Assets
+ 1
+
+
+ Assets
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ False
+
+
+ 12
+
+
+
+
+
diff --git a/demos/PopupBrowser/cef.inc b/demos/PopupBrowser/cef.inc
new file mode 100644
index 00000000..984ae795
--- /dev/null
+++ b/demos/PopupBrowser/cef.inc
@@ -0,0 +1,384 @@
+// ************************************************************************
+// ***************************** CEF4Delphi *******************************
+// ************************************************************************
+//
+// CEF4Delphi is based on DCEF3 which uses CEF3 to embed a chromium-based
+// browser in Delphi applications.
+//
+// The original license of DCEF3 still applies to CEF4Delphi.
+//
+// For more information about CEF4Delphi visit :
+// https://www.briskbard.com/index.php?lang=en&pageid=cef
+//
+// Copyright © 2017 Salvador Díaz Fau. All rights reserved.
+//
+// ************************************************************************
+// ************ vvvv Original license and comments below vvvv *************
+// ************************************************************************
+(*
+ * Delphi Chromium Embedded 3
+ *
+ * Usage allowed under the restrictions of the Lesser GNU General Public License
+ * or alternatively the restrictions of the Mozilla Public License 1.1
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
+ * the specific language governing rights and limitations under the License.
+ *
+ * Unit owner : Henri Gourvest
+ * Web site : http://www.progdigy.com
+ * Repository : http://code.google.com/p/delphichromiumembedded/
+ * Group : http://groups.google.com/group/delphichromiumembedded
+ *
+ * Embarcadero Technologies, Inc is not permitted to use or redistribute
+ * this source code without explicit permission.
+ *
+ *)
+
+ // The complete list of compiler versions is here :
+ // http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Compiler_Versions
+
+{$DEFINE DELPHI_VERSION_UNKNOW}
+
+{$IFDEF FPC}
+ {$DEFINE CEF_MULTI_THREADED_MESSAGE_LOOP}
+ {$DEFINE SUPPORTS_INLINE}
+{$ENDIF}
+
+// Delphi 5
+{$IFDEF VER130}
+ {$UNDEF DELPHI_VERSION_UNKNOW}
+ {$DEFINE DELPHI5_UP}
+{$ENDIF}
+
+// Delphi 6
+{$IFDEF VER140}
+ {$UNDEF DELPHI_VERSION_UNKNOW}
+ {$DEFINE DELPHI5_UP}
+ {$DEFINE DELPHI6_UP}
+{$ENDIF}
+
+// Delphi 7
+{$IFDEF VER150}
+ {$UNDEF DELPHI_VERSION_UNKNOW}
+ {$DEFINE DELPHI5_UP}
+ {$DEFINE DELPHI6_UP}
+ {$DEFINE DELPHI7_UP}
+{$ENDIF}
+
+// Delphi 8
+{$IFDEF VER160}
+ {$UNDEF DELPHI_VERSION_UNKNOW}
+ {$DEFINE DELPHI5_UP}
+ {$DEFINE DELPHI6_UP}
+ {$DEFINE DELPHI7_UP}
+ {$DEFINE DELPHI8_UP}
+{$ENDIF}
+
+// Delphi 2005
+{$IFDEF VER170}
+ {$UNDEF DELPHI_VERSION_UNKNOW}
+ {$DEFINE DELPHI5_UP}
+ {$DEFINE DELPHI6_UP}
+ {$DEFINE DELPHI7_UP}
+ {$DEFINE DELPHI8_UP}
+ {$DEFINE DELPHI9_UP}
+{$ENDIF}
+
+{$IFDEF VER180}
+ {$UNDEF DELPHI_VERSION_UNKNOW}
+ // Delphi 2007
+ {$IFDEF VER185}
+ {$DEFINE DELPHI5_UP}
+ {$DEFINE DELPHI6_UP}
+ {$DEFINE DELPHI7_UP}
+ {$DEFINE DELPHI8_UP}
+ {$DEFINE DELPHI9_UP}
+ {$DEFINE DELPHI10_UP}
+ {$DEFINE DELPHI11_UP}
+ // Delphi 2006
+ {$ELSE}
+ {$DEFINE DELPHI5_UP}
+ {$DEFINE DELPHI6_UP}
+ {$DEFINE DELPHI7_UP}
+ {$DEFINE DELPHI8_UP}
+ {$DEFINE DELPHI9_UP}
+ {$DEFINE DELPHI10_UP}
+ {$ENDIF}
+{$ENDIF}
+
+// Delphi 2009
+{$IFDEF VER200}
+ {$UNDEF DELPHI_VERSION_UNKNOW}
+ {$DEFINE DELPHI5_UP}
+ {$DEFINE DELPHI6_UP}
+ {$DEFINE DELPHI7_UP}
+ {$DEFINE DELPHI8_UP}
+ {$DEFINE DELPHI9_UP}
+ {$DEFINE DELPHI10_UP}
+ {$DEFINE DELPHI11_UP}
+ {$DEFINE DELPHI12_UP}
+{$ENDIF}
+
+//Delphi 2010
+{$IFDEF VER210}
+ {$UNDEF DELPHI_VERSION_UNKNOW}
+ {$DEFINE DELPHI5_UP}
+ {$DEFINE DELPHI6_UP}
+ {$DEFINE DELPHI7_UP}
+ {$DEFINE DELPHI8_UP}
+ {$DEFINE DELPHI9_UP}
+ {$DEFINE DELPHI10_UP}
+ {$DEFINE DELPHI11_UP}
+ {$DEFINE DELPHI12_UP}
+ {$DEFINE DELPHI14_UP}
+{$ENDIF}
+
+// Delphi XE
+{$IFDEF VER220}
+ {$UNDEF DELPHI_VERSION_UNKNOW}
+ {$DEFINE DELPHI5_UP}
+ {$DEFINE DELPHI6_UP}
+ {$DEFINE DELPHI7_UP}
+ {$DEFINE DELPHI8_UP}
+ {$DEFINE DELPHI9_UP}
+ {$DEFINE DELPHI10_UP}
+ {$DEFINE DELPHI11_UP}
+ {$DEFINE DELPHI12_UP}
+ {$DEFINE DELPHI14_UP}
+ {$DEFINE DELPHI15_UP}
+{$ENDIF}
+
+// Delphi XE2
+{$IFDEF VER230}
+ {$UNDEF DELPHI_VERSION_UNKNOW}
+ {$DEFINE DELPHI5_UP}
+ {$DEFINE DELPHI6_UP}
+ {$DEFINE DELPHI7_UP}
+ {$DEFINE DELPHI8_UP}
+ {$DEFINE DELPHI9_UP}
+ {$DEFINE DELPHI10_UP}
+ {$DEFINE DELPHI11_UP}
+ {$DEFINE DELPHI12_UP}
+ {$DEFINE DELPHI14_UP}
+ {$DEFINE DELPHI15_UP}
+ {$DEFINE DELPHI16_UP}
+{$ENDIF}
+
+// Delphi XE3
+{$IFDEF VER240}
+ {$UNDEF DELPHI_VERSION_UNKNOW}
+ {$DEFINE DELPHI5_UP}
+ {$DEFINE DELPHI6_UP}
+ {$DEFINE DELPHI7_UP}
+ {$DEFINE DELPHI8_UP}
+ {$DEFINE DELPHI9_UP}
+ {$DEFINE DELPHI10_UP}
+ {$DEFINE DELPHI11_UP}
+ {$DEFINE DELPHI12_UP}
+ {$DEFINE DELPHI14_UP}
+ {$DEFINE DELPHI15_UP}
+ {$DEFINE DELPHI16_UP}
+ {$DEFINE DELPHI17_UP}
+{$ENDIF}
+
+// Delphi XE4
+{$IFDEF VER250}
+ {$UNDEF DELPHI_VERSION_UNKNOW}
+ {$DEFINE DELPHI5_UP}
+ {$DEFINE DELPHI6_UP}
+ {$DEFINE DELPHI7_UP}
+ {$DEFINE DELPHI8_UP}
+ {$DEFINE DELPHI9_UP}
+ {$DEFINE DELPHI10_UP}
+ {$DEFINE DELPHI11_UP}
+ {$DEFINE DELPHI12_UP}
+ {$DEFINE DELPHI14_UP}
+ {$DEFINE DELPHI15_UP}
+ {$DEFINE DELPHI16_UP}
+ {$DEFINE DELPHI17_UP}
+ {$DEFINE DELPHI18_UP}
+{$ENDIF}
+
+// Delphi XE5
+{$IFDEF VER260}
+ {$UNDEF DELPHI_VERSION_UNKNOW}
+ {$DEFINE DELPHI5_UP}
+ {$DEFINE DELPHI6_UP}
+ {$DEFINE DELPHI7_UP}
+ {$DEFINE DELPHI8_UP}
+ {$DEFINE DELPHI9_UP}
+ {$DEFINE DELPHI10_UP}
+ {$DEFINE DELPHI11_UP}
+ {$DEFINE DELPHI12_UP}
+ {$DEFINE DELPHI14_UP}
+ {$DEFINE DELPHI15_UP}
+ {$DEFINE DELPHI16_UP}
+ {$DEFINE DELPHI17_UP}
+ {$DEFINE DELPHI18_UP}
+ {$DEFINE DELPHI19_UP}
+{$ENDIF}
+
+// Delphi XE6
+{$IFDEF VER270}
+ {$UNDEF DELPHI_VERSION_UNKNOW}
+ {$DEFINE DELPHI5_UP}
+ {$DEFINE DELPHI6_UP}
+ {$DEFINE DELPHI7_UP}
+ {$DEFINE DELPHI8_UP}
+ {$DEFINE DELPHI9_UP}
+ {$DEFINE DELPHI10_UP}
+ {$DEFINE DELPHI11_UP}
+ {$DEFINE DELPHI12_UP}
+ {$DEFINE DELPHI14_UP}
+ {$DEFINE DELPHI15_UP}
+ {$DEFINE DELPHI16_UP}
+ {$DEFINE DELPHI17_UP}
+ {$DEFINE DELPHI18_UP}
+ {$DEFINE DELPHI19_UP}
+ {$DEFINE DELPHI20_UP}
+{$ENDIF}
+
+// Delphi XE7
+{$IFDEF VER280}
+ {$UNDEF DELPHI_VERSION_UNKNOW}
+ {$DEFINE DELPHI5_UP}
+ {$DEFINE DELPHI6_UP}
+ {$DEFINE DELPHI7_UP}
+ {$DEFINE DELPHI8_UP}
+ {$DEFINE DELPHI9_UP}
+ {$DEFINE DELPHI10_UP}
+ {$DEFINE DELPHI11_UP}
+ {$DEFINE DELPHI12_UP}
+ {$DEFINE DELPHI14_UP}
+ {$DEFINE DELPHI15_UP}
+ {$DEFINE DELPHI16_UP}
+ {$DEFINE DELPHI17_UP}
+ {$DEFINE DELPHI18_UP}
+ {$DEFINE DELPHI19_UP}
+ {$DEFINE DELPHI20_UP}
+ {$DEFINE DELPHI21_UP}
+{$ENDIF}
+
+// Delphi XE8
+{$IFDEF VER290}
+ {$UNDEF DELPHI_VERSION_UNKNOW}
+ {$DEFINE DELPHI5_UP}
+ {$DEFINE DELPHI6_UP}
+ {$DEFINE DELPHI7_UP}
+ {$DEFINE DELPHI8_UP}
+ {$DEFINE DELPHI9_UP}
+ {$DEFINE DELPHI10_UP}
+ {$DEFINE DELPHI11_UP}
+ {$DEFINE DELPHI12_UP}
+ {$DEFINE DELPHI14_UP}
+ {$DEFINE DELPHI15_UP}
+ {$DEFINE DELPHI16_UP}
+ {$DEFINE DELPHI17_UP}
+ {$DEFINE DELPHI18_UP}
+ {$DEFINE DELPHI19_UP}
+ {$DEFINE DELPHI20_UP}
+ {$DEFINE DELPHI21_UP}
+ {$DEFINE DELPHI22_UP}
+{$ENDIF VER290}
+
+// Rad Studio 10 - Delphi Seattle
+{$IFDEF VER300}
+ {$UNDEF DELPHI_VERSION_UNKNOW}
+ {$DEFINE DELPHI5_UP}
+ {$DEFINE DELPHI6_UP}
+ {$DEFINE DELPHI7_UP}
+ {$DEFINE DELPHI8_UP}
+ {$DEFINE DELPHI9_UP}
+ {$DEFINE DELPHI10_UP}
+ {$DEFINE DELPHI11_UP}
+ {$DEFINE DELPHI12_UP}
+ {$DEFINE DELPHI14_UP}
+ {$DEFINE DELPHI15_UP}
+ {$DEFINE DELPHI16_UP}
+ {$DEFINE DELPHI17_UP}
+ {$DEFINE DELPHI18_UP}
+ {$DEFINE DELPHI19_UP}
+ {$DEFINE DELPHI20_UP}
+ {$DEFINE DELPHI21_UP}
+ {$DEFINE DELPHI22_UP}
+ {$DEFINE DELPHI23_UP}
+{$ENDIF}
+
+// Rad Studio 10.1 - Delphi Berlin
+{$IFDEF VER310}
+ {$UNDEF DELPHI_VERSION_UNKNOW}
+ {$DEFINE DELPHI5_UP}
+ {$DEFINE DELPHI6_UP}
+ {$DEFINE DELPHI7_UP}
+ {$DEFINE DELPHI8_UP}
+ {$DEFINE DELPHI9_UP}
+ {$DEFINE DELPHI10_UP}
+ {$DEFINE DELPHI11_UP}
+ {$DEFINE DELPHI12_UP}
+ {$DEFINE DELPHI14_UP}
+ {$DEFINE DELPHI15_UP}
+ {$DEFINE DELPHI16_UP}
+ {$DEFINE DELPHI17_UP}
+ {$DEFINE DELPHI18_UP}
+ {$DEFINE DELPHI19_UP}
+ {$DEFINE DELPHI20_UP}
+ {$DEFINE DELPHI21_UP}
+ {$DEFINE DELPHI22_UP}
+ {$DEFINE DELPHI23_UP}
+ {$DEFINE DELPHI24_UP}
+{$ENDIF}
+
+// Rad Studio 10.2 - Delphi Tokyo
+{$IFDEF VER320}
+ {$UNDEF DELPHI_VERSION_UNKNOW}
+ {$DEFINE DELPHI5_UP}
+ {$DEFINE DELPHI6_UP}
+ {$DEFINE DELPHI7_UP}
+ {$DEFINE DELPHI8_UP}
+ {$DEFINE DELPHI9_UP}
+ {$DEFINE DELPHI10_UP}
+ {$DEFINE DELPHI11_UP}
+ {$DEFINE DELPHI12_UP}
+ {$DEFINE DELPHI14_UP}
+ {$DEFINE DELPHI15_UP}
+ {$DEFINE DELPHI16_UP}
+ {$DEFINE DELPHI17_UP}
+ {$DEFINE DELPHI18_UP}
+ {$DEFINE DELPHI19_UP}
+ {$DEFINE DELPHI20_UP}
+ {$DEFINE DELPHI21_UP}
+ {$DEFINE DELPHI22_UP}
+ {$DEFINE DELPHI23_UP}
+ {$DEFINE DELPHI24_UP}
+ {$DEFINE DELPHI25_UP}
+{$ENDIF}
+
+
+{$IFDEF DELPHI_VERSION_UNKNOW}
+ {$DEFINE DELPHI5_UP}
+ {$DEFINE DELPHI6_UP}
+ {$DEFINE DELPHI7_UP}
+ {$DEFINE DELPHI8_UP}
+ {$DEFINE DELPHI9_UP}
+ {$DEFINE DELPHI10_UP}
+ {$DEFINE DELPHI11_UP}
+ {$DEFINE DELPHI12_UP}
+ {$DEFINE DELPHI14_UP}
+ {$DEFINE DELPHI15_UP}
+ {$DEFINE DELPHI16_UP}
+ {$DEFINE DELPHI17_UP}
+ {$DEFINE DELPHI18_UP}
+ {$DEFINE DELPHI19_UP}
+ {$DEFINE DELPHI20_UP}
+ {$DEFINE DELPHI21_UP}
+ {$DEFINE DELPHI22_UP}
+ {$DEFINE DELPHI23_UP}
+ {$DEFINE DELPHI24_UP}
+ {$DEFINE DELPHI25_UP}
+{$ENDIF}
+
+{$IFDEF DELPHI9_UP}
+ {$DEFINE SUPPORTS_INLINE}
+{$ENDIF}
+
diff --git a/demos/PopupBrowser/uChildForm.dfm b/demos/PopupBrowser/uChildForm.dfm
new file mode 100644
index 00000000..4f99bb5e
--- /dev/null
+++ b/demos/PopupBrowser/uChildForm.dfm
@@ -0,0 +1,62 @@
+object ChildForm: TChildForm
+ Left = 0
+ Top = 0
+ Caption = 'Popup'
+ ClientHeight = 256
+ ClientWidth = 352
+ Color = clBtnFace
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = []
+ OldCreateOrder = False
+ Position = poScreenCenter
+ OnAfterMonitorDpiChanged = FormAfterMonitorDpiChanged
+ OnClose = FormClose
+ OnCloseQuery = FormCloseQuery
+ OnCreate = FormCreate
+ OnDestroy = FormDestroy
+ OnHide = FormHide
+ OnShow = FormShow
+ PixelsPerInch = 96
+ TextHeight = 13
+ object Panel1: TBufferPanel
+ Left = 0
+ Top = 0
+ Width = 352
+ Height = 256
+ Align = alClient
+ Caption = 'Panel1'
+ Color = clWhite
+ ParentBackground = False
+ TabOrder = 0
+ TabStop = True
+ OnClick = Panel1Click
+ OnEnter = Panel1Enter
+ OnExit = Panel1Exit
+ OnMouseDown = Panel1MouseDown
+ OnMouseMove = Panel1MouseMove
+ OnMouseUp = Panel1MouseUp
+ OnResize = Panel1Resize
+ OnMouseLeave = Panel1MouseLeave
+ ExplicitWidth = 800
+ ExplicitHeight = 530
+ end
+ object Chromium1: TChromium
+ OnTitleChange = Chromium1TitleChange
+ OnTooltip = Chromium1Tooltip
+ OnBeforePopup = Chromium1BeforePopup
+ OnBeforeClose = Chromium1BeforeClose
+ OnClose = Chromium1Close
+ OnGetViewRect = Chromium1GetViewRect
+ OnGetScreenPoint = Chromium1GetScreenPoint
+ OnGetScreenInfo = Chromium1GetScreenInfo
+ OnPopupShow = Chromium1PopupShow
+ OnPopupSize = Chromium1PopupSize
+ OnPaint = Chromium1Paint
+ OnCursorChange = Chromium1CursorChange
+ Left = 24
+ Top = 56
+ end
+end
diff --git a/demos/PopupBrowser/uChildForm.pas b/demos/PopupBrowser/uChildForm.pas
new file mode 100644
index 00000000..7e529b6c
--- /dev/null
+++ b/demos/PopupBrowser/uChildForm.pas
@@ -0,0 +1,821 @@
+// ************************************************************************
+// ***************************** CEF4Delphi *******************************
+// ************************************************************************
+//
+// CEF4Delphi is based on DCEF3 which uses CEF3 to embed a chromium-based
+// browser in Delphi applications.
+//
+// The original license of DCEF3 still applies to CEF4Delphi.
+//
+// For more information about CEF4Delphi visit :
+// https://www.briskbard.com/index.php?lang=en&pageid=cef
+//
+// Copyright © 2018 Salvador Díaz Fau. All rights reserved.
+//
+// ************************************************************************
+// ************ vvvv Original license and comments below vvvv *************
+// ************************************************************************
+(*
+ * Delphi Chromium Embedded 3
+ *
+ * Usage allowed under the restrictions of the Lesser GNU General Public License
+ * or alternatively the restrictions of the Mozilla Public License 1.1
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
+ * the specific language governing rights and limitations under the License.
+ *
+ * Unit owner : Henri Gourvest
+ * Web site : http://www.progdigy.com
+ * Repository : http://code.google.com/p/delphichromiumembedded/
+ * Group : http://groups.google.com/group/delphichromiumembedded
+ *
+ * Embarcadero Technologies, Inc is not permitted to use or redistribute
+ * this source code without explicit permission.
+ *
+ *)
+
+unit uChildForm;
+
+{$I cef.inc}
+
+interface
+
+uses
+ {$IFDEF DELPHI16_UP}
+ Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
+ System.SyncObjs, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
+ Vcl.ExtCtrls, Vcl.AppEvnts,
+ {$ELSE}
+ Windows, Messages, SysUtils, Variants, Classes, SyncObjs,
+ Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, AppEvnts,
+ {$ENDIF}
+ uCEFChromium, uCEFTypes, uCEFInterfaces, uCEFConstants, uBufferPanel;
+
+const
+ CEF_SHOWCHILD = WM_APP + $A52;
+
+type
+ TChildForm = class(TForm)
+ Chromium1: TChromium;
+ Panel1: TBufferPanel;
+
+ procedure Panel1Enter(Sender: TObject);
+ procedure Panel1Exit(Sender: TObject);
+ procedure Panel1Resize(Sender: TObject);
+ procedure Panel1Click(Sender: TObject);
+ procedure Panel1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
+ procedure Panel1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
+ procedure Panel1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
+ procedure Panel1MouseLeave(Sender: TObject);
+
+ procedure FormCreate(Sender: TObject);
+ procedure FormDestroy(Sender: TObject);
+ procedure FormShow(Sender: TObject);
+ procedure FormHide(Sender: TObject);
+ procedure FormAfterMonitorDpiChanged(Sender: TObject; OldDPI, NewDPI: Integer);
+ procedure FormClose(Sender: TObject; var Action: TCloseAction);
+ procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
+
+ procedure Chromium1Paint(Sender: TObject; const browser: ICefBrowser; kind: TCefPaintElementType; dirtyRectsCount: NativeUInt; const dirtyRects: PCefRectArray; const buffer: Pointer; width, height: Integer);
+ procedure Chromium1CursorChange(Sender: TObject; const browser: ICefBrowser; cursor: HICON; cursorType: TCefCursorType; const customCursorInfo: PCefCursorInfo);
+ procedure Chromium1GetViewRect(Sender: TObject; const browser: ICefBrowser; var rect: TCefRect; out Result: Boolean);
+ procedure Chromium1GetScreenPoint(Sender: TObject; const browser: ICefBrowser; viewX, viewY: Integer; var screenX, screenY: Integer; out Result: Boolean);
+ procedure Chromium1GetScreenInfo(Sender: TObject; const browser: ICefBrowser; var screenInfo: TCefScreenInfo; out Result: Boolean);
+ procedure Chromium1PopupShow(Sender: TObject; const browser: ICefBrowser; show: Boolean);
+ procedure Chromium1PopupSize(Sender: TObject; const browser: ICefBrowser; const rect: PCefRect);
+ procedure Chromium1Tooltip(Sender: TObject; const browser: ICefBrowser; var text: ustring; out Result: Boolean);
+ procedure Chromium1BeforePopup(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; const targetUrl, targetFrameName: ustring; targetDisposition: TCefWindowOpenDisposition; userGesture: Boolean; var popupFeatures: TCefPopupFeatures; var windowInfo: TCefWindowInfo; var client: ICefClient; var settings: TCefBrowserSettings; var noJavascriptAccess: Boolean; out Result: Boolean);
+ procedure Chromium1TitleChange(Sender: TObject; const browser: ICefBrowser; const title: ustring);
+ procedure Chromium1Close(Sender: TObject; const browser: ICefBrowser; out Result: Boolean);
+ procedure Chromium1BeforeClose(Sender: TObject; const browser: ICefBrowser);
+
+ protected
+ FPopUpBitmap : TBitmap;
+ FPopUpRect : TRect;
+ FShowPopUp : boolean;
+ FResizing : boolean;
+ FPendingResize : boolean;
+ FCanClose : boolean;
+ FClosing : boolean;
+ FClientInitialized : boolean;
+ FResizeCS : TCriticalSection;
+ FPopupFeatures : TCefPopupFeatures;
+
+ function getModifiers(Shift: TShiftState): TCefEventFlags;
+ function GetButton(Button: TMouseButton): TCefMouseButtonType;
+ procedure ApplyPopupFeatures;
+ procedure DoResize;
+
+ procedure WMMove(var aMessage : TWMMove); message WM_MOVE;
+ procedure WMMoving(var aMessage : TMessage); message WM_MOVING;
+ procedure WMCaptureChanged(var aMessage : TMessage); message WM_CAPTURECHANGED;
+ procedure WMCancelMode(var aMessage : TMessage); message WM_CANCELMODE;
+ procedure WMEnterMenuLoop(var aMessage: TMessage); message WM_ENTERMENULOOP;
+ procedure WMExitMenuLoop(var aMessage: TMessage); message WM_EXITMENULOOP;
+ procedure PendingResizeMsg(var aMessage : TMessage); message CEF_PENDINGRESIZE;
+ procedure ShowChildMsg(var aMessage : TMessage); message CEF_SHOWCHILD;
+
+ public
+ function CreateClientHandler(var windowInfo : TCefWindowInfo; var client : ICefClient; const targetFrameName : string; const popupFeatures : TCefPopupFeatures) : boolean;
+
+ procedure HandleSysCharMsg(var Msg: tagMSG; var Handled: Boolean);
+ procedure HandleSysKeyDownMsg(var Msg: tagMSG; var Handled: Boolean);
+ procedure HandleSysKeyUpMsg(var Msg: tagMSG; var Handled: Boolean);
+ procedure HandleKeyDownMsg(var Msg: tagMSG; var Handled: Boolean);
+ procedure HandleKeyUpMsg(var Msg: tagMSG; var Handled: Boolean);
+ procedure HandleCharMsg(var Msg: tagMSG; var Handled: Boolean);
+ procedure HandleMouseWheelMsg(var Msg: tagMSG; var Handled: Boolean);
+
+ property ClientInitialized : boolean read FClientInitialized;
+ property Closing : boolean read FClosing;
+ end;
+
+implementation
+
+{$R *.dfm}
+
+uses
+ {$IFDEF DELPHI16_UP}
+ System.Math,
+ {$ELSE}
+ Math,
+ {$ENDIF}
+ uCEFMiscFunctions, uCEFApplication, uMainForm;
+
+// This is the destruction sequence in OSR mode :
+// 1- FormCloseQuery sets CanClose to the initial FCanClose value (False) and calls chrmosr.CloseBrowser(True).
+// 2- chrmosr.CloseBrowser(True) will trigger chrmosr.OnClose and we have to
+// set "Result" to false and CEF3 will destroy the internal browser immediately.
+// 3- chrmosr.OnBeforeClose is triggered because the internal browser was destroyed.
+// Now we set FCanClose to True and send WM_CLOSE to the form.
+
+procedure TChildForm.HandleSysCharMsg(var Msg: tagMSG; var Handled: Boolean);
+var
+ TempKeyEvent : TCefKeyEvent;
+begin
+ if Panel1.Focused and (Msg.wParam in [VK_BACK..VK_HELP]) then
+ begin
+ TempKeyEvent.kind := KEYEVENT_CHAR;
+ TempKeyEvent.modifiers := GetCefKeyboardModifiers(Msg.wParam, Msg.lParam);
+ TempKeyEvent.windows_key_code := Msg.wParam;
+ TempKeyEvent.native_key_code := Msg.lParam;
+ TempKeyEvent.is_system_key := ord(True);
+ TempKeyEvent.character := #0;
+ TempKeyEvent.unmodified_character := #0;
+ TempKeyEvent.focus_on_editable_field := ord(False);
+
+ Chromium1.SendKeyEvent(@TempKeyEvent);
+ Handled := True;
+ end
+ else
+ Handled := False;
+end;
+
+procedure TChildForm.HandleSysKeyDownMsg(var Msg: tagMSG; var Handled: Boolean);
+var
+ TempKeyEvent : TCefKeyEvent;
+begin
+ if Panel1.Focused and (Msg.wParam in [VK_BACK..VK_HELP]) then
+ begin
+ TempKeyEvent.kind := KEYEVENT_RAWKEYDOWN;
+ TempKeyEvent.modifiers := GetCefKeyboardModifiers(Msg.wParam, Msg.lParam);
+ TempKeyEvent.windows_key_code := Msg.wParam;
+ TempKeyEvent.native_key_code := Msg.lParam;
+ TempKeyEvent.is_system_key := ord(True);
+ TempKeyEvent.character := #0;
+ TempKeyEvent.unmodified_character := #0;
+ TempKeyEvent.focus_on_editable_field := ord(False);
+
+ Chromium1.SendKeyEvent(@TempKeyEvent);
+ Handled := True;
+ end
+ else
+ Handled := False;
+end;
+
+procedure TChildForm.HandleSysKeyUpMsg(var Msg: tagMSG; var Handled: Boolean);
+var
+ TempKeyEvent : TCefKeyEvent;
+begin
+ if Panel1.Focused and (Msg.wParam in [VK_BACK..VK_HELP]) then
+ begin
+ TempKeyEvent.kind := KEYEVENT_KEYUP;
+ TempKeyEvent.modifiers := GetCefKeyboardModifiers(Msg.wParam, Msg.lParam);
+ TempKeyEvent.windows_key_code := Msg.wParam;
+ TempKeyEvent.native_key_code := Msg.lParam;
+ TempKeyEvent.is_system_key := ord(True);
+ TempKeyEvent.character := #0;
+ TempKeyEvent.unmodified_character := #0;
+ TempKeyEvent.focus_on_editable_field := ord(False);
+
+ Chromium1.SendKeyEvent(@TempKeyEvent);
+ Handled := True;
+ end
+ else
+ Handled := False;
+end;
+
+procedure TChildForm.HandleKeyDownMsg(var Msg: tagMSG; var Handled: Boolean);
+var
+ TempKeyEvent : TCefKeyEvent;
+begin
+ if Panel1.Focused and (Msg.wParam in [VK_BACK..VK_HELP]) then
+ begin
+ TempKeyEvent.kind := KEYEVENT_RAWKEYDOWN;
+ TempKeyEvent.modifiers := GetCefKeyboardModifiers(Msg.wParam, Msg.lParam);
+ TempKeyEvent.windows_key_code := Msg.wParam;
+ TempKeyEvent.native_key_code := Msg.lParam;
+ TempKeyEvent.is_system_key := ord(False);
+ TempKeyEvent.character := #0;
+ TempKeyEvent.unmodified_character := #0;
+ TempKeyEvent.focus_on_editable_field := ord(False);
+
+ Chromium1.SendKeyEvent(@TempKeyEvent);
+ Handled := True;
+ end
+ else
+ Handled := False;
+end;
+
+procedure TChildForm.HandleKeyUpMsg(var Msg: tagMSG; var Handled: Boolean);
+var
+ TempKeyEvent : TCefKeyEvent;
+begin
+ if Panel1.Focused and (Msg.wParam in [VK_BACK..VK_HELP]) then
+ begin
+ TempKeyEvent.kind := KEYEVENT_KEYUP;
+ TempKeyEvent.modifiers := GetCefKeyboardModifiers(Msg.wParam, Msg.lParam);
+ TempKeyEvent.windows_key_code := Msg.wParam;
+ TempKeyEvent.native_key_code := Msg.lParam;
+ TempKeyEvent.is_system_key := ord(False);
+ TempKeyEvent.character := #0;
+ TempKeyEvent.unmodified_character := #0;
+ TempKeyEvent.focus_on_editable_field := ord(False);
+
+ Chromium1.SendKeyEvent(@TempKeyEvent);
+ Handled := True;
+ end
+ else
+ Handled := False;
+end;
+
+procedure TChildForm.HandleCharMsg(var Msg: tagMSG; var Handled: Boolean);
+var
+ TempKeyEvent : TCefKeyEvent;
+begin
+ if Panel1.Focused then
+ begin
+ TempKeyEvent.kind := KEYEVENT_CHAR;
+ TempKeyEvent.modifiers := GetCefKeyboardModifiers(Msg.wParam, Msg.lParam);
+ TempKeyEvent.windows_key_code := Msg.wParam;
+ TempKeyEvent.native_key_code := Msg.lParam;
+ TempKeyEvent.is_system_key := ord(False);
+ TempKeyEvent.character := #0;
+ TempKeyEvent.unmodified_character := #0;
+ TempKeyEvent.focus_on_editable_field := ord(False);
+
+ Chromium1.SendKeyEvent(@TempKeyEvent);
+ Handled := True;
+ end
+ else
+ Handled := False;
+end;
+
+procedure TChildForm.HandleMouseWheelMsg(var Msg: tagMSG; var Handled: Boolean);
+var
+ TempMouseEvent : TCefMouseEvent;
+begin
+ if Panel1.Focused and (GlobalCEFApp <> nil) then
+ begin
+ TempMouseEvent.x := Msg.lParam and $FFFF;
+ TempMouseEvent.y := Msg.lParam shr 16;
+ TempMouseEvent.modifiers := GetCefMouseModifiers(Msg.wParam);
+ DeviceToLogical(TempMouseEvent, GlobalCEFApp.DeviceScaleFactor);
+ Chromium1.SendMouseWheelEvent(@TempMouseEvent, 0, int16(Msg.wParam shr 16));
+ Handled := False;
+ end;
+end;
+
+function TChildForm.CreateClientHandler(var windowInfo : TCefWindowInfo;
+ var client : ICefClient;
+ const targetFrameName : string;
+ const popupFeatures : TCefPopupFeatures) : boolean;
+begin
+ Chromium1.InitializeDragAndDrop(Panel1);
+
+ WindowInfoAsWindowless(windowInfo, 0, targetFrameName);
+ FPopupFeatures := popupFeatures;
+ FClientInitialized := Chromium1.CreateClientHandler(client);
+ Result := FClientInitialized;
+end;
+
+procedure TChildForm.ApplyPopupFeatures;
+begin
+ if (FPopupFeatures.xset <> 0) then Chromium1.SetFormLeftTo(FPopupFeatures.x);
+ if (FPopupFeatures.yset <> 0) then Chromium1.SetFormTopTo(FPopupFeatures.y);
+ if (FPopupFeatures.widthset <> 0) then Chromium1.ResizeFormWidthTo(FPopupFeatures.width);
+ if (FPopupFeatures.heightset <> 0) then Chromium1.ResizeFormHeightTo(FPopupFeatures.height);
+end;
+
+procedure TChildForm.Chromium1BeforeClose(Sender: TObject; const browser: ICefBrowser);
+begin
+ FCanClose := True;
+ PostMessage(Handle, WM_CLOSE, 0, 0);
+end;
+
+procedure TChildForm.Chromium1BeforePopup(Sender : TObject;
+ const browser : ICefBrowser;
+ const frame : ICefFrame;
+ const targetUrl : ustring;
+ const targetFrameName : ustring;
+ targetDisposition : TCefWindowOpenDisposition;
+ userGesture : Boolean;
+ var popupFeatures : TCefPopupFeatures;
+ var windowInfo : TCefWindowInfo;
+ var client : ICefClient;
+ var settings : TCefBrowserSettings;
+ var noJavascriptAccess : Boolean;
+ out Result : Boolean);
+begin
+ case targetDisposition of
+ WOD_NEW_FOREGROUND_TAB,
+ WOD_NEW_BACKGROUND_TAB,
+ WOD_NEW_WINDOW : Result := True; // For simplicity, this demo blocks new tabs and new windows.
+
+ WOD_NEW_POPUP : Result := not(TMainForm(Owner).CreateClientHandler(windowInfo, client, targetFrameName, popupFeatures));
+
+ else Result := False;
+ end;
+end;
+
+procedure TChildForm.Chromium1Close(Sender: TObject; const browser: ICefBrowser; out Result: Boolean);
+begin
+ Result := False;
+end;
+
+procedure TChildForm.Chromium1CursorChange(Sender : TObject;
+ const browser : ICefBrowser;
+ cursor : HICON;
+ cursorType : TCefCursorType;
+ const customCursorInfo : PCefCursorInfo);
+begin
+ Panel1.Cursor := GefCursorToWindowsCursor(cursorType);
+end;
+
+procedure TChildForm.Chromium1GetScreenInfo(Sender : TObject;
+ const browser : ICefBrowser;
+ var screenInfo : TCefScreenInfo;
+ out Result : Boolean);
+var
+ TempRect : TCEFRect;
+begin
+ if (GlobalCEFApp <> nil) then
+ begin
+ TempRect.x := 0;
+ TempRect.y := 0;
+ TempRect.width := DeviceToLogical(Panel1.Width, GlobalCEFApp.DeviceScaleFactor);
+ TempRect.height := DeviceToLogical(Panel1.Height, GlobalCEFApp.DeviceScaleFactor);
+
+ screenInfo.device_scale_factor := GlobalCEFApp.DeviceScaleFactor;
+ screenInfo.depth := 0;
+ screenInfo.depth_per_component := 0;
+ screenInfo.is_monochrome := Ord(False);
+ screenInfo.rect := TempRect;
+ screenInfo.available_rect := TempRect;
+
+ Result := True;
+ end
+ else
+ Result := False;
+end;
+
+procedure TChildForm.Chromium1GetScreenPoint(Sender : TObject;
+ const browser : ICefBrowser;
+ viewX : Integer;
+ viewY : Integer;
+ var screenX : Integer;
+ var screenY : Integer;
+ out Result : Boolean);
+var
+ TempScreenPt, TempViewPt : TPoint;
+begin
+ if (GlobalCEFApp <> nil) then
+ begin
+ TempViewPt.x := LogicalToDevice(viewX, GlobalCEFApp.DeviceScaleFactor);
+ TempViewPt.y := LogicalToDevice(viewY, GlobalCEFApp.DeviceScaleFactor);
+ TempScreenPt := Panel1.ClientToScreen(TempViewPt);
+ screenX := TempScreenPt.x;
+ screenY := TempScreenPt.y;
+ Result := True;
+ end
+ else
+ Result := False;
+end;
+
+procedure TChildForm.Chromium1GetViewRect(Sender : TObject;
+ const browser : ICefBrowser;
+ var rect : TCefRect;
+ out Result : Boolean);
+begin
+ if (GlobalCEFApp <> nil) then
+ begin
+ rect.x := 0;
+ rect.y := 0;
+ rect.width := DeviceToLogical(Panel1.Width, GlobalCEFApp.DeviceScaleFactor);
+ rect.height := DeviceToLogical(Panel1.Height, GlobalCEFApp.DeviceScaleFactor);
+ Result := True;
+ end
+ else
+ Result := False;
+end;
+
+procedure TChildForm.Chromium1Paint(Sender : TObject;
+ const browser : ICefBrowser;
+ kind : TCefPaintElementType;
+ dirtyRectsCount : NativeUInt;
+ const dirtyRects : PCefRectArray;
+ const buffer : Pointer;
+ width : Integer;
+ height : Integer);
+var
+ src, dst: PByte;
+ i, j, TempLineSize, TempSrcOffset, TempDstOffset, SrcStride, DstStride : Integer;
+ n : NativeUInt;
+ TempWidth, TempHeight, TempScanlineSize : integer;
+ TempBufferBits : Pointer;
+ TempForcedResize : boolean;
+begin
+ try
+ FResizeCS.Acquire;
+ TempForcedResize := False;
+
+ if Panel1.BeginBufferDraw then
+ begin
+ if (kind = PET_POPUP) then
+ begin
+ if (FPopUpBitmap = nil) or
+ (width <> FPopUpBitmap.Width) or
+ (height <> FPopUpBitmap.Height) then
+ begin
+ if (FPopUpBitmap <> nil) then FPopUpBitmap.Free;
+
+ FPopUpBitmap := TBitmap.Create;
+ FPopUpBitmap.PixelFormat := pf32bit;
+ FPopUpBitmap.HandleType := bmDIB;
+ FPopUpBitmap.Width := width;
+ FPopUpBitmap.Height := height;
+ end;
+
+ TempWidth := FPopUpBitmap.Width;
+ TempHeight := FPopUpBitmap.Height;
+ TempScanlineSize := FPopUpBitmap.Width * SizeOf(TRGBQuad);
+ TempBufferBits := FPopUpBitmap.Scanline[pred(FPopUpBitmap.Height)];
+ end
+ else
+ begin
+ TempForcedResize := Panel1.UpdateBufferDimensions(Width, Height) or not(Panel1.BufferIsResized(False));
+ TempWidth := Panel1.BufferWidth;
+ TempHeight := Panel1.BufferHeight;
+ TempScanlineSize := Panel1.ScanlineSize;
+ TempBufferBits := Panel1.BufferBits;
+ end;
+
+ if (TempBufferBits <> nil) then
+ begin
+ SrcStride := Width * SizeOf(TRGBQuad);
+ DstStride := - TempScanlineSize;
+
+ n := 0;
+
+ while (n < dirtyRectsCount) do
+ begin
+ if (dirtyRects[n].x >= 0) and (dirtyRects[n].y >= 0) then
+ begin
+ TempLineSize := min(dirtyRects[n].width, TempWidth - dirtyRects[n].x) * SizeOf(TRGBQuad);
+
+ if (TempLineSize > 0) then
+ begin
+ TempSrcOffset := ((dirtyRects[n].y * Width) + dirtyRects[n].x) * SizeOf(TRGBQuad);
+ TempDstOffset := ((TempScanlineSize * pred(TempHeight)) - (dirtyRects[n].y * TempScanlineSize)) +
+ (dirtyRects[n].x * SizeOf(TRGBQuad));
+
+ src := @PByte(buffer)[TempSrcOffset];
+ dst := @PByte(TempBufferBits)[TempDstOffset];
+
+ i := 0;
+ j := min(dirtyRects[n].height, TempHeight - dirtyRects[n].y);
+
+ while (i < j) do
+ begin
+ Move(src^, dst^, TempLineSize);
+
+ Inc(dst, DstStride);
+ Inc(src, SrcStride);
+ inc(i);
+ end;
+ end;
+ end;
+
+ inc(n);
+ end;
+
+ if FShowPopup and (FPopUpBitmap <> nil) then
+ Panel1.BufferDraw(FPopUpRect.Left, FPopUpRect.Top, FPopUpBitmap);
+ end;
+
+ Panel1.EndBufferDraw;
+ Panel1.InvalidatePanel;
+
+ if (kind = PET_VIEW) then
+ begin
+ if TempForcedResize or FPendingResize then PostMessage(Handle, CEF_PENDINGRESIZE, 0, 0);
+
+ FResizing := False;
+ FPendingResize := False;
+ end;
+ end;
+ finally
+ FResizeCS.Release;
+ end;
+end;
+
+procedure TChildForm.Chromium1PopupShow(Sender : TObject;
+ const browser : ICefBrowser;
+ show : Boolean);
+begin
+ if show then
+ FShowPopUp := True
+ else
+ begin
+ FShowPopUp := False;
+ FPopUpRect := rect(0, 0, 0, 0);
+
+ if (Chromium1 <> nil) then Chromium1.Invalidate(PET_VIEW);
+ end;
+end;
+
+procedure TChildForm.Chromium1PopupSize(Sender : TObject;
+ const browser : ICefBrowser;
+ const rect : PCefRect);
+begin
+ if (GlobalCEFApp <> nil) then
+ begin
+ LogicalToDevice(rect^, GlobalCEFApp.DeviceScaleFactor);
+
+ FPopUpRect.Left := rect.x;
+ FPopUpRect.Top := rect.y;
+ FPopUpRect.Right := rect.x + rect.width - 1;
+ FPopUpRect.Bottom := rect.y + rect.height - 1;
+ end;
+end;
+
+procedure TChildForm.Chromium1TitleChange(Sender: TObject; const browser: ICefBrowser; const title: ustring);
+begin
+ Caption := title;
+end;
+
+procedure TChildForm.Chromium1Tooltip(Sender: TObject; const browser: ICefBrowser; var text: ustring; out Result: Boolean);
+begin
+ Panel1.hint := text;
+ Panel1.ShowHint := (length(text) > 0);
+ Result := True;
+end;
+
+function TChildForm.getModifiers(Shift: TShiftState): TCefEventFlags;
+begin
+ Result := EVENTFLAG_NONE;
+
+ if (ssShift in Shift) then Result := Result or EVENTFLAG_SHIFT_DOWN;
+ if (ssAlt in Shift) then Result := Result or EVENTFLAG_ALT_DOWN;
+ if (ssCtrl in Shift) then Result := Result or EVENTFLAG_CONTROL_DOWN;
+ if (ssLeft in Shift) then Result := Result or EVENTFLAG_LEFT_MOUSE_BUTTON;
+ if (ssRight in Shift) then Result := Result or EVENTFLAG_RIGHT_MOUSE_BUTTON;
+ if (ssMiddle in Shift) then Result := Result or EVENTFLAG_MIDDLE_MOUSE_BUTTON;
+end;
+
+function TChildForm.GetButton(Button: TMouseButton): TCefMouseButtonType;
+begin
+ case Button of
+ TMouseButton.mbRight : Result := MBT_RIGHT;
+ TMouseButton.mbMiddle : Result := MBT_MIDDLE;
+ else Result := MBT_LEFT;
+ end;
+end;
+
+procedure TChildForm.WMMove(var aMessage : TWMMove);
+begin
+ inherited;
+
+ if (Chromium1 <> nil) then Chromium1.NotifyMoveOrResizeStarted;
+end;
+
+procedure TChildForm.WMMoving(var aMessage : TMessage);
+begin
+ inherited;
+
+ if (Chromium1 <> nil) then Chromium1.NotifyMoveOrResizeStarted;
+end;
+
+procedure TChildForm.WMCaptureChanged(var aMessage : TMessage);
+begin
+ inherited;
+
+ if (Chromium1 <> nil) then Chromium1.SendCaptureLostEvent;
+end;
+
+procedure TChildForm.WMCancelMode(var aMessage : TMessage);
+begin
+ inherited;
+
+ if (Chromium1 <> nil) then Chromium1.SendCaptureLostEvent;
+end;
+
+procedure TChildForm.WMEnterMenuLoop(var aMessage: TMessage);
+begin
+ inherited;
+
+ if (aMessage.wParam = 0) and (GlobalCEFApp <> nil) then GlobalCEFApp.OsmodalLoop := True;
+end;
+
+procedure TChildForm.WMExitMenuLoop(var aMessage: TMessage);
+begin
+ inherited;
+
+ if (aMessage.wParam = 0) and (GlobalCEFApp <> nil) then GlobalCEFApp.OsmodalLoop := False;
+end;
+
+procedure TChildForm.FormAfterMonitorDpiChanged(Sender: TObject; OldDPI, NewDPI: Integer);
+begin
+ if (Chromium1 <> nil) then
+ begin
+ Chromium1.NotifyScreenInfoChanged;
+ Chromium1.WasResized;
+ end;
+end;
+
+procedure TChildForm.FormClose(Sender: TObject; var Action: TCloseAction);
+begin
+ Action := caFree;
+end;
+
+procedure TChildForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
+begin
+ CanClose := FCanClose;
+
+ if not(FClosing) then
+ begin
+ FClosing := True;
+ Visible := False;
+ Chromium1.CloseBrowser(True);
+ end;
+end;
+
+procedure TChildForm.FormCreate(Sender: TObject);
+begin
+ FPopUpBitmap := nil;
+ FPopUpRect := rect(0, 0, 0, 0);
+ FShowPopUp := False;
+ FResizing := False;
+ FPendingResize := False;
+ FCanClose := False;
+ FClosing := False;
+ FClientInitialized := False;
+ FResizeCS := TCriticalSection.Create;
+end;
+
+procedure TChildForm.FormDestroy(Sender: TObject);
+begin
+ Chromium1.ShutdownDragAndDrop;
+
+ if (FPopUpBitmap <> nil) then FreeAndNil(FPopUpBitmap);
+
+ if FClientInitialized and TMainForm(Owner).HandleAllocated then
+ PostMessage(TMainForm(Owner).Handle, CEF_CHILDDESTROYED, 0, 0);
+end;
+
+procedure TChildForm.FormHide(Sender: TObject);
+begin
+ Chromium1.SendFocusEvent(False);
+ Chromium1.WasHidden(True);
+end;
+
+procedure TChildForm.FormShow(Sender: TObject);
+begin
+ Chromium1.WasHidden(False);
+ Chromium1.SendFocusEvent(True);
+end;
+
+procedure TChildForm.Panel1Click(Sender: TObject);
+begin
+ Panel1.SetFocus;
+end;
+
+procedure TChildForm.Panel1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
+var
+ TempEvent : TCefMouseEvent;
+begin
+ if (GlobalCEFApp <> nil) and (Chromium1 <> nil) then
+ begin
+ Panel1.SetFocus;
+
+ TempEvent.x := X;
+ TempEvent.y := Y;
+ TempEvent.modifiers := getModifiers(Shift);
+ DeviceToLogical(TempEvent, GlobalCEFApp.DeviceScaleFactor);
+ Chromium1.SendMouseClickEvent(@TempEvent, GetButton(Button), False, 1);
+ end;
+end;
+
+procedure TChildForm.Panel1MouseLeave(Sender: TObject);
+var
+ TempEvent : TCefMouseEvent;
+ TempPoint : TPoint;
+begin
+ if (GlobalCEFApp <> nil) and (Chromium1 <> nil) then
+ begin
+ GetCursorPos(TempPoint);
+ TempPoint := Panel1.ScreenToclient(TempPoint);
+ TempEvent.x := TempPoint.x;
+ TempEvent.y := TempPoint.y;
+ TempEvent.modifiers := GetCefMouseModifiers;
+ DeviceToLogical(TempEvent, GlobalCEFApp.DeviceScaleFactor);
+ Chromium1.SendMouseMoveEvent(@TempEvent, True);
+ end;
+end;
+
+procedure TChildForm.Panel1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
+var
+ TempEvent : TCefMouseEvent;
+begin
+ if (GlobalCEFApp <> nil) and (Chromium1 <> nil) then
+ begin
+ TempEvent.x := X;
+ TempEvent.y := Y;
+ TempEvent.modifiers := getModifiers(Shift);
+ DeviceToLogical(TempEvent, GlobalCEFApp.DeviceScaleFactor);
+ Chromium1.SendMouseMoveEvent(@TempEvent, False);
+ end;
+end;
+
+procedure TChildForm.Panel1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
+var
+ TempEvent : TCefMouseEvent;
+begin
+ if (GlobalCEFApp <> nil) and (Chromium1 <> nil) then
+ begin
+ TempEvent.x := X;
+ TempEvent.y := Y;
+ TempEvent.modifiers := getModifiers(Shift);
+ DeviceToLogical(TempEvent, GlobalCEFApp.DeviceScaleFactor);
+ Chromium1.SendMouseClickEvent(@TempEvent, GetButton(Button), True, 1);
+ end;
+end;
+
+procedure TChildForm.Panel1Resize(Sender: TObject);
+begin
+ DoResize;
+end;
+
+procedure TChildForm.PendingResizeMsg(var aMessage : TMessage);
+begin
+ DoResize;
+end;
+
+procedure TChildForm.ShowChildMsg(var aMessage : TMessage);
+begin
+ ApplyPopupFeatures;
+ Show;
+end;
+
+procedure TChildForm.DoResize;
+begin
+ try
+ FResizeCS.Acquire;
+
+ if FResizing then
+ FPendingResize := True
+ else
+ if Panel1.BufferIsResized then
+ Chromium1.Invalidate(PET_VIEW)
+ else
+ begin
+ FResizing := True;
+ Chromium1.WasResized;
+ end;
+ finally
+ FResizeCS.Release;
+ end;
+end;
+
+procedure TChildForm.Panel1Enter(Sender: TObject);
+begin
+ Chromium1.SendFocusEvent(True);
+end;
+
+procedure TChildForm.Panel1Exit(Sender: TObject);
+begin
+ Chromium1.SendFocusEvent(False);
+end;
+
+end.
diff --git a/demos/PopupBrowser/uMainForm.dfm b/demos/PopupBrowser/uMainForm.dfm
new file mode 100644
index 00000000..a1347b01
--- /dev/null
+++ b/demos/PopupBrowser/uMainForm.dfm
@@ -0,0 +1,84 @@
+object MainForm: TMainForm
+ Left = 0
+ Top = 0
+ Caption = 'Initializing browser. Please wait...'
+ ClientHeight = 624
+ ClientWidth = 1038
+ Color = clBtnFace
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = []
+ OldCreateOrder = False
+ Position = poScreenCenter
+ OnCloseQuery = FormCloseQuery
+ OnCreate = FormCreate
+ OnDestroy = FormDestroy
+ OnShow = FormShow
+ PixelsPerInch = 96
+ TextHeight = 13
+ object AddressPnl: TPanel
+ Left = 0
+ Top = 0
+ Width = 1038
+ Height = 30
+ Align = alTop
+ BevelOuter = bvNone
+ Enabled = False
+ Padding.Left = 5
+ Padding.Top = 5
+ Padding.Right = 5
+ Padding.Bottom = 5
+ ShowCaption = False
+ TabOrder = 0
+ object AddressEdt: TEdit
+ Left = 5
+ Top = 5
+ Width = 997
+ Height = 20
+ Margins.Right = 5
+ Align = alClient
+ TabOrder = 0
+ Text = 'file:///PopupBrowser.html'
+ ExplicitHeight = 21
+ end
+ object GoBtn: TButton
+ Left = 1002
+ Top = 5
+ Width = 31
+ Height = 20
+ Margins.Left = 5
+ Align = alRight
+ Caption = 'Go'
+ TabOrder = 1
+ OnClick = GoBtnClick
+ end
+ end
+ object CEFWindowParent1: TCEFWindowParent
+ Left = 0
+ Top = 30
+ Width = 1038
+ Height = 594
+ Align = alClient
+ TabOrder = 1
+ end
+ object Timer1: TTimer
+ Enabled = False
+ Interval = 300
+ OnTimer = Timer1Timer
+ Left = 56
+ Top = 88
+ end
+ object Chromium1: TChromium
+ OnBeforePopup = Chromium1BeforePopup
+ OnAfterCreated = Chromium1AfterCreated
+ Left = 56
+ Top = 152
+ end
+ object AppEvents: TApplicationEvents
+ OnMessage = AppEventsMessage
+ Left = 56
+ Top = 216
+ end
+end
diff --git a/demos/PopupBrowser/uMainForm.pas b/demos/PopupBrowser/uMainForm.pas
new file mode 100644
index 00000000..972d6fb4
--- /dev/null
+++ b/demos/PopupBrowser/uMainForm.pas
@@ -0,0 +1,345 @@
+// ************************************************************************
+// ***************************** CEF4Delphi *******************************
+// ************************************************************************
+//
+// CEF4Delphi is based on DCEF3 which uses CEF3 to embed a chromium-based
+// browser in Delphi applications.
+//
+// The original license of DCEF3 still applies to CEF4Delphi.
+//
+// For more information about CEF4Delphi visit :
+// https://www.briskbard.com/index.php?lang=en&pageid=cef
+//
+// Copyright © 2018 Salvador Díaz Fau. All rights reserved.
+//
+// ************************************************************************
+// ************ vvvv Original license and comments below vvvv *************
+// ************************************************************************
+(*
+ * Delphi Chromium Embedded 3
+ *
+ * Usage allowed under the restrictions of the Lesser GNU General Public License
+ * or alternatively the restrictions of the Mozilla Public License 1.1
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
+ * the specific language governing rights and limitations under the License.
+ *
+ * Unit owner : Henri Gourvest
+ * Web site : http://www.progdigy.com
+ * Repository : http://code.google.com/p/delphichromiumembedded/
+ * Group : http://groups.google.com/group/delphichromiumembedded
+ *
+ * Embarcadero Technologies, Inc is not permitted to use or redistribute
+ * this source code without explicit permission.
+ *
+ *)
+
+unit uMainForm;
+
+{$I cef.inc}
+
+interface
+
+uses
+ {$IFDEF DELPHI16_UP}
+ Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
+ Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls, System.SyncObjs,
+ {$ELSE}
+ Windows, Messages, SysUtils, Variants, Classes, Graphics,
+ Controls, Forms, Dialogs, StdCtrls, ExtCtrls, SyncObjs,
+ {$ENDIF}
+ uCEFChromium, uCEFWindowParent, uCEFInterfaces, uCEFConstants, uCEFTypes, uChildForm,
+ Vcl.AppEvnts;
+
+const
+ CEF_CREATENEXTCHILD = WM_APP + $A50;
+ CEF_CHILDDESTROYED = WM_APP + $A51;
+
+type
+ TMainForm = class(TForm)
+ AddressPnl: TPanel;
+ AddressEdt: TEdit;
+ GoBtn: TButton;
+ Timer1: TTimer;
+ Chromium1: TChromium;
+ CEFWindowParent1: TCEFWindowParent;
+ AppEvents: TApplicationEvents;
+
+ procedure GoBtnClick(Sender: TObject);
+ procedure Timer1Timer(Sender: TObject);
+ procedure AppEventsMessage(var Msg: tagMSG; var Handled: Boolean);
+
+ procedure FormShow(Sender: TObject);
+ procedure FormCreate(Sender: TObject);
+ procedure FormDestroy(Sender: TObject);
+ procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
+
+ procedure Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser);
+ procedure Chromium1BeforePopup(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; const targetUrl, targetFrameName: ustring; targetDisposition: TCefWindowOpenDisposition; userGesture: Boolean; var popupFeatures: TCefPopupFeatures; var windowInfo: TCefWindowInfo; var client: ICefClient; var settings: TCefBrowserSettings; var noJavascriptAccess: Boolean; out Result: Boolean);
+
+ protected
+ FChildForm : TChildForm;
+ FCriticalSection : TCriticalSection;
+ FClosing : boolean;
+
+ function GetPopupChildCount : integer;
+
+ procedure ClosePopupChildren;
+
+ procedure WMMove(var aMessage : TWMMove); message WM_MOVE;
+ procedure WMMoving(var aMessage : TMessage); message WM_MOVING;
+ procedure WMEnterMenuLoop(var aMessage: TMessage); message WM_ENTERMENULOOP;
+ procedure WMExitMenuLoop(var aMessage: TMessage); message WM_EXITMENULOOP;
+
+ procedure BrowserCreatedMsg(var aMessage : TMessage); message CEF_AFTERCREATED;
+ procedure CreateNextChildMsg(var aMessage : TMessage); message CEF_CREATENEXTCHILD;
+ procedure ChildDestroyedMsg(var aMessage : TMessage); message CEF_CHILDDESTROYED;
+
+ public
+ function CreateClientHandler(var windowInfo : TCefWindowInfo; var client : ICefClient; const targetFrameName : string; var popupFeatures : TCefPopupFeatures) : boolean;
+
+ property PopupChildCount : integer read GetPopupChildCount;
+ end;
+
+var
+ MainForm: TMainForm;
+
+implementation
+
+{$R *.dfm}
+
+uses
+ uCEFApplication, uCEFMiscFunctions;
+
+// This is demo shows how to create popup windows in CEF.
+
+// You need to understand The SimpleBrowser2 and SimpleOSRBrowser demos completely before trying to understand this demo.
+
+// When TChromium needs to show a new popup window it executes TChromium.OnBeforePopup.
+
+// VCL components *MUST* be created and destroyed in the main thread but CEF executes the
+// TChromium.OnBeforePopup in a different thread.
+
+// For this reason this demo creates a hidden popup form (TChildForm) in case CEF needs to show a popup window.
+// TChromium.OnBeforePopup calls TChildForm.CreateClientHandler to initialize some parameters and create the new ICefClient.
+// After that, it sends a CEF_CREATENEXTCHILD message to show the popup form and create a new one.
+
+// All the child forms must be correctly destroyed before closing the main form. Read the code comments in uChildForm.pas
+// to know how the popup windows are destroyed.
+
+// The main form sends a WM_CLOSE to all active popup forms and waits until all of them have sent a CEF_CHILDDESTROYED message.
+
+procedure TMainForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
+begin
+ FClosing := True;
+ Visible := False;
+
+ if (PopupChildCount > 0) then
+ begin
+ ClosePopupChildren;
+ CanClose := False;
+ end
+ else
+ CanClose := True;
+end;
+
+procedure TMainForm.FormCreate(Sender: TObject);
+begin
+ FClosing := False;
+ FCriticalSection := TCriticalSection.Create;
+
+ Chromium1.Options.BackgroundColor := CefColorSetARGB($FF, $FF, $FF, $FF);
+end;
+
+procedure TMainForm.FormDestroy(Sender: TObject);
+begin
+ FreeAndNil(FCriticalSection);
+end;
+
+procedure TMainForm.FormShow(Sender: TObject);
+begin
+ // You *MUST* call CreateBrowser to create and initialize the browser.
+ // This will trigger the AfterCreated event when the browser is fully
+ // initialized and ready to receive commands.
+
+ // GlobalCEFApp.GlobalContextInitialized has to be TRUE before creating any browser
+ // If it's not initialized yet, we use a simple timer to create the browser later.
+ if not(Chromium1.CreateBrowser(CEFWindowParent1)) then Timer1.Enabled := True;
+end;
+
+procedure TMainForm.Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser);
+begin
+ // Now the browser is fully initialized we can send a message to the main form to load the initial web page.
+ PostMessage(Handle, CEF_AFTERCREATED, 0, 0);
+end;
+
+procedure TMainForm.Chromium1BeforePopup(Sender : TObject;
+ const browser : ICefBrowser;
+ const frame : ICefFrame;
+ const targetUrl : ustring;
+ const targetFrameName : ustring;
+ targetDisposition : TCefWindowOpenDisposition;
+ userGesture : Boolean;
+ var popupFeatures : TCefPopupFeatures;
+ var windowInfo : TCefWindowInfo;
+ var client : ICefClient;
+ var settings : TCefBrowserSettings;
+ var noJavascriptAccess : Boolean;
+ out Result : Boolean);
+begin
+ case targetDisposition of
+ WOD_NEW_FOREGROUND_TAB,
+ WOD_NEW_BACKGROUND_TAB,
+ WOD_NEW_WINDOW : Result := True; // For simplicity, this demo blocks new tabs and new windows.
+
+ WOD_NEW_POPUP : Result := not(CreateClientHandler(windowInfo, client, targetFrameName, popupFeatures));
+
+ else Result := False;
+ end;
+end;
+
+function TMainForm.CreateClientHandler(var windowInfo : TCefWindowInfo;
+ var client : ICefClient;
+ const targetFrameName : string;
+ var popupFeatures : TCefPopupFeatures) : boolean;
+begin
+ try
+ FCriticalSection.Acquire;
+
+ Result := (FChildForm <> nil) and
+ FChildForm.CreateClientHandler(windowInfo, client, targetFrameName, popupFeatures) and
+ PostMessage(Handle, CEF_CREATENEXTCHILD, 0, 0);
+ finally
+ FCriticalSection.Release;
+ end;
+end;
+
+function TMainForm.GetPopupChildCount : integer;
+var
+ i : integer;
+ TempForm : TCustomForm;
+begin
+ Result := 0;
+ i := pred(screen.CustomFormCount);
+
+ while (i >= 0) do
+ begin
+ TempForm := screen.CustomForms[i];
+
+ // Only count the fully initialized child forms and not the one waiting to be used.
+
+ if (TempForm is TChildForm) and
+ TChildForm(TempForm).ClientInitialized then
+ inc(Result);
+
+ dec(i);
+ end;
+end;
+
+procedure TMainForm.ClosePopupChildren;
+var
+ i : integer;
+ TempForm : TCustomForm;
+begin
+ i := pred(screen.CustomFormCount);
+
+ while (i >= 0) do
+ begin
+ TempForm := screen.CustomForms[i];
+
+ // Only send WM_CLOSE to fully initialized child forms.
+
+ if (TempForm is TChildForm) and
+ TChildForm(TempForm).ClientInitialized and
+ not(TChildForm(TempForm).Closing) then
+ PostMessage(TChildForm(screen.CustomForms[i]).Handle, WM_CLOSE, 0, 0);
+
+ dec(i);
+ end;
+end;
+
+procedure TMainForm.AppEventsMessage(var Msg: tagMSG; var Handled: Boolean);
+begin
+ case Msg.message of
+ WM_SYSCHAR : if (screen.FocusedForm is TChildForm) then TChildForm(screen.FocusedForm).HandleSysCharMsg(Msg, Handled);
+ WM_SYSKEYDOWN : if (screen.FocusedForm is TChildForm) then TChildForm(screen.FocusedForm).HandleSysKeyDownMsg(Msg, Handled);
+ WM_SYSKEYUP : if (screen.FocusedForm is TChildForm) then TChildForm(screen.FocusedForm).HandleSysKeyUpMsg(Msg, Handled);
+ WM_KEYDOWN : if (screen.FocusedForm is TChildForm) then TChildForm(screen.FocusedForm).HandleKeyDownMsg(Msg, Handled);
+ WM_KEYUP : if (screen.FocusedForm is TChildForm) then TChildForm(screen.FocusedForm).HandleKeyUpMsg(Msg, Handled);
+ WM_CHAR : if (screen.FocusedForm is TChildForm) then TChildForm(screen.FocusedForm).HandleCharMsg(Msg, Handled);
+ WM_MOUSEWHEEL : if (screen.FocusedForm is TChildForm) then TChildForm(screen.FocusedForm).HandleMouseWheelMsg(Msg, Handled);
+
+ else Handled := False;
+ end;
+end;
+
+procedure TMainForm.BrowserCreatedMsg(var aMessage : TMessage);
+begin
+ FChildForm := TChildForm.Create(self);
+ Caption := 'Popup Browser';
+ AddressPnl.Enabled := True;
+ GoBtn.Click;
+end;
+
+procedure TMainForm.CreateNextChildMsg(var aMessage : TMessage);
+begin
+ try
+ FCriticalSection.Acquire;
+
+ if (FChildForm <> nil) then
+ PostMessage(FChildForm.Handle, CEF_SHOWCHILD, 0, 0);
+
+ FChildForm := TChildForm.Create(self);
+ finally
+ FCriticalSection.Release;
+ end;
+end;
+
+procedure TMainForm.ChildDestroyedMsg(var aMessage : TMessage);
+begin
+ if FClosing and (PopupChildCount = 0) then Close;
+end;
+
+procedure TMainForm.GoBtnClick(Sender: TObject);
+begin
+ // This will load the URL in the edit box
+ Chromium1.LoadURL(AddressEdt.Text);
+end;
+
+procedure TMainForm.Timer1Timer(Sender: TObject);
+begin
+ Timer1.Enabled := False;
+ if not(Chromium1.CreateBrowser(CEFWindowParent1)) and not(Chromium1.Initialized) then
+ Timer1.Enabled := True;
+end;
+
+procedure TMainForm.WMMove(var aMessage : TWMMove);
+begin
+ inherited;
+
+ if (Chromium1 <> nil) then Chromium1.NotifyMoveOrResizeStarted;
+end;
+
+procedure TMainForm.WMMoving(var aMessage : TMessage);
+begin
+ inherited;
+
+ if (Chromium1 <> nil) then Chromium1.NotifyMoveOrResizeStarted;
+end;
+
+procedure TMainForm.WMEnterMenuLoop(var aMessage: TMessage);
+begin
+ inherited;
+
+ if (aMessage.wParam = 0) and (GlobalCEFApp <> nil) then GlobalCEFApp.OsmodalLoop := True;
+end;
+
+procedure TMainForm.WMExitMenuLoop(var aMessage: TMessage);
+begin
+ inherited;
+
+ if (aMessage.wParam = 0) and (GlobalCEFApp <> nil) then GlobalCEFApp.OsmodalLoop := False;
+end;
+
+end.