TChromium control - Initialization issue

john.augustine
Posts: 18
Joined: Fri Jul 10, 2020 1:33 pm

TChromium control - Initialization issue

Post by john.augustine » Fri Jul 10, 2020 2:06 pm

Hi,

I am trying to create a small browser utility bu using CEF4 Delphi.

System Information:
It's a real PC and not a virtual machine
Operation System: Windows 10 Enterprise
System Type: 64-bit
Delphi version: Delphi 10 Seattle
Installed CEF4 controls in my developer environment

About Utility:
Utility contains,Main Form & Browser form. Here, i am trying open the browser form by click on "Open Browser" button which is in Main Form.
I am using "class function" to create the browser form and sending URL as parameter.

In browser form, using "LoadURL" to open the web site. Here, "GetInitialized" is always failing due to FBrowserId is 0. Hence page is not loading.
I have placed TButton (GO button) on the same browser form and used "LoadURL" (on Click), surprised....now the LoadURL is working fine and there is no Initialization issue....If i add a simple ShowMessage('Hi') when before calling LoadURL then it works fine.

Still wondering, why working only with Button click and ShowMessage (on the browser form)....and not working when calling from Main Form.

Could you please help me to resolve this issue?

Code:

******************************************************************************Main Form:**************************************************************
unit Main;

interface

uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
TfrmMain = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
frmMain: TfrmMain;

implementation

uses Browser;

{$R *.dfm}

procedure TfrmMain.Button1Click(Sender: TObject);
var
lURL: string;
begin
lURL:= 'www.google.com';
TfrmBrowser.Execute(lURL);
end;

end.

******************************************************************************Browser Form:**************************************************************

Browser Form:

unit Browser;

{$I cef.inc}

interface

uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, uCEFChromiumCore, uCEFChromium,
uCEFWinControl, uCEFWindowParent, uCEFTypes, uCEFInterfaces, uCEFConstants,
uCEFApplication, uCEFStringVisitor, Vcl.ExtCtrls, Vcl.StdCtrls, Vcl.ComCtrls,
System.NetEncoding, Vcl.AppEvnts;

