Disclosure Statement: This site contains affiliate links, which means that I may receive a commission if you make a purchase using these links. As an eBay Partner, I earn from qualifying purchases.
DECF4 and Delphi StyleManager
DECF4 and Delphi StyleManager
Setting a style other than the Windows default using TSyleManager.TrySetStyle (I am using Delphi XE2) causes web pages to no longer display in TCEFWindowParent. Does anyone know why this is and what I can do to fix it?
Thanks in advance
Steve
Thanks in advance
Steve
- salvadordf
- Posts: 4084
- Joined: Thu Feb 02, 2017 12:24 pm
- Location: Spain
- Contact:
Re: DECF4 and Delphi StyleManager
Selecting a new VCL style at runtime recreates the control handles. When Chromium detects that the handles are destroyed it thinks that the application is closing and the browser should be destroyed too.
We have 2 workarounds :
We have 2 workarounds :
- Set the style when the app is starting and warn the user that any style change requires an application restart.
- Close all the browsers before the application sets a new style at runtime and open the browsers manually after that if necessary.
Re: DECF4 and Delphi StyleManager
Moving the code to set the style at program start up to a point before the browsers are created seems to fix the biggest problem. I'll keep hacking away at the case where the style is changed while the program is active.
Thanks
Steve
Thanks
Steve
Re: DECF4 and Delphi StyleManager
Now I am trying to solve the problem of the web page not displaying in the CEFWindowParent when the style is changed while the window is active.
Here is what I am doing:
Chromium.CloseAllBrowsers;
TStyleManager.TrySetStyle(newStyle);
Chromium.CreateBrowser(CEFWindowParent);
Chromium.LoadUrl(url);
Sometimes this causes the program to close with no error shown. Sometimes the web page simply doesn't appear in CEFWindowParent.
Tracing through LoadUrl shows Chromium.Initialized to be False, which causes the navigation to be skipped.
Steve
Here is what I am doing:
Chromium.CloseAllBrowsers;
TStyleManager.TrySetStyle(newStyle);
Chromium.CreateBrowser(CEFWindowParent);
Chromium.LoadUrl(url);
Sometimes this causes the program to close with no error shown. Sometimes the web page simply doesn't appear in CEFWindowParent.
Tracing through LoadUrl shows Chromium.Initialized to be False, which causes the navigation to be skipped.
Steve
Re: DECF4 and Delphi StyleManager
Create and recreate the browser yourself, much like TinyBrowser.
Something like this..
+++
CreateСEF;
Creating a browser at startup, when changing the style, the browser must create a new one.
Something like this..
Code: Select all
TStyleManager.AnimationOnControls:= True;
TStyleManager.TrySetStyle(SName, false);
if Assigned(CefWindowParent[0]) then FreeAndNil(CefWindowParent[0]);
if Assigned(ChromeCEF[0]) then FreeAndNil(ChromeCEF[0]);
CreateСEF;
Code: Select all
if Assigned(ChromeCEF[0]) then FreeAndNil(ChromeCEF[0]);
ChromeCEF[0]:= TChromModCEF.Create(nil);
if Assigned(CefWindowParent[0]) then FreeAndNil(CefWindowParent[0]);
CefWindowParent[0]:= TCEFWindowParent.Create(nil);
CefWindowParent[0].Parent:= Form1.PanBR1;
...... ALL PARAM
ChromeCEF[0].Chromium.CreateBrowser(CefWindowParent[0], '', BRContext[0]);
- salvadordf
- Posts: 4084
- Joined: Thu Feb 02, 2017 12:24 pm
- Location: Spain
- Contact:
Re: DECF4 and Delphi StyleManager
The browser destruction is asynchronous. It takes several steps that are described in the code comments of each demo.
This means that it's not possible to close the browsers and immediately create new ones.
Re: DECF4 and Delphi StyleManager
I have tried this several different ways and I still can't make it work.
I added the rather convoluted code required to safely destroy the browser in TChromium.OnClose and TChromium.OnBeforeClose. Like this:
In the case where I am changing the style, FMainFormClosing will be False. This works fine when I close the main form.
When changing the style I do this:
FBrowserCreated is set to True in the TChromium.OnAfterCreated event.
Everything seems to proceed as I would expect until CreateBrowser is called. At this time, the AfterCreated event fires, then the OnBeforeClose event fires. Then when I try to use LoadUrl it fails because BrowserID = 0.
I added the rather convoluted code required to safely destroy the browser in TChromium.OnClose and TChromium.OnBeforeClose. Like this:
Code: Select all
procedure TMenu5Form.browseWindowBeforeClose(Sender: TObject; const browser: ICefBrowser);
begin
// The main browser is being destroyed
if ((browseWindow.BrowserId = 0) and FMainFormClosing) then
begin
FCanClose := True;
PostMessage(Handle, WM_CLOSE, 0, 0);
end;
end;
procedure TMenu5Form.browseWindowClose(Sender: TObject; const browser: ICefBrowser;
var aAction: TCefCloseBrowserAction);
begin
if ((browser <> nil) and
(browseWindow.BrowserId = browser.Identifier) and
(CEFWindowParent <> nil)) then
begin
PostMessage(Handle, CEF_DESTROY, 0, 0);
aAction := cbaDelay;
end;
end;
procedure TMenu5Form.BrowserDestroyMsg(var aMessage: TMessage);
// Fire when a browser is being destroyed. Freeing CEFParentWindow here causes
// the browser.OnBeforeClose event to fire, which allows the program to finish
// closing.
begin
FreeAndNil(CEFWindowParent);
end;
When changing the style I do this:
Code: Select all
// Destroy the browser and wait for all events to be processed.
browseWindow.CloseAllBrowsers;
while (browseWindow.BrowserId <> 0) do
begin
Sleep(10);
Application.ProcessMessages;
end;
// Set the new style
TStyleManager.TrySetStyle(Menu5Data.UserInfo.U_STYLE);
fcurrentStyle := Menu5Data.UserInfo.U_STYLE;
// Create a new browser
CEFWindowParent := TCEFWindowParent.Create(Self);
with CEFWindowParent do
begin
Parent := pnlBrowse;
Align := alClient;
end;
FBrowserCreated := False;
if (not browseWindow.CreateBrowser(CEFWindowParent)) then
ShowMessage('OOPS!');
while (not FBrowserCreated) do
begin
Sleep(10);
Application.ProcessMessages;
end;
//
browseWindow.LoadUrl(url);
Everything seems to proceed as I would expect until CreateBrowser is called. At this time, the AfterCreated event fires, then the OnBeforeClose event fires. Then when I try to use LoadUrl it fails because BrowserID = 0.
Re: DECF4 and Delphi StyleManager
I think I finally have it working. I had to put Application.ProcessMessages after TrySetStyle.