2017-05-21 17:41:10 +02:00
// ************************************************************************
// ***************************** CEF4Delphi *******************************
// ************************************************************************
//
2019-10-19 10:58:34 +02:00
// CEF4Delphi is based on DCEF3 which uses CEF to embed a chromium-based
2017-05-21 17:41:10 +02:00
// 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
//
2019-05-19 16:08:15 +02:00
// Copyright © 2019 Salvador Diaz Fau. All rights reserved.
2017-05-21 17:41:10 +02:00
//
// ************************************************************************
// ************ 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 < hgourvest@ gmail. com>
* 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;
2019-05-19 16:08:15 +02:00
{$MODE Delphi}
2017-05-21 17:41:10 +02:00
{$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;
{$ELSE}
2019-05-19 16:08:15 +02:00
LCLIntf, LCLType, LMessages, Messages, SysUtils, Variants, Classes, Graphics,
2019-10-09 12:24:47 +02:00
Controls, Forms, Dialogs, StdCtrls, ExtCtrls, uCEFSentinel;
2017-05-21 17:41:10 +02:00
{$ENDIF}
const
CEFBROWSER_CREATED = WM_APP + $100 ;
CEFBROWSER_CHILDDESTROYED = WM_APP + $101 ;
2017-06-11 17:48:20 +02:00
CEFBROWSER_DESTROY = WM_APP + $102 ;
2017-12-14 12:09:13 +01:00
CEFBROWSER_INITIALIZED = WM_APP + $103 ;
2017-05-21 17:41:10 +02:00
type
2019-10-09 12:24:47 +02:00
{ TMainForm }
2017-05-21 17:41:10 +02:00
TMainForm = class( TForm)
2017-12-14 12:09:13 +01:00
ButtonPnl: TPanel;
2019-10-09 12:24:47 +02:00
CEFSentinel1: TCEFSentinel;
2017-05-21 17:41:10 +02:00
Edit1: TEdit;
2017-12-14 12:09:13 +01:00
Button1: TButton;
2019-10-09 12:24:47 +02:00
procedure CEFSentinel1Close( Sender: TObject) ;
2017-05-21 17:41:10 +02:00
procedure FormCreate( Sender: TObject) ;
procedure Button1Click( Sender: TObject) ;
2017-12-14 12:09:13 +01:00
procedure FormShow( Sender: TObject) ;
2017-05-21 17:41:10 +02:00
private
// Variables to control when can we destroy the form safely
2017-06-11 17:48:20 +02:00
FCanClose : boolean ; // Set to True when all the child forms are closed
2017-05-21 17:41:10 +02:00
FClosing : boolean ; // Set to True in the CloseQuery event.
procedure CreateToolboxChild( const ChildCaption, URL: string ) ;
procedure CloseAllChildForms;
function GetChildClosing : boolean ;
function GetChildFormCount : integer ;
protected
procedure ChildDestroyedMsg( var aMessage : TMessage) ; message CEFBROWSER_CHILDDESTROYED;
2017-12-14 12:09:13 +01:00
procedure CEFInitializedMsg( var aMessage : TMessage) ; message CEFBROWSER_INITIALIZED;
2017-05-21 17:41:10 +02:00
public
function CloseQuery: Boolean ; override ;
property ChildClosing : boolean read GetChildClosing;
property ChildFormCount : integer read GetChildFormCount;
end ;
var
MainForm: TMainForm;
2018-06-17 14:18:11 +02:00
procedure CreateGlobalCEFApp;
2017-12-14 12:09:13 +01:00
2017-05-21 17:41:10 +02:00
implementation
2019-05-19 16:08:15 +02:00
{$R *.lfm}
2017-05-21 17:41:10 +02:00
uses
2017-12-14 12:09:13 +01:00
uChildForm, uCEFApplication;
2017-05-21 17:41:10 +02:00
// Destruction steps
// =================
// 1. Destroy all child forms
2019-10-14 15:39:27 +02:00
// 2. Wait until all the child forms are closed before calling TCEFSentinel.Start, which will trigger TCEFSentinel.OnClose when all renderer processes are closed
// 3. TCEFSentinel.OnClose closes the main form.
2017-05-21 17:41:10 +02:00
2017-12-14 12:09:13 +01:00
procedure GlobalCEFApp_OnContextInitialized;
begin
2017-12-27 14:05:33 +01:00
if ( MainForm < > nil ) and MainForm. HandleAllocated then
PostMessage( MainForm. Handle, CEFBROWSER_INITIALIZED, 0 , 0 ) ;
2017-12-14 12:09:13 +01:00
end ;
2018-06-17 14:18:11 +02:00
procedure CreateGlobalCEFApp;
begin
GlobalCEFApp : = TCefApplication. Create;
2019-06-19 16:53:26 +02:00
GlobalCEFApp. OnContextInitialized : = GlobalCEFApp_OnContextInitialized;
2018-06-17 14:18:11 +02:00
end ;
2017-05-21 17:41:10 +02:00
procedure TMainForm. CreateToolboxChild( const ChildCaption, URL: string ) ;
var
TempChild : TChildForm;
begin
TempChild : = TChildForm. Create( self) ;
TempChild. Caption : = ChildCaption;
TempChild. Homepage : = URL;
TempChild. Show;
end ;
procedure TMainForm. FormCreate( Sender: TObject) ;
begin
FCanClose : = False ;
FClosing : = False ;
end ;
2019-10-09 12:24:47 +02:00
procedure TMainForm. CEFSentinel1Close( Sender: TObject) ;
begin
FCanClose : = True ;
PostMessage( Handle, WM_CLOSE, 0 , 0 ) ;
end ;
2017-05-21 17:41:10 +02:00
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
PostMessage( TChildForm( Components[ i] ) . Handle, WM_CLOSE, 0 , 0 ) ;
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 ;
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 ;
procedure TMainForm. Button1Click( Sender: TObject) ;
begin
CreateToolboxChild( 'Browser' , Edit1. Text ) ;
end ;
procedure TMainForm. ChildDestroyedMsg( var aMessage : TMessage) ;
begin
2019-10-09 12:24:47 +02:00
// If there are no more child forms we start the sentinel
if FClosing and ( ChildFormCount = 0 ) then CEFSentinel1. Start;
2017-05-21 17:41:10 +02:00
end ;
function TMainForm. CloseQuery: Boolean ;
begin
if FClosing or ChildClosing then
Result : = FCanClose
else
begin
FClosing : = True ;
if ( ChildFormCount = 0 ) then
Result : = True
else
begin
Result : = False ;
Edit1. Enabled : = False ;
Button1. Enabled : = False ;
CloseAllChildForms;
end ;
end ;
end ;
2017-12-14 12:09:13 +01:00
procedure TMainForm. CEFInitializedMsg( var aMessage : TMessage) ;
begin
Caption : = 'ToolBox Browser' ;
ButtonPnl. Enabled : = True ;
cursor : = crDefault;
end ;
procedure TMainForm. FormShow( Sender: TObject) ;
begin
if ( GlobalCEFApp < > nil ) and GlobalCEFApp. GlobalContextInitialized then
begin
Caption : = 'ToolBox Browser' ;
ButtonPnl. Enabled : = True ;
cursor : = crDefault;
end ;
end ;
2017-05-21 17:41:10 +02:00
end .