type
TfrmBrowser = class(TForm)
CEFWindowParent: TCEFWindowParent;
dLoadTimer: TTimer;
Panel1: TPanel;
Button1: TButton;
dStatusBar: TStatusBar;
dACRChromiumBrowser: TChromium;
procedure FormCreate(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure dLoadTimerTimer(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure dACRChromiumBrowserLoadError(Sender: TObject;
const browser: ICefBrowser; const frame: ICefFrame; errorCode: Integer;
const errorText, failedUrl: ustring);
procedure dACRChromiumBrowserBeforeContextMenu(Sender: TObject;
const browser: ICefBrowser; const frame: ICefFrame;
const params: ICefContextMenuParams; const model: ICefMenuModel);
procedure dACRChromiumBrowserBeforeBrowse(Sender: TObject;
const browser: ICefBrowser; const frame: ICefFrame;
const request: ICefRequest; user_gesture, isRedirect: Boolean;
out Result: Boolean);
procedure dACRChromiumBrowserLoadEnd(Sender: TObject;
const browser: ICefBrowser; const frame: ICefFrame;
httpStatusCode: Integer);
private
{ Private declarations }
fURL: string;
procedure LoadBrowser(aURL: string);
public
{ Public declarations }
class function Execute( aURL: String ): TModalResult;
end;

var
frmBrowser: TfrmBrowser;

implementation

{$R *.dfm}

procedure TfrmBrowser.Button1Click(Sender: TObject);
begin
dACRChromiumBrowser.LoadURL(fURL);
end;

procedure TfrmBrowser.dACRChromiumBrowserBeforeBrowse(Sender: TObject;
const browser: ICefBrowser; const frame: ICefFrame;
const request: ICefRequest; user_gesture, isRedirect: Boolean;
out Result: Boolean);
begin
dStatusBar.Panels[0].Text := request.Url;
end;

procedure TfrmBrowser.dACRChromiumBrowserBeforeContextMenu(Sender: TObject;
const browser: ICefBrowser; const frame: ICefFrame;
const params: ICefContextMenuParams; const model: ICefMenuModel);
begin
model.Clear;
end;

procedure TfrmBrowser.dACRChromiumBrowserLoadEnd(Sender: TObject;
const browser: ICefBrowser; const frame: ICefFrame; httpStatusCode: Integer);
begin
dStatusBar.Panels[0].Text := 'Done';
end;

procedure TfrmBrowser.dACRChromiumBrowserLoadError(Sender: TObject;
const browser: ICefBrowser; const frame: ICefFrame; errorCode: Integer;
const errorText, failedUrl: ustring);
var
TempString : string;
begin
if (errorCode = ERR_ABORTED) then exit;

TempString := '<html><body bgcolor="white">' +
'<h2>Failed to load URL ' + failedUrl +
' with error ' + errorText +
' (' + inttostr(errorCode) + ').</h2></body></html>';

dACRChromiumBrowser.LoadString(TempString, frame)
end;

procedure TfrmBrowser.dLoadTimerTimer(Sender: TObject);
begin
dLoadTimer.Enabled := False;
if not(dACRChromiumBrowser.CreateBrowser(CEFWindowParent, '')) and
not(dACRChromiumBrowser.Initialized) then
dLoadTimer.Enabled := True;
end;

class function TfrmBrowser.Execute( aURL: String ): TModalResult;
var
lfrmBrowser: TfrmBrowser;
begin
lfrmBrowser := TfrmBrowser.Create(nil);
lfrmBrowser.fURL:= aURL;

try
Result := lfrmBrowser.ShowModal;
finally
FreeAndNil( lfrmBrowser );
end;
end;

procedure TfrmBrowser.FormCreate(Sender: TObject);
begin
dACRChromiumBrowser.MultiBrowserMode := True;
end;

procedure TfrmBrowser.FormShow(Sender: TObject);
begin
try
if not(dACRChromiumBrowser.CreateBrowser(CEFWindowParent, '')) then dLoadTimer.Enabled := True;

if fURL <> '' then
LoadBrowser(fURL);
except
on E: Exception do
begin
end;
end;
end;

procedure TfrmBrowser.LoadBrowser(aURL: string);
begin
dACRChromiumBrowser.LoadURL(aURL, '');
end;

end.

*********************************************************************************DPR***************************************************************************************
program Test_Browser_03;

{$I cef.inc}

uses
Vcl.Forms,
uCEFApplication,
Main in 'Main.pas' {frmMain},
Browser in 'Browser.pas' {frmBrowser};

{$R *.res}

begin
GlobalCEFApp := TCefApplication.Create;
GlobalCEFApp.cache:= 'cache';

if GlobalCEFApp.StartMainProcess then
begin
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TfrmMain, frmMain);
Application.Run;
end;

GlobalCEFApp.Free;
GlobalCEFApp := nil;
end.

************************************************************************************************************************************************************************

Thanks & Regards,
John Augustine
Last edited by john.augustine on Fri Jul 10, 2020 2:28 pm, edited 1 time in total.

User avatar
salvadordf
Posts: 2495
Joined: Thu Feb 02, 2017 12:24 pm
Location: Spain
Contact:

Re: TChromium control - Initialization issue

Post by salvadordf » Fri Jul 10, 2020 2:24 pm

Hi,

Read this post about the browser initialization :
https://www.briskbard.com/forum/viewtopic.php?f=8&t=1391#p5773

It's necessary to wait for the TChromium.OnAfterCreated event after the TChromium.CreateBrowser call before loading any URL.

You can also set the TChromium.DefaultURL property before the TChromium.CreateBrowser call to load that URL as soon as the browser is fully initialized.

This application is similar to the ToolBoxBrowser demo but it needs to implement the destruction steps. Please, use the code in that demo as a template for this application.

john.augustine
Posts: 18
Joined: Fri Jul 10, 2020 1:33 pm

Re: TChromium control - Initialization issue

Post by john.augustine » Fri Jul 10, 2020 2:43 pm

Awesome!!!

It works! Thank you so much for your help!!!

As you suggested, set the DefaultUrl when before "CreateBrowser" and it works fine. Still, i have one question.

Question:
So, shall i set my actual target URL as DefaultUrl and avoid using LoadURL?

Kindly advice on this.

Thanks & Regards,
John Augustine

******************************************************************************************************************************************************************************
procedure TfrmBrowser.FormShow(Sender: TObject);
begin
try
dACRChromiumBrowser.DefaultUrl:= fURL;
if not(dACRChromiumBrowser.CreateBrowser(CEFWindowParent, '')) then dLoadTimer.Enabled := True;

if fURL <> '' then
LoadBrowser(fURL);
except
on E: Exception do
begin
end;
end;
end;

procedure TfrmBrowser.LoadBrowser(aURL: string);
begin
//dACRChromiumBrowser.LoadURL(aURL, '');
end;

User avatar
salvadordf
Posts: 2495
Joined: Thu Feb 02, 2017 12:24 pm
Location: Spain
Contact:

Re: TChromium control - Initialization issue

Post by salvadordf » Fri Jul 10, 2020 2:55 pm

Both solutions are perfectly valid.

Perhaps setting DefaultURL is a little bit better because the user can navigate back from LoadURL and he/she would see a white screen in that case.

john.augustine
Posts: 18
Joined: Fri Jul 10, 2020 1:33 pm

Re: TChromium control - Initialization issue

Post by john.augustine » Fri Jul 10, 2020 3:28 pm

Great!!!

Thanks a lot for your quick reply/help!!!

Happy Week End!

Thanks & Regards,
John Augustine

john.augustine
Posts: 18
Joined: Fri Jul 10, 2020 1:33 pm

Re: TChromium control - Initialization issue

Post by john.augustine » Sat Jul 11, 2020 5:05 pm

Hi,

As you suggested, i have used/applied "ToolBoxBrowser" demo code. Now, everything is fine except one issue.
Actually, in my application my URL contains "HTML" data having URL, token to open the corresponding page. So, i didn't go with DefaultURL instead using LoadURL [ used the concept of PostMessage(Handle, CEFBROWSER_CREATED, 0, 0) ].

Now, page is loading without "ShowMessage" or any "button click". In this page, there is a functionality like, page should open in a new page/popup window when i click detach button. But, the corresponding data is displaying in same current browser window and not in new window. Actually, a new page is opening but immediately it is closing and again the entire page refreshing and loading again.

Could please help me on this?

Thanks & Regards,
John Augustine

User avatar
salvadordf
Posts: 2495
Joined: Thu Feb 02, 2017 12:24 pm
Location: Spain
Contact:

Re: TChromium control - Initialization issue

Post by salvadordf » Sun Jul 12, 2020 7:56 am

john.augustine wrote:
Sat Jul 11, 2020 5:05 pm
Hi,

As you suggested, i have used/applied "ToolBoxBrowser" demo code. Now, everything is fine except one issue.
Actually, in my application my URL contains "HTML" data having URL, token to open the corresponding page. So, i didn't go with DefaultURL instead using LoadURL [ used the concept of PostMessage(Handle, CEFBROWSER_CREATED, 0, 0) ].
If you try to load a DATA URI you should be able to set it to TChromium.DefaultURL without a problem.
john.augustine wrote:
Sat Jul 11, 2020 5:05 pm
Now, page is loading without "ShowMessage" or any "button click". In this page, there is a functionality like, page should open in a new page/popup window when i click detach button. But, the corresponding data is displaying in same current browser window and not in new window. Actually, a new page is opening but immediately it is closing and again the entire page refreshing and loading again.
Could please help me on this?
I'm sorry but I don't understand. I would need to see the code to reproduce the issue in my computer.

john.augustine
Posts: 18
Joined: Fri Jul 10, 2020 1:33 pm

Re: TChromium control - Initialization issue

Post by john.augustine » Sun Jul 12, 2020 3:59 pm

Hi,

Thank you for your reply!

Below is the code...

Thanks & Regards,
John Augustine

***************************************************************************************************************************************************************************************

unit Browser;

{$I cef.inc}

interface

{$WARN UNIT_PLATFORM OFF}

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, XMLIntf, XMLDoc, ActnList, ImgList, ExtCtrls, ComCtrls, INIFiles,
OleCtrls, SHDocVw, ToolWin, StrUtils, ActiveX, Math, uCEFWinControl, uCEFChromiumWindow,
uCEFChromiumCore, uCEFChromium, uCEFWindowParent, uCEFInterfaces, uCEFApplication,
uCEFTypes, uCEFConstants, uCEFSentinel, uCEFStringVisitor;

const
CEFBROWSER_CREATED = WM_APP + $100;

type
TfrmBrowser = class(ThmBaseSizeableDialog)
dToolBar: TToolBar;
dCloseToolButton: TToolButton;
dLoadTimer: TTimer;
CEFWindowParent: TCEFWindowParent;
dACRChromiumBrowser: TChromium;

procedure dCloseToolButtonClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure dLoadTimerTimer(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure dACRChromiumBrowserAfterCreated(Sender: TObject; const browser: ICefBrowser);
private
fFileCache: ThmFileCache;
fHTML: string;

procedure LoadFromString(const HTML: string);
procedure Load;
protected
procedure BrowserCreatedMsg(var aMessage : TMessage); message CEFBROWSER_CREATED;
public
//Display dialog (Action from Main form)
class function Execute( const aCaregiverID, aPatientID: Integer; const aServiceName, aServiceDiplayName, aServiceConfig: String ): TModalResult;

end;

implementation

{$R *.dfm}

class function TfrmBrowser.Execute( const aCaregiverID, aPatientID: Integer;
const aServiceName, aServiceDiplayName, aServiceConfig: String ): TModalResult;
var
lfrmBrowser: TfrmBrowser;
begin
lfrmBrowser := TfrmBrowser.Create(nil);
try
Result := lfrmBrowser.ShowModal;
finally
FreeAndNil( lfrmBrowser );
end;
end;

procedure TfrmBrowser.FormCreate(Sender: TObject);
begin
fFileCache:= ThmFileCache.Create;
dACRChromiumBrowser.MultiBrowserMode := True;
end;

procedure TfrmBrowser.FormShow(Sender: TObject);
begin
try
dACRChromiumBrowser.DefaultUrl := 'about:blank';
Load;
dACRChromiumBrowser.CreateBrowser(CEFWindowParent, '');

//if not(dACRChromiumBrowser.CreateBrowser(CEFWindowParent, '')) then dLoadTimer.Enabled := True;
except
on E: Exception do
begin
end;
end;
end;

procedure TfrmBrowser.Load;
var
Launch: TemrLaunch;
LaunchType: TemrLaunchType;
lResult: String;
begin
try
Launch.GenerateRequest(LaunchType, lResult);
LoadFromString( lResult );
finally
Launch.Free;
end;
end;

procedure TfrmBrowser.LoadFromString(const HTML: string);
var
lTempFilename: string;
begin
fHTML := HTML;

//lTempFilename := fFileCache.SaveToFile('html', HTML);
//dACRChromiumBrowser.LoadURL(lTempFilename);
end;

procedure TfrmBrowser.dACRChromiumBrowserAfterCreated(
Sender: TObject; const browser: ICefBrowser);
var
lTempFilename: string;
begin
PostMessage(Handle, CEFBROWSER_CREATED, 0, 0);
end;

procedure TfrmBrowser.BrowserCreatedMsg(var aMessage : TMessage);
var
lTempFilename: string;
begin
lTempFilename := fFileCache.SaveToFile('html', fHTML);
dACRChromiumBrowser.LoadURL(lTempFilename);
end;

procedure TfrmBrowser.dLoadTimerTimer(Sender: TObject);
begin
dLoadTimer.Enabled := False;
if not(dACRChromiumBrowser.CreateBrowser(CEFWindowParent, '')) and not(dACRChromiumBrowser.Initialized) then
dLoadTimer.Enabled := True;
end;

procedure TfrmBrowser.dCloseToolButtonClick(Sender: TObject);
begin
ModalResult := mrOK;
end;

procedure TfrmBrowser.FormDestroy(Sender: TObject);
begin
FreeAndNil(fFileCache);
end;

end.

User avatar
salvadordf
Posts: 2495
Joined: Thu Feb 02, 2017 12:24 pm
Location: Spain
Contact:

Re: TChromium control - Initialization issue

Post by salvadordf » Mon Jul 13, 2020 9:59 am

Open the ToolBoxBrowser demo and modify the TMainForm.Button1Click procedure.

Create a DATA URL with your custom HTML instead of setting the Edit1.Text as the URL parameter.

Call Launch.GenerateRequest to get the HTML in lResult and then create the DATA URI with this :

Code: Select all

MyNewDataUri := CefGetDataURI(lResult, 'text/html');
You should call CreateToolboxChild using this code :

Code: Select all

CreateToolboxChild('My custom window title', MyNewDataUri);

john.augustine
Posts: 18
Joined: Fri Jul 10, 2020 1:33 pm

Re: TChromium control - Initialization issue

Post by john.augustine » Mon Jul 13, 2020 12:31 pm

Hi

Thank you for your reply!

I tried below logic and it works fine without any issues! I have downloaded this code from one of the discussion in forum. I hope you have attached this project...(MiniBrowser - Latest)

Thanks a lot for all your timely help!

procedure TMiniBrowserFrm.Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser);
begin
PostMessage(Handle, CEF_AFTERCREATED, Integer(browser.Wrap), 0);
end;

procedure TMiniBrowserFrm.BrowserCreatedMsg(var aMessage : TMessage);
var
browser: ICefBrowser;
begin
CEFWindowParent1.UpdateSize;
NavControlPnl.Enabled := True;
try
browser := TCefBrowserRef.UnWrap(Pointer(aMessage.WParam));
if browser.IsSame(Chromium1.Browser) then
begin
AddURL(MINIBROWSER_HOMEPAGE);
browser.MainFrame.LoadUrl(MINIBROWSER_HOMEPAGE);
end;
finally
browser := nil
end;
end;

Post Reply