diff --git a/demos/FMXToolBoxBrowser/00-DeleteDCUs.bat b/demos/FMXToolBoxBrowser/00-DeleteDCUs.bat new file mode 100644 index 00000000..dbd008bc --- /dev/null +++ b/demos/FMXToolBoxBrowser/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/FMXToolBoxBrowser/FMXToolBoxBrowser.dpr b/demos/FMXToolBoxBrowser/FMXToolBoxBrowser.dpr new file mode 100644 index 00000000..bfbab5fd --- /dev/null +++ b/demos/FMXToolBoxBrowser/FMXToolBoxBrowser.dpr @@ -0,0 +1,64 @@ +// ************************************************************************ +// ***************************** 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 FMXToolBoxBrowser; + +uses + System.StartUpCopy, + FMX.Forms, + {$IFDEF MSWINDOWS} + WinApi.Windows, + {$ENDIF } + uCEFApplication, + uFMXApplicationService in 'uFMXApplicationService.pas', + uMainForm in 'uMainForm.pas' {MainForm}, + uChildForm in 'uChildForm.pas' {ChildForm}; + +{$R *.res} + +begin + CreateGlobalCEFApp; + + if GlobalCEFApp.StartMainProcess then + begin + Application.Initialize; + Application.CreateForm(TMainForm, MainForm); + Application.Run; + end; + + DestroyGlobalCEFApp; +end. diff --git a/demos/FMXToolBoxBrowser/FMXToolBoxBrowser.dproj b/demos/FMXToolBoxBrowser/FMXToolBoxBrowser.dproj new file mode 100644 index 00000000..df620529 --- /dev/null +++ b/demos/FMXToolBoxBrowser/FMXToolBoxBrowser.dproj @@ -0,0 +1,623 @@ + + + {04DED2F9-59A2-4E14-A538-C6B47842101F} + 18.2 + FMX + FMXToolBoxBrowser.dpr + True + Debug + Win32 + 3 + 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 + + + .\$(Platform)\$(Config) + ..\..\bin + false + false + false + false + false + RESTComponents;emsclientfiredac;FireDACIBDriver;emsclient;FireDACCommon;RESTBackendComponents;soapserver;CloudService;FireDACCommonDriver;inet;FireDAC;FireDACSqliteDriver;soaprtl;soapmidas;$(DCC_UsePackage) + System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace) + $(BDS)\bin\delphi_PROJECTICON.ico + $(BDS)\bin\delphi_PROJECTICNS.icns + FMXToolBoxBrowser + 3082 + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= + + + DBXSqliteDriver;DataSnapServerMidas;DBXDb2Driver;DBXInterBaseDriver;vclactnband;vclFireDAC;DataSnapFireDAC;svnui;tethering;Componentes;FireDACADSDriver;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;svn;DBXOracleDriver;inetdb;Componentes_Int;IndyProtocols240;fmx;fmxdae;FireDACDBXDriver;dbexpress;vclx;dsnap;DataSnapCommon;DataSnapConnectors;VCLRESTComponents;vclie;CEF4Delphi_FMX;bindengine;DBXMySQLDriver;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonODBC;DataSnapClient;bindcompdbx;vcl;DBXSybaseASEDriver;FireDACDb2Driver;dsnapcon;FireDACMSAccDriver;fmxFireDAC;FireDACInfxDriver;vclimg;Componentes_UI;FireDACPgDriver;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;DbxCommonDriver;Componentes_Misc;IndySystem240;DataSnapServer;xmlrtl;DataSnapNativeClient;fmxobj;vclwinx;FireDACDSDriver;rtl;DbxClientDriver;IndyCore240;DBXSybaseASADriver;CustomIPTransport;vcldsnap;bindcomp;appanalytics;Componentes_RTF;DBXInformixDriver;bindcompvcl;Componentes_vCard;dbxcds;VclSmp;adortl;FireDACODBCDriver;DataSnapIndy10ServerTransport;dsnapxml;DataSnapProviderClient;dbrtl;inetdbxpress;FireDACMongoDBDriver;fmxase;$(DCC_UsePackage) + Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(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 + $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png + $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png + + + DBXSqliteDriver;DataSnapServerMidas;DBXDb2Driver;DBXInterBaseDriver;vclactnband;vclFireDAC;DataSnapFireDAC;tethering;FireDACADSDriver;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;DBXOracleDriver;inetdb;IndyProtocols240;fmx;fmxdae;FireDACDBXDriver;dbexpress;vclx;dsnap;DataSnapCommon;DataSnapConnectors;VCLRESTComponents;vclie;bindengine;DBXMySQLDriver;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonODBC;DataSnapClient;bindcompdbx;vcl;DBXSybaseASEDriver;FireDACDb2Driver;dsnapcon;FireDACMSAccDriver;fmxFireDAC;FireDACInfxDriver;vclimg;FireDACPgDriver;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;DbxCommonDriver;IndySystem240;DataSnapServer;xmlrtl;DataSnapNativeClient;fmxobj;vclwinx;FireDACDSDriver;rtl;DbxClientDriver;IndyCore240;DBXSybaseASADriver;CustomIPTransport;vcldsnap;bindcomp;appanalytics;DBXInformixDriver;bindcompvcl;dbxcds;VclSmp;adortl;FireDACODBCDriver;DataSnapIndy10ServerTransport;dsnapxml;DataSnapProviderClient;dbrtl;inetdbxpress;FireDACMongoDBDriver;fmxase;$(DCC_UsePackage) + 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 + $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png + $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png + + + DEBUG;$(DCC_Define) + true + false + true + true + true + + + false + true + true + true + 1033 + + + true + true + + + false + RELEASE;$(DCC_Define) + 0 + 0 + + + true + true + + + true + true + + + + MainSource + + + +
MainForm
+ fmx +
+ +
ChildForm
+ fmx +
+ + Cfg_2 + Base + + + Base + + + Cfg_1 + Base + +
+ + Delphi.Personality.12 + Application + + + + FMXToolBoxBrowser.dpr + + + IP Abstraction Indy Implementation Design Time + Microsoft Office 2000 Sample Automation Server Wrapper Components + Microsoft Office XP Sample Automation Server Wrapper Components + + + + + + true + + + + + true + + + + + true + + + + + true + + + + + FMXToolBoxBrowser.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 + True + + + 12 + + + + +
diff --git a/demos/FMXToolBoxBrowser/cef.inc b/demos/FMXToolBoxBrowser/cef.inc new file mode 100644 index 00000000..8ad3597b --- /dev/null +++ b/demos/FMXToolBoxBrowser/cef.inc @@ -0,0 +1,382 @@ +// ************************************************************************ +// ***************************** 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 Diaz 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} + +// 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 (First 64bit compiler) +{$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 FPC} + {$DEFINE SUPPORTS_INLINE} +{$ELSE} + {$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} +{$ENDIF} + +{$IFDEF DELPHI9_UP} + {$DEFINE SUPPORTS_INLINE} +{$ENDIF} + diff --git a/demos/FMXToolBoxBrowser/uChildForm.fmx b/demos/FMXToolBoxBrowser/uChildForm.fmx new file mode 100644 index 00000000..30f8026b --- /dev/null +++ b/demos/FMXToolBoxBrowser/uChildForm.fmx @@ -0,0 +1,28 @@ +object ChildForm: TChildForm + Left = 0 + Top = 0 + BorderIcons = [biSystemMenu, biMinimize] + BorderStyle = Single + Caption = 'Form1' + ClientHeight = 600 + ClientWidth = 800 + Position = ScreenCenter + FormFactor.Width = 320 + FormFactor.Height = 480 + FormFactor.Devices = [Desktop] + OnCreate = FormCreate + OnClose = FormClose + OnCloseQuery = FormCloseQuery + OnDestroy = FormDestroy + OnResize = FormResize + OnShow = FormShow + DesignerMasterStyle = 0 + object FMXChromium1: TFMXChromium + OnBeforePopup = FMXChromium1BeforePopup + OnAfterCreated = FMXChromium1AfterCreated + OnBeforeClose = FMXChromium1BeforeClose + OnClose = FMXChromium1Close + Left = 40 + Top = 32 + end +end diff --git a/demos/FMXToolBoxBrowser/uChildForm.pas b/demos/FMXToolBoxBrowser/uChildForm.pas new file mode 100644 index 00000000..95f0fa4a --- /dev/null +++ b/demos/FMXToolBoxBrowser/uChildForm.pas @@ -0,0 +1,269 @@ +// ************************************************************************ +// ***************************** 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 Diaz 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; + +interface + +uses + {$IFDEF MSWINDOWS} + Winapi.Messages, Winapi.Windows, + {$ENDIF} + System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, + FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, + uFMXChromium, uFMXWindowParent, uCEFInterfaces, uCEFConstants, uCEFTypes; + +type + TChildForm = class(TForm) + FMXChromium1: TFMXChromium; + + procedure FormShow(Sender: TObject); + procedure FormCreate(Sender: TObject); + procedure FormResize(Sender: TObject); + procedure FormClose(Sender: TObject; var Action: TCloseAction); + procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); + procedure FormDestroy(Sender: TObject); + + procedure FMXChromium1BeforePopup(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; const targetUrl, targetFrameName: ustring; targetDisposition: TCefWindowOpenDisposition; userGesture: Boolean; const popupFeatures: TCefPopupFeatures; var windowInfo: TCefWindowInfo; var client: ICefClient; var settings: TCefBrowserSettings; var noJavascriptAccess, Result: Boolean); + procedure FMXChromium1AfterCreated(Sender: TObject; const browser: ICefBrowser); + procedure FMXChromium1BeforeClose(Sender: TObject; const browser: ICefBrowser); + procedure FMXChromium1Close(Sender: TObject; const browser: ICefBrowser; out Result: Boolean); + + protected + // Variables to control when can we destroy the form safely + FCanClose : boolean; // Set to True in TFMXChromium.OnBeforeClose + FClosing : boolean; // Set to True in the CloseQuery event. + FMXWindowParent : TFMXWindowParent; + FHomepage : string; + + function GetBrowserID : integer; + + procedure ResizeChild; + procedure CreateFMXWindowParent; + function PostCustomMessage(aMessage : cardinal; wParam : cardinal = 0; lParam : integer = 0) : boolean; + + public + procedure NotifyMoveOrResizeStarted; + procedure DoBrowserCreated; + procedure DoDestroyParent; + procedure SendCloseMsg; + + property Closing : boolean read FClosing; + property Homepage : string read FHomepage write FHomepage; + property BrowserID : integer read GetBrowserID; + end; + +implementation + +{$R *.fmx} + +uses + FMX.Platform, FMX.Platform.Win, + uCEFMiscFunctions, uCEFApplication, uFMXApplicationService, uMainForm; + +// Child destruction steps +// ======================= +// 1. FormCloseQuery calls TFMXChromium.CloseBrowser +// 2. TFMXChromium.OnClose sends a CEF_DESTROY message to destroy FMXWindowParent in the main thread. +// 3. TFMXChromium.OnBeforeClose sets FCanClose := True and sends WM_CLOSE to the form. + + +function TChildForm.PostCustomMessage(aMessage, wParam : cardinal; lParam : integer) : boolean; +{$IFDEF MSWINDOWS} +var + TempHWND : HWND; +{$ENDIF} +begin + Result := False; + + {$IFDEF MSWINDOWS} + if (Handle <> nil) then + begin + TempHWND := FmxHandleToHWND(Handle); + Result := (TempHWND <> 0) and WinApi.Windows.PostMessage(TempHWND, aMessage, wParam, lParam); + end; + {$ENDIF} +end; + +function TChildForm.GetBrowserID : integer; +begin + Result := FMXChromium1.BrowserID; +end; + +procedure TChildForm.CreateFMXWindowParent; +begin + if (FMXWindowParent = nil) then + begin + FMXWindowParent := TFMXWindowParent.CreateNew(nil); + FMXWindowParent.Reparent(Handle); + ResizeChild; + FMXWindowParent.Show; + end; +end; + +procedure TChildForm.ResizeChild; +var + TempRect : System.Types.TRect; +begin + if (FMXWindowParent <> nil) then + begin + TempRect.Top := 0; + TempRect.Left := 0; + TempRect.Right := ClientWidth - 1; + TempRect.Bottom := ClientHeight - 1; + + FMXWindowParent.SetBounds(TempRect); + end; +end; + +procedure TChildForm.FMXChromium1AfterCreated(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. + PostCustomMessage(CEF_AFTERCREATED, 0, BrowserID); +end; + +procedure TChildForm.FMXChromium1BeforeClose(Sender: TObject; const browser: ICefBrowser); +begin + FCanClose := True; + PostCustomMessage(WM_CLOSE); +end; + +procedure TChildForm.FMXChromium1BeforePopup(Sender: TObject; + const browser: ICefBrowser; const frame: ICefFrame; const targetUrl, + targetFrameName: ustring; targetDisposition: TCefWindowOpenDisposition; + userGesture: Boolean; const popupFeatures: TCefPopupFeatures; + var windowInfo: TCefWindowInfo; var client: ICefClient; + var settings: TCefBrowserSettings; var noJavascriptAccess, + Result: Boolean); +begin + // For simplicity, this demo blocks all popup windows and new tabs + Result := (targetDisposition in [WOD_NEW_FOREGROUND_TAB, WOD_NEW_BACKGROUND_TAB, WOD_NEW_POPUP, WOD_NEW_WINDOW]); +end; + +procedure TChildForm.FMXChromium1Close(Sender: TObject; const browser: ICefBrowser; out Result: Boolean); +begin + PostCustomMessage(CEF_DESTROY, 0, BrowserID); + Result := True; +end; + +procedure TChildForm.FormClose(Sender: TObject; var Action: TCloseAction); +begin + Action := TCloseAction.caFree; +end; + +procedure TChildForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean); +begin + CanClose := FCanClose; + + if not(FClosing) then + begin + FClosing := True; + FMXChromium1.CloseBrowser(True); + end; +end; + +procedure TChildForm.FormCreate(Sender: TObject); +begin + FCanClose := False; + FClosing := False; + FMXWindowParent := nil; + FHomepage := ''; +end; + +procedure TChildForm.FormDestroy(Sender: TObject); +begin + // Tell the main form that a child has been destroyed. + // The main form will check if this was the last child to close itself + if (MainForm <> nil) then MainForm.SendChildDestroyedMsg; +end; + +procedure TChildForm.FormResize(Sender: TObject); +begin + // TFMXWindowParent has to be resized at runtime + ResizeChild; +end; + +procedure TChildForm.FormShow(Sender: TObject); +var + TempHandle : HWND; + TempRect : System.Types.TRect; + TempClientRect : TRectF; +begin + // TFMXWindowParent has to be created at runtime + CreateFMXWindowParent; + + // 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. + + if not(FMXChromium1.Initialized) then + begin + TempHandle := FmxHandleToHWND(FMXWindowParent.Handle); + TempClientRect := FMXWindowParent.ClientRect; + TempRect.Left := round(TempClientRect.Left); + TempRect.Top := round(TempClientRect.Top); + TempRect.Right := round(TempClientRect.Right); + TempRect.Bottom := round(TempClientRect.Bottom); + + FMXChromium1.CreateBrowser(TempHandle, TempRect); + end; +end; + +procedure TChildForm.NotifyMoveOrResizeStarted; +begin + // This is needed to display some HTML elements correctly + if (FMXChromium1 <> nil) then FMXChromium1.NotifyMoveOrResizeStarted; +end; + +procedure TChildForm.DoBrowserCreated; +begin + // Load the homepage after the browser is fully initialized + if (length(FHomepage) > 0) then FMXChromium1.LoadURL(FHomepage); +end; + +procedure TChildForm.DoDestroyParent; +begin + // We destroy FMXWindowParent safely in the main thread and this will trigger the TFMXChromium.OnBeforeClose event. + if (FMXWindowParent <> nil) then FreeAndNil(FMXWindowParent); +end; + +procedure TChildForm.SendCloseMsg; +begin + PostCustomMessage(WM_CLOSE); +end; + +end. diff --git a/demos/FMXToolBoxBrowser/uFMXApplicationService.pas b/demos/FMXToolBoxBrowser/uFMXApplicationService.pas new file mode 100644 index 00000000..81ea39c5 --- /dev/null +++ b/demos/FMXToolBoxBrowser/uFMXApplicationService.pas @@ -0,0 +1,225 @@ +// ************************************************************************ +// ***************************** 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 Diaz 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 uFMXApplicationService; + +{$I cef.inc} + +// This unit is based in the TFMXApplicationService class created by Takashi Yamamoto +// https://www.gesource.jp/weblog/?p=7367 + +interface + +uses + FMX.Platform; + +type + TFMXApplicationService = class(TInterfacedObject, IFMXApplicationService) + protected + class var OldFMXApplicationService: IFMXApplicationService; + class var NewFMXApplicationService: IFMXApplicationService; + + public + procedure Run; + function HandleMessage: Boolean; + procedure WaitMessage; + function GetDefaultTitle: string; + function GetTitle: string; + procedure SetTitle(const Value: string); + function GetVersionString: string; + procedure Terminate; + function Terminating: Boolean; + function Running: Boolean; + + class procedure AddPlatformService; + + property DefaultTitle : string read GetDefaultTitle; + property Title : string read GetTitle write SetTitle; + property AppVersion : string read GetVersionString; + end; + +implementation + +uses + FMX.Forms, + uMainForm, + uChildForm, + uCEFApplication, + {$IFDEF MSWINDOWS} + Winapi.Messages, Winapi.Windows, + {$ENDIF} + uCEFConstants; + +class procedure TFMXApplicationService.AddPlatformService; +begin + if TPlatformServices.Current.SupportsPlatformService(IFMXApplicationService, IInterface(OldFMXApplicationService)) then + begin + TPlatformServices.Current.RemovePlatformService(IFMXApplicationService); + + NewFMXApplicationService := TFMXApplicationService.Create; + TPlatformServices.Current.AddPlatformService(IFMXApplicationService, NewFMXApplicationService); + end; +end; + +function TFMXApplicationService.GetDefaultTitle: string; +begin + Result := OldFMXApplicationService.GetDefaultTitle; +end; + +function TFMXApplicationService.GetTitle: string; +begin + Result := OldFMXApplicationService.GetTitle; +end; + +function TFMXApplicationService.GetVersionString: string; +begin + Result := OldFMXApplicationService.GetVersionString; +end; + +procedure TFMXApplicationService.Run; +begin + OldFMXApplicationService.Run; +end; + +procedure TFMXApplicationService.SetTitle(const Value: string); +begin + OldFMXApplicationService.SetTitle(Value); +end; + +procedure TFMXApplicationService.Terminate; +begin + OldFMXApplicationService.Terminate; +end; + +function TFMXApplicationService.Terminating: Boolean; +begin + Result := OldFMXApplicationService.Terminating; +end; + +procedure TFMXApplicationService.WaitMessage; +begin + OldFMXApplicationService.WaitMessage; +end; + +function TFMXApplicationService.Running: Boolean; +begin + {$IFDEF DELPHI24_UP} + Result := OldFMXApplicationService.Running; + {$ELSE} + Result := True; + {$ENDIF} +end; + +function TFMXApplicationService.HandleMessage: Boolean; +{$IFDEF MSWINDOWS} +var + i : integer; + TempMsg : TMsg; +{$ENDIF} +begin + {$IFDEF MSWINDOWS} + if PeekMessage(TempMsg, 0, 0, 0, PM_NOREMOVE) then + case TempMsg.Message of + WM_MOVE, + WM_MOVING : + if not(Application.Terminated) and + (screen.ActiveForm <> nil) and + (screen.ActiveForm is TChildForm) then + TChildForm(screen.ActiveForm).NotifyMoveOrResizeStarted; + + WM_ENTERMENULOOP : + if not(Application.Terminated) and + (TempMsg.wParam = 0) and + (GlobalCEFApp <> nil) then + GlobalCEFApp.OsmodalLoop := True; + + WM_EXITMENULOOP : + if not(Application.Terminated) and + (TempMsg.wParam = 0) and + (GlobalCEFApp <> nil) then + GlobalCEFApp.OsmodalLoop := False; + + CEF_INITIALIZED : + if not(Application.Terminated) and + (Application.MainForm <> nil) and + (Application.MainForm is TMainForm) then + TMainForm(Application.MainForm).DoCEFInitialized; + + CEF_CHILDDESTROYED : + if not(Application.Terminated) and + (Application.MainForm <> nil) and + (Application.MainForm is TMainForm) then + TMainForm(Application.MainForm).DoChildDestroyed; + + CEF_AFTERCREATED : + if not(Application.Terminated) then + begin + i := 0; + + while (i < screen.FormCount) do + if (screen.Forms[i] is TChildForm) and + (TChildForm(screen.Forms[i]).BrowserID = TempMsg.lParam) then + begin + TChildForm(screen.Forms[i]).DoBrowserCreated; + i := screen.FormCount; + end + else + inc(i); + end; + + CEF_DESTROY : + if not(Application.Terminated) then + begin + i := 0; + + while (i < screen.FormCount) do + if (screen.Forms[i] is TChildForm) and + (TChildForm(screen.Forms[i]).BrowserID = TempMsg.lParam) then + begin + TChildForm(screen.Forms[i]).DoDestroyParent; + i := screen.FormCount; + end + else + inc(i); + end; + end; + {$ENDIF} + + Result := OldFMXApplicationService.HandleMessage; +end; + +end. diff --git a/demos/FMXToolBoxBrowser/uMainForm.fmx b/demos/FMXToolBoxBrowser/uMainForm.fmx new file mode 100644 index 00000000..cd3232cb --- /dev/null +++ b/demos/FMXToolBoxBrowser/uMainForm.fmx @@ -0,0 +1,44 @@ +object MainForm: TMainForm + Left = 0 + Top = 0 + BorderIcons = [biSystemMenu, biMinimize] + BorderStyle = Single + Caption = 'Initializing browser. Please wait...' + ClientHeight = 23 + ClientWidth = 404 + Position = ScreenCenter + FormFactor.Width = 320 + FormFactor.Height = 480 + FormFactor.Devices = [Desktop] + OnCreate = FormCreate + OnCloseQuery = FormCloseQuery + OnShow = FormShow + DesignerMasterStyle = 0 + object ButtonPnl: TPanel + Align = Client + Enabled = False + Size.Width = 404.000000000000000000 + Size.Height = 23.000000000000000000 + Size.PlatformDefault = False + TabOrder = 0 + object AddressEdt: TEdit + Touch.InteractiveGestures = [LongTap, DoubleTap] + Align = Client + TabOrder = 0 + Text = 'https://www.google.com' + Size.Width = 324.000000000000000000 + Size.Height = 23.000000000000000000 + Size.PlatformDefault = False + end + object OpenBtn: TButton + Align = Right + Position.X = 324.000000000000000000 + Size.Width = 80.000000000000000000 + Size.Height = 23.000000000000000000 + Size.PlatformDefault = False + TabOrder = 1 + Text = 'Open' + OnClick = OpenBtnClick + end + end +end diff --git a/demos/FMXToolBoxBrowser/uMainForm.pas b/demos/FMXToolBoxBrowser/uMainForm.pas new file mode 100644 index 00000000..bf728a2d --- /dev/null +++ b/demos/FMXToolBoxBrowser/uMainForm.pas @@ -0,0 +1,280 @@ +// ************************************************************************ +// ***************************** 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 Diaz 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 MSWINDOWS} + Winapi.Messages, Winapi.Windows, + {$ENDIF} + System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, + FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Edit, + FMX.Controls.Presentation, FMX.StdCtrls; + + +const + CEF_CHILDDESTROYED = WM_APP + $100; + CEF_INITIALIZED = WM_APP + $101; + +type + TMainForm = class(TForm) + ButtonPnl: TPanel; + AddressEdt: TEdit; + OpenBtn: TButton; + procedure FormShow(Sender: TObject); + procedure FormCreate(Sender: TObject); + procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); + procedure OpenBtnClick(Sender: TObject); + private + // Variables to control when can we destroy the form safely + FCanClose : boolean; // Set to True when all the child forms are closed + FClosing : boolean; // Set to True in the CloseQuery event. + + function GetChildFormCount : integer; + function GetChildClosing : boolean; + + procedure CreateToolboxChild(const ChildCaption, URL: string); + procedure CloseAllChildForms; + function PostCustomMessage(aMessage : cardinal; wParam : cardinal = 0; lParam : integer = 0) : boolean; + + protected + + public + procedure DoCEFInitialized; + procedure DoChildDestroyed; + procedure SendChildDestroyedMsg; + + property ChildClosing : boolean read GetChildClosing; + property ChildFormCount : integer read GetChildFormCount; + end; + +var + MainForm: TMainForm; + +procedure CreateGlobalCEFApp; + +implementation + +{$R *.fmx} + +uses + FMX.Platform, FMX.Platform.Win, + uCEFMiscFunctions, uFMXApplicationService, uChildForm, uCEFApplication; + +// Main form destruction steps +// =========================== +// 1. Destroy all child forms +// 2. Wait until all the child forms are closed before closing the main form and terminating the application. + + +procedure GlobalCEFApp_OnContextInitialized; +begin + if (MainForm <> nil) then MainForm.PostCustomMessage(CEF_INITIALIZED); +end; + +procedure CreateGlobalCEFApp; +begin + GlobalCEFApp := TCefApplication.Create; + GlobalCEFApp.OnContextInitialized := GlobalCEFApp_OnContextInitialized; +end; + +function TMainForm.PostCustomMessage(aMessage, wParam : cardinal; lParam : integer) : boolean; +{$IFDEF MSWINDOWS} +var + TempHWND : HWND; +{$ENDIF} +begin + Result := False; + + {$IFDEF MSWINDOWS} + if (Handle <> nil) then + begin + TempHWND := FmxHandleToHWND(Handle); + Result := (TempHWND <> 0) and WinApi.Windows.PostMessage(TempHWND, aMessage, wParam, lParam); + end; + {$ENDIF} +end; + +procedure TMainForm.CreateToolboxChild(const ChildCaption, URL: string); +var + TempChild : TChildForm; +begin + if (length(URL) > 0) then + begin + TempChild := TChildForm.Create(self); + TempChild.Caption := ChildCaption; + TempChild.Homepage := URL; + TempChild.Show; + end; +end; + +function TMainForm.GetChildFormCount : integer; +var + i : integer; + TempComponent : TComponent; +begin + Result := 0; + i := pred(ComponentCount); + + while (i >= 0) do + begin + TempComponent := Components[i]; + + if (TempComponent <> nil) and + (TempComponent is TChildForm) then + inc(Result); + + dec(i); + end; +end; + +function TMainForm.GetChildClosing : boolean; +var + i : integer; + TempComponent : TComponent; +begin + Result := false; + i := pred(ComponentCount); + + while (i >= 0) do + begin + TempComponent := Components[i]; + + if (TempComponent <> nil) and + (TempComponent is TChildForm) then + begin + if TChildForm(Components[i]).Closing then + begin + Result := True; + exit; + end + else + dec(i); + end + else + dec(i); + end; +end; + +procedure TMainForm.OpenBtnClick(Sender: TObject); +begin + CreateToolboxChild('Browser', AddressEdt.Text); +end; + +procedure TMainForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean); +begin + // The main form closes all child forms first and only after that it sets CanClose to True. + if FClosing or ChildClosing then + CanClose := FCanClose + else + begin + FClosing := True; + + if (ChildFormCount = 0) then + CanClose := True + else + begin + CanClose := False; + ButtonPnl.Enabled := False; + + CloseAllChildForms; + end; + end; +end; + +procedure TMainForm.CloseAllChildForms; +var + i : integer; + TempComponent : TComponent; +begin + i := pred(ComponentCount); + + while (i >= 0) do + begin + TempComponent := Components[i]; + + if (TempComponent <> nil) and + (TempComponent is TChildForm) and + not(TChildForm(Components[i]).Closing) then + TChildForm(Components[i]).SendCloseMsg; + + dec(i); + end; +end; + +procedure TMainForm.FormCreate(Sender: TObject); +begin + // TFMXApplicationService is used to handle custom Windows messages + TFMXApplicationService.AddPlatformService; + + FCanClose := False; + FClosing := False; +end; + +procedure TMainForm.FormShow(Sender: TObject); +begin + if (GlobalCEFApp <> nil) and GlobalCEFApp.GlobalContextInitialized then DoCEFInitialized; +end; + +procedure TMainForm.DoCEFInitialized; +begin + // Enable the GUI when the global context is initialized. + Caption := 'FMX ToolBox Browser'; + ButtonPnl.Enabled := True; + cursor := crDefault; +end; + +procedure TMainForm.DoChildDestroyed; +begin + // If there are no more child forms we can destroy the main form + if FClosing and (ChildFormCount = 0) then + begin + FCanClose := True; + PostCustomMessage(WM_CLOSE); + end; +end; + +procedure TMainForm.SendChildDestroyedMsg; +begin + PostCustomMessage(CEF_CHILDDESTROYED); +end; + +end.