1
0
mirror of https://github.com/salvadordf/CEF4Delphi.git synced 2025-04-17 06:57:13 +02:00

Fixed an issue copying the bitmap in uCEFBrowserThread

Added more checks to uCEFBrowserThread
This commit is contained in:
Salvador Diaz Fau 2020-12-14 13:27:19 +01:00
parent 1299a6f596
commit 8f88a31440
14 changed files with 1325 additions and 904 deletions

View File

@ -53,6 +53,16 @@ begin
GlobalCEFApp.EnableHighDPISupport := True; GlobalCEFApp.EnableHighDPISupport := True;
GlobalCEFApp.ShowMessageDlg := False; GlobalCEFApp.ShowMessageDlg := False;
GlobalCEFApp.BlinkSettings := 'hideScrollbars'; GlobalCEFApp.BlinkSettings := 'hideScrollbars';
{
// In case you use a custom directory for the CEF binaries you have to set these properties
// here and in the main process
GlobalCEFApp.FrameworkDirPath := 'c:\cef';
GlobalCEFApp.ResourcesDirPath := 'c:\cef';
GlobalCEFApp.LocalesDirPath := 'c:\cef\locales';
GlobalCEFApp.SetCurrentDir := True;
}
GlobalCEFApp.StartSubProcess; GlobalCEFApp.StartSubProcess;
DestroyGlobalCEFApp; DestroyGlobalCEFApp;
end. end.

View File

@ -84,16 +84,19 @@ type
FErrorText : ustring; FErrorText : ustring;
FFailedUrl : ustring; FFailedUrl : ustring;
FPendingUrl : ustring; FPendingUrl : ustring;
FSyncEvents : boolean;
function GetErrorCode : integer; function GetErrorCode : integer;
function GetErrorText : ustring; function GetErrorText : ustring;
function GetFailedUrl : ustring; function GetFailedUrl : ustring;
function GetInitialized : boolean; function GetInitialized : boolean;
procedure SetErrorText(const aValue : ustring);
procedure Panel_OnResize(Sender: TObject); procedure Panel_OnResize(Sender: TObject);
procedure Browser_OnAfterCreated(Sender: TObject; const browser: ICefBrowser); procedure Browser_OnAfterCreated(Sender: TObject; const browser: ICefBrowser);
procedure Browser_OnPaint(Sender: TObject; const browser: ICefBrowser; kind: TCefPaintElementType; dirtyRectsCount: NativeUInt; const dirtyRects: PCefRectArray; const buffer: Pointer; width, height: Integer); procedure Browser_OnPaint(Sender: TObject; const browser: ICefBrowser; kind: TCefPaintElementType; dirtyRectsCount: NativeUInt; const dirtyRects: PCefRectArray; const buffer: Pointer; aWidth, aHeight: Integer);
procedure Browser_OnGetViewRect(Sender: TObject; const browser: ICefBrowser; var rect: TCefRect); procedure Browser_OnGetViewRect(Sender: TObject; const browser: ICefBrowser; var rect: TCefRect);
procedure Browser_OnGetScreenPoint(Sender: TObject; const browser: ICefBrowser; viewX, viewY: Integer; var screenX, screenY: Integer; out Result: Boolean); procedure Browser_OnGetScreenPoint(Sender: TObject; const browser: ICefBrowser; viewX, viewY: Integer; var screenX, screenY: Integer; out Result: Boolean);
procedure Browser_OnGetScreenInfo(Sender: TObject; const browser: ICefBrowser; var screenInfo: TCefScreenInfo; out Result: Boolean); procedure Browser_OnGetScreenInfo(Sender: TObject; const browser: ICefBrowser; var screenInfo: TCefScreenInfo; out Result: Boolean);
@ -104,13 +107,15 @@ type
procedure Browser_OnLoadError(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; errorCode: Integer; const errorText, failedUrl: ustring); procedure Browser_OnLoadError(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; errorCode: Integer; const errorText, failedUrl: ustring);
procedure Browser_OnLoadingStateChange(Sender: TObject; const browser: ICefBrowser; isLoading, canGoBack, canGoForward: Boolean); procedure Browser_OnLoadingStateChange(Sender: TObject; const browser: ICefBrowser; isLoading, canGoBack, canGoForward: Boolean);
procedure DoOnError;
procedure DoOnSnapshotAvailable;
procedure Resize; procedure Resize;
function CreateBrowser : boolean; function CreateBrowser : boolean;
procedure TakeSnapshot; function TakeSnapshot : boolean;
procedure CloseBrowser; procedure CloseBrowser;
procedure DoOnError;
procedure InitError; procedure InitError;
procedure WebpagePostProcessing; procedure WebpagePostProcessing;
procedure WebpageError;
procedure LoadPendingURL; procedure LoadPendingURL;
procedure Execute; override; procedure Execute; override;
@ -124,9 +129,11 @@ type
procedure LoadUrl(const aURL : ustring); procedure LoadUrl(const aURL : ustring);
property ErrorCode : integer read GetErrorCode; property ErrorCode : integer read GetErrorCode;
property ErrorText : ustring read GetErrorText; property ErrorText : ustring read GetErrorText write SetErrorText;
property FailedUrl : ustring read GetFailedUrl; property FailedUrl : ustring read GetFailedUrl;
property Initialized : boolean read GetInitialized; property Initialized : boolean read GetInitialized;
property Closing : boolean read FClosing;
property SyncEvents : boolean read FSyncEvents write FSyncEvents;
property OnSnapshotAvailable : TNotifyEvent read FOnSnapshotAvailable write FOnSnapshotAvailable; property OnSnapshotAvailable : TNotifyEvent read FOnSnapshotAvailable write FOnSnapshotAvailable;
property OnError : TNotifyEvent read FOnError write FOnError; property OnError : TNotifyEvent read FOnError write FOnError;
@ -178,6 +185,7 @@ begin
FOnSnapshotAvailable := nil; FOnSnapshotAvailable := nil;
FOnError := nil; FOnError := nil;
FClosing := False; FClosing := False;
FSyncEvents := False;
end; end;
destructor TCEFBrowserThread.Destroy; destructor TCEFBrowserThread.Destroy;
@ -234,23 +242,41 @@ end;
function TCEFBrowserThread.GetErrorCode : integer; function TCEFBrowserThread.GetErrorCode : integer;
begin begin
FBrowserInfoCS.Acquire; if assigned(FBrowserInfoCS) then
Result := FErrorCode; try
FBrowserInfoCS.Release; FBrowserInfoCS.Acquire;
Result := FErrorCode;
finally
FBrowserInfoCS.Release;
end
else
Result := 0;
end; end;
function TCEFBrowserThread.GetErrorText : ustring; function TCEFBrowserThread.GetErrorText : ustring;
begin begin
FBrowserInfoCS.Acquire; if assigned(FBrowserInfoCS) then
Result := FErrorText; try
FBrowserInfoCS.Release; FBrowserInfoCS.Acquire;
Result := FErrorText;
finally
FBrowserInfoCS.Release;
end
else
Result := '';
end; end;
function TCEFBrowserThread.GetFailedUrl : ustring; function TCEFBrowserThread.GetFailedUrl : ustring;
begin begin
FBrowserInfoCS.Acquire; if assigned(FBrowserInfoCS) then
Result := FFailedUrl; try
FBrowserInfoCS.Release; FBrowserInfoCS.Acquire;
Result := FFailedUrl;
finally
FBrowserInfoCS.Release;
end
else
Result := '';
end; end;
function TCEFBrowserThread.GetInitialized : boolean; function TCEFBrowserThread.GetInitialized : boolean;
@ -266,69 +292,85 @@ begin
end; end;
end; end;
procedure TCEFBrowserThread.SetErrorText(const aValue : ustring);
begin
if assigned(FBrowserInfoCS) then
try
FBrowserInfoCS.Acquire;
FErrorText := aValue;
finally
FBrowserInfoCS.Release;
end;
end;
function TCEFBrowserThread.CopySnapshot(var aSnapshot : TBitmap) : boolean; function TCEFBrowserThread.CopySnapshot(var aSnapshot : TBitmap) : boolean;
begin begin
Result := False; Result := False;
if FClosing or Terminated or (FBrowserInfoCS = nil) then exit; if FClosing or Terminated or not(Initialized) then exit;
try if assigned(FBrowserInfoCS) then
try try
FBrowserInfoCS.Acquire; try
FBrowserInfoCS.Acquire;
if assigned(FSnapshot) and not(FSnapshot.Empty) then if assigned(FSnapshot) and not(FSnapshot.Empty) then
begin begin
if (aSnapshot = nil) then if (aSnapshot = nil) then
begin begin
aSnapshot := TBitmap.Create; aSnapshot := TBitmap.Create;
aSnapshot.PixelFormat := pf32bit; aSnapshot.PixelFormat := pf32bit;
aSnapshot.HandleType := bmDIB; aSnapshot.HandleType := bmDIB;
aSnapshot.Width := FSnapshot.Width; end;
aSnapshot.Height := FSnapshot.Height;
end;
aSnapshot.Assign(FSnapshot); if (aSnapshot.Width <> FSnapshot.Width) then
Result := True; aSnapshot.Width := FSnapshot.Width;
end;
except if (aSnapshot.Height <> FSnapshot.Height) then
on e : exception do aSnapshot.Height := FSnapshot.Height;
if CustomExceptionHandler('TCEFBrowserThread.CopySnapshot', e) then raise;
aSnapshot.Canvas.Draw(0, 0, FSnapshot);
Result := True;
end;
except
on e : exception do
if CustomExceptionHandler('TCEFBrowserThread.CopySnapshot', e) then raise;
end;
finally
FBrowserInfoCS.Release;
end; end;
finally
FBrowserInfoCS.Release;
end;
end; end;
function TCEFBrowserThread.SaveSnapshotToFile(const aPath : ustring) : boolean; function TCEFBrowserThread.SaveSnapshotToFile(const aPath : ustring) : boolean;
begin begin
Result := False; Result := False;
if (FBrowserInfoCS = nil) then exit; if FClosing or Terminated or not(Initialized) then exit;
try if assigned(FBrowserInfoCS) and (length(aPath) > 0) then
try try
FBrowserInfoCS.Acquire; try
FBrowserInfoCS.Acquire;
if assigned(FSnapshot) and not(FSnapshot.Empty) then if assigned(FSnapshot) and not(FSnapshot.Empty) then
begin begin
FSnapshot.SaveToFile(aPath); FSnapshot.SaveToFile(aPath);
Result := True; Result := True;
end; end;
except except
on e : exception do on e : exception do
if CustomExceptionHandler('TCEFBrowserThread.SaveSnapshotToFile', e) then raise; if CustomExceptionHandler('TCEFBrowserThread.SaveSnapshotToFile', e) then raise;
end;
finally
FBrowserInfoCS.Release;
end; end;
finally
FBrowserInfoCS.Release;
end;
end; end;
procedure TCEFBrowserThread.LoadUrl(const aURL : ustring); procedure TCEFBrowserThread.LoadUrl(const aURL : ustring);
begin begin
if FClosing or Terminated or (FBrowserInfoCS = nil) then if FClosing or Terminated or not(Initialized) then exit;
exit;
if Initialized then if assigned(FBrowserInfoCS) then
try try
FBrowserInfoCS.Acquire; FBrowserInfoCS.Acquire;
FPendingUrl := aURL; FPendingUrl := aURL;
@ -351,12 +393,16 @@ end;
procedure TCEFBrowserThread.Browser_OnAfterCreated(Sender: TObject; const browser: ICefBrowser); procedure TCEFBrowserThread.Browser_OnAfterCreated(Sender: TObject; const browser: ICefBrowser);
begin begin
FBrowserInfoCS.Acquire; if assigned(FBrowserInfoCS) then
FInitialized := True; try
FBrowserInfoCS.Release; FBrowserInfoCS.Acquire;
FInitialized := True;
finally
FBrowserInfoCS.Release;
end;
end; end;
procedure TCEFBrowserThread.Browser_OnPaint(Sender: TObject; const browser: ICefBrowser; kind: TCefPaintElementType; dirtyRectsCount: NativeUInt; const dirtyRects: PCefRectArray; const buffer: Pointer; width, height: Integer); procedure TCEFBrowserThread.Browser_OnPaint(Sender: TObject; const browser: ICefBrowser; kind: TCefPaintElementType; dirtyRectsCount: NativeUInt; const dirtyRects: PCefRectArray; const buffer: Pointer; aWidth, aHeight: Integer);
var var
src, dst: PByte; src, dst: PByte;
i, j, TempLineSize, TempSrcOffset, TempDstOffset, SrcStride, DstStride : Integer; i, j, TempLineSize, TempSrcOffset, TempDstOffset, SrcStride, DstStride : Integer;
@ -366,112 +412,116 @@ var
TempForcedResize : boolean; TempForcedResize : boolean;
TempSrcRect : TRect; TempSrcRect : TRect;
begin begin
try if assigned(FResizeCS) and assigned(FPanel) then
FResizeCS.Acquire; try
TempForcedResize := False; FResizeCS.Acquire;
TempForcedResize := False;
if FPanel.BeginBufferDraw then if FPanel.BeginBufferDraw then
begin begin
if (kind = PET_POPUP) then if (kind = PET_POPUP) then
begin begin
if (FPopUpBitmap = nil) or if (FPopUpBitmap = nil) or
(width <> FPopUpBitmap.Width) or (aWidth <> FPopUpBitmap.Width) or
(height <> FPopUpBitmap.Height) then (aHeight <> FPopUpBitmap.Height) then
begin begin
if (FPopUpBitmap <> nil) then FPopUpBitmap.Free; if (FPopUpBitmap <> nil) then FPopUpBitmap.Free;
FPopUpBitmap := TBitmap.Create; FPopUpBitmap := TBitmap.Create;
FPopUpBitmap.PixelFormat := pf32bit; FPopUpBitmap.PixelFormat := pf32bit;
FPopUpBitmap.HandleType := bmDIB; FPopUpBitmap.HandleType := bmDIB;
FPopUpBitmap.Width := width; FPopUpBitmap.Width := aWidth;
FPopUpBitmap.Height := height; FPopUpBitmap.Height := aHeight;
end; end;
TempWidth := FPopUpBitmap.Width; TempWidth := FPopUpBitmap.Width;
TempHeight := FPopUpBitmap.Height; TempHeight := FPopUpBitmap.Height;
TempScanlineSize := FPopUpBitmap.Width * SizeOf(TRGBQuad); TempScanlineSize := FPopUpBitmap.Width * SizeOf(TRGBQuad);
TempBufferBits := FPopUpBitmap.Scanline[pred(FPopUpBitmap.Height)]; TempBufferBits := FPopUpBitmap.Scanline[pred(FPopUpBitmap.Height)];
end end
else else
begin begin
TempForcedResize := FPanel.UpdateBufferDimensions(Width, Height) or not(FPanel.BufferIsResized(False)); TempForcedResize := FPanel.UpdateBufferDimensions(aWidth, aHeight) or not(FPanel.BufferIsResized(False));
TempWidth := FPanel.BufferWidth; TempWidth := FPanel.BufferWidth;
TempHeight := FPanel.BufferHeight; TempHeight := FPanel.BufferHeight;
TempScanlineSize := FPanel.ScanlineSize; TempScanlineSize := FPanel.ScanlineSize;
TempBufferBits := FPanel.BufferBits; TempBufferBits := FPanel.BufferBits;
end; end;
if (TempBufferBits <> nil) then if (TempBufferBits <> nil) then
begin begin
SrcStride := Width * SizeOf(TRGBQuad); SrcStride := aWidth * SizeOf(TRGBQuad);
DstStride := - TempScanlineSize; DstStride := - TempScanlineSize;
n := 0; n := 0;
while (n < dirtyRectsCount) do while (n < dirtyRectsCount) do
begin begin
if (dirtyRects[n].x >= 0) and (dirtyRects[n].y >= 0) then if (dirtyRects[n].x >= 0) and (dirtyRects[n].y >= 0) then
begin begin
TempLineSize := min(dirtyRects[n].width, TempWidth - dirtyRects[n].x) * SizeOf(TRGBQuad); TempLineSize := min(dirtyRects[n].width, TempWidth - dirtyRects[n].x) * SizeOf(TRGBQuad);
if (TempLineSize > 0) then if (TempLineSize > 0) then
begin begin
TempSrcOffset := ((dirtyRects[n].y * Width) + dirtyRects[n].x) * SizeOf(TRGBQuad); TempSrcOffset := ((dirtyRects[n].y * aWidth) + dirtyRects[n].x) * SizeOf(TRGBQuad);
TempDstOffset := ((TempScanlineSize * pred(TempHeight)) - (dirtyRects[n].y * TempScanlineSize)) + TempDstOffset := ((TempScanlineSize * pred(TempHeight)) - (dirtyRects[n].y * TempScanlineSize)) +
(dirtyRects[n].x * SizeOf(TRGBQuad)); (dirtyRects[n].x * SizeOf(TRGBQuad));
src := @PByte(buffer)[TempSrcOffset]; src := @PByte(buffer)[TempSrcOffset];
dst := @PByte(TempBufferBits)[TempDstOffset]; dst := @PByte(TempBufferBits)[TempDstOffset];
i := 0; i := 0;
j := min(dirtyRects[n].height, TempHeight - dirtyRects[n].y); j := min(dirtyRects[n].height, TempHeight - dirtyRects[n].y);
while (i < j) do while (i < j) do
begin begin
Move(src^, dst^, TempLineSize); Move(src^, dst^, TempLineSize);
Inc(dst, DstStride); Inc(dst, DstStride);
Inc(src, SrcStride); Inc(src, SrcStride);
inc(i); inc(i);
end; end;
end; end;
end; end;
inc(n); inc(n);
end; end;
if FShowPopup and (FPopUpBitmap <> nil) then if FShowPopup and (FPopUpBitmap <> nil) then
begin begin
TempSrcRect := Rect(0, 0, TempSrcRect := Rect(0, 0,
min(FPopUpRect.Right - FPopUpRect.Left, FPopUpBitmap.Width), min(FPopUpRect.Right - FPopUpRect.Left, FPopUpBitmap.Width),
min(FPopUpRect.Bottom - FPopUpRect.Top, FPopUpBitmap.Height)); min(FPopUpRect.Bottom - FPopUpRect.Top, FPopUpBitmap.Height));
FPanel.BufferDraw(FPopUpBitmap, TempSrcRect, FPopUpRect); FPanel.BufferDraw(FPopUpBitmap, TempSrcRect, FPopUpRect);
end; end;
end; end;
FPanel.EndBufferDraw; FPanel.EndBufferDraw;
if (kind = PET_VIEW) then if (kind = PET_VIEW) then
begin begin
if TempForcedResize or FPendingResize then if TempForcedResize or FPendingResize then
PostThreadMessage(ThreadID, CEF_PENDINGRESIZE, 0, 0); PostThreadMessage(ThreadID, CEF_PENDINGRESIZE, 0, 0);
FResizing := False; FResizing := False;
FPendingResize := False; FPendingResize := False;
end; end;
end; end;
finally finally
FResizeCS.Release; FResizeCS.Release;
end; end;
end; end;
procedure TCEFBrowserThread.Browser_OnGetViewRect(Sender: TObject; const browser: ICefBrowser; var rect: TCefRect); procedure TCEFBrowserThread.Browser_OnGetViewRect(Sender: TObject; const browser: ICefBrowser; var rect: TCefRect);
begin begin
rect.x := 0; if assigned(FPanel) then
rect.y := 0; begin
rect.width := DeviceToLogical(FPanel.Width, FScreenScale); rect.x := 0;
rect.height := DeviceToLogical(FPanel.Height, FScreenScale); rect.y := 0;
rect.width := DeviceToLogical(FPanel.Width, FScreenScale);
rect.height := DeviceToLogical(FPanel.Height, FScreenScale);
end;
end; end;
procedure TCEFBrowserThread.Browser_OnGetScreenPoint(Sender: TObject; const browser: ICefBrowser; viewX, viewY: Integer; var screenX, screenY: Integer; out Result: Boolean); procedure TCEFBrowserThread.Browser_OnGetScreenPoint(Sender: TObject; const browser: ICefBrowser; viewX, viewY: Integer; var screenX, screenY: Integer; out Result: Boolean);
@ -485,19 +535,22 @@ procedure TCEFBrowserThread.Browser_OnGetScreenInfo(Sender: TObject; const brows
var var
TempRect : TCEFRect; TempRect : TCEFRect;
begin begin
TempRect.x := 0; if assigned(FPanel) then
TempRect.y := 0; begin
TempRect.width := DeviceToLogical(FPanel.Width, FScreenScale); TempRect.x := 0;
TempRect.height := DeviceToLogical(FPanel.Height, FScreenScale); TempRect.y := 0;
TempRect.width := DeviceToLogical(FPanel.Width, FScreenScale);
TempRect.height := DeviceToLogical(FPanel.Height, FScreenScale);
screenInfo.device_scale_factor := FScreenScale; screenInfo.device_scale_factor := FScreenScale;
screenInfo.depth := 0; screenInfo.depth := 0;
screenInfo.depth_per_component := 0; screenInfo.depth_per_component := 0;
screenInfo.is_monochrome := Ord(False); screenInfo.is_monochrome := Ord(False);
screenInfo.rect := TempRect; screenInfo.rect := TempRect;
screenInfo.available_rect := TempRect; screenInfo.available_rect := TempRect;
Result := True; Result := True;
end;
end; end;
procedure TCEFBrowserThread.Browser_OnPopupShow(Sender: TObject; const browser: ICefBrowser; show: Boolean); procedure TCEFBrowserThread.Browser_OnPopupShow(Sender: TObject; const browser: ICefBrowser; show: Boolean);
@ -536,7 +589,7 @@ end;
procedure TCEFBrowserThread.Browser_OnLoadError(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; errorCode: Integer; const errorText, failedUrl: ustring); procedure TCEFBrowserThread.Browser_OnLoadError(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; errorCode: Integer; const errorText, failedUrl: ustring);
begin begin
if not(FClosing) and not(Terminated) and (frame <> nil) and frame.IsValid and frame.IsMain then if not(FClosing) and not(Terminated) and (frame <> nil) and frame.IsValid and frame.IsMain and assigned(FBrowserInfoCS) then
try try
FBrowserInfoCS.Acquire; FBrowserInfoCS.Acquire;
@ -558,25 +611,25 @@ end;
procedure TCEFBrowserThread.Resize; procedure TCEFBrowserThread.Resize;
begin begin
if FClosing or Terminated or (FPanel = nil) or (FResizeCS = nil) or (FBrowser = nil) then if FClosing or Terminated or not(Initialized) then exit;
exit;
try if assigned(FResizeCS) and assigned(FPanel) then
FResizeCS.Acquire; try
FResizeCS.Acquire;
if FResizing then if FResizing then
FPendingResize := True FPendingResize := True
else
if FPanel.BufferIsResized then
FBrowser.Invalidate(PET_VIEW)
else else
begin if FPanel.BufferIsResized then
FResizing := True; FBrowser.Invalidate(PET_VIEW)
FBrowser.WasResized; else
end; begin
finally FResizing := True;
FResizeCS.Release; FBrowser.WasResized;
end; end;
finally
FResizeCS.Release;
end;
end; end;
function TCEFBrowserThread.CreateBrowser : boolean; function TCEFBrowserThread.CreateBrowser : boolean;
@ -586,20 +639,20 @@ end;
procedure TCEFBrowserThread.LoadPendingURL; procedure TCEFBrowserThread.LoadPendingURL;
begin begin
if FClosing or Terminated or (FBrowser = nil) or (FBrowserInfoCS = nil) then if FClosing or Terminated or not(Initialized) then exit;
exit;
try if assigned(FBrowserInfoCS) then
FBrowserInfoCS.Acquire; try
FBrowserInfoCS.Acquire;
if (length(FPendingURL) > 0) then if (length(FPendingURL) > 0) then
begin begin
FBrowser.LoadURL(FPendingURL); FBrowser.LoadURL(FPendingURL);
FPendingURL := ''; FPendingURL := '';
end; end;
finally finally
FBrowserInfoCS.Release; FBrowserInfoCS.Release;
end; end;
end; end;
procedure TCEFBrowserThread.WebpagePostProcessing; procedure TCEFBrowserThread.WebpagePostProcessing;
@ -610,32 +663,58 @@ begin
if (FDelayMs > 0) then if (FDelayMs > 0) then
sleep(FDelayMs); sleep(FDelayMs);
TakeSnapshot; if TakeSnapshot and assigned(FOnSnapshotAvailable) then
begin
if assigned(FOnSnapshotAvailable) then FOnSnapshotAvailable(self); if FSyncEvents then
Synchronize(DoOnSnapshotAvailable)
else
DoOnSnapshotAvailable;
end;
end; end;
procedure TCEFBrowserThread.TakeSnapshot; procedure TCEFBrowserThread.WebpageError;
begin begin
if (FPanel = nil) or (FPanel.Buffer = nil) or (FBrowserInfoCS = nil) then if not(FClosing) and not(Terminated) and assigned(FOnError) then
exit; begin
if FSyncEvents then
Synchronize(DoOnError)
else
DoOnError;
end;
end;
try function TCEFBrowserThread.TakeSnapshot : boolean;
FBrowserInfoCS.Acquire; begin
Result := False;
if (FSnapshot = nil) then if FClosing or Terminated or not(Initialized) then exit;
begin
FSnapshot := TBitmap.Create;
FSnapshot.PixelFormat := pf32bit;
FSnapshot.HandleType := bmDIB;
FSnapshot.Width := FPanel.BufferWidth;
FSnapshot.Height := FPanel.BufferHeight;
end;
FSnapshot.Assign(FPanel.Buffer); if assigned(FBrowserInfoCS) and assigned(FPanel) and FPanel.BeginBufferDraw then
finally try
FBrowserInfoCS.Release; FBrowserInfoCS.Acquire;
end;
if assigned(FPanel.Buffer) and not(FPanel.Buffer.Empty) then
begin
if (FSnapshot = nil) then
begin
FSnapshot := TBitmap.Create;
FSnapshot.PixelFormat := pf32bit;
FSnapshot.HandleType := bmDIB;
end;
if (FSnapshot.Width <> FPanel.BufferWidth) then
FSnapshot.Width := FPanel.BufferWidth;
if (FSnapshot.Height <> FPanel.BufferHeight) then
FSnapshot.Height := FPanel.BufferHeight;
FSnapshot.Canvas.Draw(0, 0, FPanel.Buffer);
Result := True;
end;
finally
FBrowserInfoCS.Release;
FPanel.EndBufferDraw;
end;
end; end;
procedure TCEFBrowserThread.CloseBrowser; procedure TCEFBrowserThread.CloseBrowser;
@ -649,16 +728,22 @@ end;
procedure TCEFBrowserThread.DoOnError; procedure TCEFBrowserThread.DoOnError;
begin begin
if assigned(FOnError) then FOnError(self);
FOnError(self); end;
procedure TCEFBrowserThread.DoOnSnapshotAvailable;
begin
FOnSnapshotAvailable(self);
end; end;
procedure TCEFBrowserThread.InitError; procedure TCEFBrowserThread.InitError;
begin begin
FBrowserInfoCS.Acquire; ErrorText := 'There was an error initializing the CEF browser.';
FErrorText := 'There was an error initializing the CEF browser.';
FBrowserInfoCS.Release; if FSyncEvents then
DoOnError; Synchronize(DoOnError)
else
DoOnError;
end; end;
procedure TCEFBrowserThread.Execute; procedure TCEFBrowserThread.Execute;
@ -678,7 +763,7 @@ begin
CEF_CLOSE_BROWSER_MSG : CloseBrowser; CEF_CLOSE_BROWSER_MSG : CloseBrowser;
CEF_LOAD_PENDING_URL_MSG : LoadPendingURL; CEF_LOAD_PENDING_URL_MSG : LoadPendingURL;
CEF_WEBPAGE_LOADED_MSG : WebpagePostProcessing; CEF_WEBPAGE_LOADED_MSG : WebpagePostProcessing;
CEF_WEBPAGE_ERROR_MSG : DoOnError; CEF_WEBPAGE_ERROR_MSG : WebpageError;
WM_QUIT : TempCont := False; WM_QUIT : TempCont := False;
end; end;

View File

@ -150,6 +150,16 @@ begin
GlobalCEFApp.BrowserSubprocessPath := 'ConsoleBrowser2_sp.exe'; // This is the other EXE for the CEF subprocesses. It's on the same directory as this app. GlobalCEFApp.BrowserSubprocessPath := 'ConsoleBrowser2_sp.exe'; // This is the other EXE for the CEF subprocesses. It's on the same directory as this app.
GlobalCEFApp.BlinkSettings := 'hideScrollbars'; // This setting removes all scrollbars to capture a cleaner snapshot GlobalCEFApp.BlinkSettings := 'hideScrollbars'; // This setting removes all scrollbars to capture a cleaner snapshot
GlobalCEFApp.OnContextInitialized := GlobalCEFApp_OnContextInitialized; GlobalCEFApp.OnContextInitialized := GlobalCEFApp_OnContextInitialized;
{
// In case you use a custom directory for the CEF binaries you have to set these properties
// here and in the subprocess
GlobalCEFApp.FrameworkDirPath := 'c:\cef';
GlobalCEFApp.ResourcesDirPath := 'c:\cef';
GlobalCEFApp.LocalesDirPath := 'c:\cef\locales';
GlobalCEFApp.SetCurrentDir := True;
}
GlobalCEFApp.StartMainProcess; GlobalCEFApp.StartMainProcess;
end; end;
@ -206,17 +216,19 @@ begin
if (length(FThread.FailedUrl) > 0) then if (length(FThread.FailedUrl) > 0) then
FErrorText := FErrorText + ' - ' + FThread.FailedUrl; FErrorText := FErrorText + ' - ' + FThread.FailedUrl;
MainAppEvent.SetEvent; if assigned(MainAppEvent) then
MainAppEvent.SetEvent;
end; end;
procedure TEncapsulatedBrowser.Thread_OnSnapshotAvailable(Sender: TObject); procedure TEncapsulatedBrowser.Thread_OnSnapshotAvailable(Sender: TObject);
begin begin
// This code is executed in the TCEFBrowserThread thread context while the main application thread is waiting for MainAppEvent. // This code is executed in the TCEFBrowserThread thread context while the main application thread is waiting for MainAppEvent.
if not(FThread.SaveSnapshotToFile(FSnapshotPath)) then if (FThread = nil) or not(FThread.SaveSnapshotToFile(FSnapshotPath)) then
FErrorText := 'There was an error copying the snapshot'; FErrorText := 'There was an error copying the snapshot';
MainAppEvent.SetEvent; if assigned(MainAppEvent) then
MainAppEvent.SetEvent;
end; end;
initialization initialization

View File

@ -54,7 +54,7 @@ type
protected protected
FCustomScale : single; FCustomScale : single;
function GetScreenScale : single; override; function GetScreenScale : single; override;
public public
property CustomScale : single read FCustomScale write FCustomScale; property CustomScale : single read FCustomScale write FCustomScale;
@ -84,16 +84,19 @@ type
FErrorText : ustring; FErrorText : ustring;
FFailedUrl : ustring; FFailedUrl : ustring;
FPendingUrl : ustring; FPendingUrl : ustring;
FSyncEvents : boolean;
function GetErrorCode : integer; function GetErrorCode : integer;
function GetErrorText : ustring; function GetErrorText : ustring;
function GetFailedUrl : ustring; function GetFailedUrl : ustring;
function GetInitialized : boolean; function GetInitialized : boolean;
procedure SetErrorText(const aValue : ustring);
procedure Panel_OnResize(Sender: TObject); procedure Panel_OnResize(Sender: TObject);
procedure Browser_OnAfterCreated(Sender: TObject; const browser: ICefBrowser); procedure Browser_OnAfterCreated(Sender: TObject; const browser: ICefBrowser);
procedure Browser_OnPaint(Sender: TObject; const browser: ICefBrowser; kind: TCefPaintElementType; dirtyRectsCount: NativeUInt; const dirtyRects: PCefRectArray; const buffer: Pointer; width, height: Integer); procedure Browser_OnPaint(Sender: TObject; const browser: ICefBrowser; kind: TCefPaintElementType; dirtyRectsCount: NativeUInt; const dirtyRects: PCefRectArray; const buffer: Pointer; aWidth, aHeight: Integer);
procedure Browser_OnGetViewRect(Sender: TObject; const browser: ICefBrowser; var rect: TCefRect); procedure Browser_OnGetViewRect(Sender: TObject; const browser: ICefBrowser; var rect: TCefRect);
procedure Browser_OnGetScreenPoint(Sender: TObject; const browser: ICefBrowser; viewX, viewY: Integer; var screenX, screenY: Integer; out Result: Boolean); procedure Browser_OnGetScreenPoint(Sender: TObject; const browser: ICefBrowser; viewX, viewY: Integer; var screenX, screenY: Integer; out Result: Boolean);
procedure Browser_OnGetScreenInfo(Sender: TObject; const browser: ICefBrowser; var screenInfo: TCefScreenInfo; out Result: Boolean); procedure Browser_OnGetScreenInfo(Sender: TObject; const browser: ICefBrowser; var screenInfo: TCefScreenInfo; out Result: Boolean);
@ -108,9 +111,11 @@ type
procedure DoOnSnapshotAvailable; procedure DoOnSnapshotAvailable;
procedure Resize; procedure Resize;
function CreateBrowser : boolean; function CreateBrowser : boolean;
procedure TakeSnapshot; function TakeSnapshot : boolean;
procedure CloseBrowser; procedure CloseBrowser;
procedure InitError;
procedure WebpagePostProcessing; procedure WebpagePostProcessing;
procedure WebpageError;
procedure LoadPendingURL; procedure LoadPendingURL;
procedure Execute; override; procedure Execute; override;
@ -120,12 +125,15 @@ type
procedure AfterConstruction; override; procedure AfterConstruction; override;
function TerminateBrowserThread : boolean; function TerminateBrowserThread : boolean;
function CopySnapshot(var aSnapshot : TBitmap) : boolean; function CopySnapshot(var aSnapshot : TBitmap) : boolean;
function SaveSnapshotToFile(const aPath : ustring) : boolean;
procedure LoadUrl(const aURL : ustring); procedure LoadUrl(const aURL : ustring);
property ErrorCode : integer read GetErrorCode; property ErrorCode : integer read GetErrorCode;
property ErrorText : ustring read GetErrorText; property ErrorText : ustring read GetErrorText write SetErrorText;
property FailedUrl : ustring read GetFailedUrl; property FailedUrl : ustring read GetFailedUrl;
property Initialized : boolean read GetInitialized; property Initialized : boolean read GetInitialized;
property Closing : boolean read FClosing;
property SyncEvents : boolean read FSyncEvents write FSyncEvents;
property OnSnapshotAvailable : TNotifyEvent read FOnSnapshotAvailable write FOnSnapshotAvailable; property OnSnapshotAvailable : TNotifyEvent read FOnSnapshotAvailable write FOnSnapshotAvailable;
property OnError : TNotifyEvent read FOnError write FOnError; property OnError : TNotifyEvent read FOnError write FOnError;
@ -177,6 +185,7 @@ begin
FOnSnapshotAvailable := nil; FOnSnapshotAvailable := nil;
FOnError := nil; FOnError := nil;
FClosing := False; FClosing := False;
FSyncEvents := False;
end; end;
destructor TCEFBrowserThread.Destroy; destructor TCEFBrowserThread.Destroy;
@ -233,23 +242,41 @@ end;
function TCEFBrowserThread.GetErrorCode : integer; function TCEFBrowserThread.GetErrorCode : integer;
begin begin
FBrowserInfoCS.Acquire; if assigned(FBrowserInfoCS) then
Result := FErrorCode; try
FBrowserInfoCS.Release; FBrowserInfoCS.Acquire;
Result := FErrorCode;
finally
FBrowserInfoCS.Release;
end
else
Result := 0;
end; end;
function TCEFBrowserThread.GetErrorText : ustring; function TCEFBrowserThread.GetErrorText : ustring;
begin begin
FBrowserInfoCS.Acquire; if assigned(FBrowserInfoCS) then
Result := FErrorText; try
FBrowserInfoCS.Release; FBrowserInfoCS.Acquire;
Result := FErrorText;
finally
FBrowserInfoCS.Release;
end
else
Result := '';
end; end;
function TCEFBrowserThread.GetFailedUrl : ustring; function TCEFBrowserThread.GetFailedUrl : ustring;
begin begin
FBrowserInfoCS.Acquire; if assigned(FBrowserInfoCS) then
Result := FFailedUrl; try
FBrowserInfoCS.Release; FBrowserInfoCS.Acquire;
Result := FFailedUrl;
finally
FBrowserInfoCS.Release;
end
else
Result := '';
end; end;
function TCEFBrowserThread.GetInitialized : boolean; function TCEFBrowserThread.GetInitialized : boolean;
@ -265,45 +292,85 @@ begin
end; end;
end; end;
procedure TCEFBrowserThread.SetErrorText(const aValue : ustring);
begin
if assigned(FBrowserInfoCS) then
try
FBrowserInfoCS.Acquire;
FErrorText := aValue;
finally
FBrowserInfoCS.Release;
end;
end;
function TCEFBrowserThread.CopySnapshot(var aSnapshot : TBitmap) : boolean; function TCEFBrowserThread.CopySnapshot(var aSnapshot : TBitmap) : boolean;
begin begin
Result := False; Result := False;
if FClosing or Terminated or (FBrowserInfoCS = nil) then exit; if FClosing or Terminated or not(Initialized) then exit;
try if assigned(FBrowserInfoCS) then
try try
FBrowserInfoCS.Acquire; try
FBrowserInfoCS.Acquire;
if assigned(FSnapshot) and not(FSnapshot.Empty) then if assigned(FSnapshot) and not(FSnapshot.Empty) then
begin begin
if (aSnapshot = nil) then if (aSnapshot = nil) then
begin begin
aSnapshot := TBitmap.Create; aSnapshot := TBitmap.Create;
aSnapshot.PixelFormat := pf32bit; aSnapshot.PixelFormat := pf32bit;
aSnapshot.HandleType := bmDIB; aSnapshot.HandleType := bmDIB;
aSnapshot.Width := FSnapshot.Width; end;
aSnapshot.Height := FSnapshot.Height;
end;
aSnapshot.Assign(FSnapshot); if (aSnapshot.Width <> FSnapshot.Width) then
Result := True; aSnapshot.Width := FSnapshot.Width;
end;
except if (aSnapshot.Height <> FSnapshot.Height) then
on e : exception do aSnapshot.Height := FSnapshot.Height;
if CustomExceptionHandler('TCEFBrowserThread.CopySnapshot', e) then raise;
aSnapshot.Canvas.Draw(0, 0, FSnapshot);
Result := True;
end;
except
on e : exception do
if CustomExceptionHandler('TCEFBrowserThread.CopySnapshot', e) then raise;
end;
finally
FBrowserInfoCS.Release;
end;
end;
function TCEFBrowserThread.SaveSnapshotToFile(const aPath : ustring) : boolean;
begin
Result := False;
if FClosing or Terminated or not(Initialized) then exit;
if assigned(FBrowserInfoCS) and (length(aPath) > 0) then
try
try
FBrowserInfoCS.Acquire;
if assigned(FSnapshot) and not(FSnapshot.Empty) then
begin
FSnapshot.SaveToFile(aPath);
Result := True;
end;
except
on e : exception do
if CustomExceptionHandler('TCEFBrowserThread.SaveSnapshotToFile', e) then raise;
end;
finally
FBrowserInfoCS.Release;
end; end;
finally
FBrowserInfoCS.Release;
end;
end; end;
procedure TCEFBrowserThread.LoadUrl(const aURL : ustring); procedure TCEFBrowserThread.LoadUrl(const aURL : ustring);
begin begin
if FClosing or Terminated or (FBrowserInfoCS = nil) then if FClosing or Terminated or not(Initialized) then exit;
exit;
if Initialized then if assigned(FBrowserInfoCS) then
try try
FBrowserInfoCS.Acquire; FBrowserInfoCS.Acquire;
FPendingUrl := aURL; FPendingUrl := aURL;
@ -326,12 +393,16 @@ end;
procedure TCEFBrowserThread.Browser_OnAfterCreated(Sender: TObject; const browser: ICefBrowser); procedure TCEFBrowserThread.Browser_OnAfterCreated(Sender: TObject; const browser: ICefBrowser);
begin begin
FBrowserInfoCS.Acquire; if assigned(FBrowserInfoCS) then
FInitialized := True; try
FBrowserInfoCS.Release; FBrowserInfoCS.Acquire;
FInitialized := True;
finally
FBrowserInfoCS.Release;
end;
end; end;
procedure TCEFBrowserThread.Browser_OnPaint(Sender: TObject; const browser: ICefBrowser; kind: TCefPaintElementType; dirtyRectsCount: NativeUInt; const dirtyRects: PCefRectArray; const buffer: Pointer; width, height: Integer); procedure TCEFBrowserThread.Browser_OnPaint(Sender: TObject; const browser: ICefBrowser; kind: TCefPaintElementType; dirtyRectsCount: NativeUInt; const dirtyRects: PCefRectArray; const buffer: Pointer; aWidth, aHeight: Integer);
var var
src, dst: PByte; src, dst: PByte;
i, j, TempLineSize, TempSrcOffset, TempDstOffset, SrcStride, DstStride : Integer; i, j, TempLineSize, TempSrcOffset, TempDstOffset, SrcStride, DstStride : Integer;
@ -341,112 +412,116 @@ var
TempForcedResize : boolean; TempForcedResize : boolean;
TempSrcRect : TRect; TempSrcRect : TRect;
begin begin
try if assigned(FResizeCS) and assigned(FPanel) then
FResizeCS.Acquire; try
TempForcedResize := False; FResizeCS.Acquire;
TempForcedResize := False;
if FPanel.BeginBufferDraw then if FPanel.BeginBufferDraw then
begin begin
if (kind = PET_POPUP) then if (kind = PET_POPUP) then
begin begin
if (FPopUpBitmap = nil) or if (FPopUpBitmap = nil) or
(width <> FPopUpBitmap.Width) or (aWidth <> FPopUpBitmap.Width) or
(height <> FPopUpBitmap.Height) then (aHeight <> FPopUpBitmap.Height) then
begin begin
if (FPopUpBitmap <> nil) then FPopUpBitmap.Free; if (FPopUpBitmap <> nil) then FPopUpBitmap.Free;
FPopUpBitmap := TBitmap.Create; FPopUpBitmap := TBitmap.Create;
FPopUpBitmap.PixelFormat := pf32bit; FPopUpBitmap.PixelFormat := pf32bit;
FPopUpBitmap.HandleType := bmDIB; FPopUpBitmap.HandleType := bmDIB;
FPopUpBitmap.Width := width; FPopUpBitmap.Width := aWidth;
FPopUpBitmap.Height := height; FPopUpBitmap.Height := aHeight;
end; end;
TempWidth := FPopUpBitmap.Width; TempWidth := FPopUpBitmap.Width;
TempHeight := FPopUpBitmap.Height; TempHeight := FPopUpBitmap.Height;
TempScanlineSize := FPopUpBitmap.Width * SizeOf(TRGBQuad); TempScanlineSize := FPopUpBitmap.Width * SizeOf(TRGBQuad);
TempBufferBits := FPopUpBitmap.Scanline[pred(FPopUpBitmap.Height)]; TempBufferBits := FPopUpBitmap.Scanline[pred(FPopUpBitmap.Height)];
end end
else else
begin begin
TempForcedResize := FPanel.UpdateBufferDimensions(Width, Height) or not(FPanel.BufferIsResized(False)); TempForcedResize := FPanel.UpdateBufferDimensions(aWidth, aHeight) or not(FPanel.BufferIsResized(False));
TempWidth := FPanel.BufferWidth; TempWidth := FPanel.BufferWidth;
TempHeight := FPanel.BufferHeight; TempHeight := FPanel.BufferHeight;
TempScanlineSize := FPanel.ScanlineSize; TempScanlineSize := FPanel.ScanlineSize;
TempBufferBits := FPanel.BufferBits; TempBufferBits := FPanel.BufferBits;
end; end;
if (TempBufferBits <> nil) then if (TempBufferBits <> nil) then
begin begin
SrcStride := Width * SizeOf(TRGBQuad); SrcStride := aWidth * SizeOf(TRGBQuad);
DstStride := - TempScanlineSize; DstStride := - TempScanlineSize;
n := 0; n := 0;
while (n < dirtyRectsCount) do while (n < dirtyRectsCount) do
begin begin
if (dirtyRects[n].x >= 0) and (dirtyRects[n].y >= 0) then if (dirtyRects[n].x >= 0) and (dirtyRects[n].y >= 0) then
begin begin
TempLineSize := min(dirtyRects[n].width, TempWidth - dirtyRects[n].x) * SizeOf(TRGBQuad); TempLineSize := min(dirtyRects[n].width, TempWidth - dirtyRects[n].x) * SizeOf(TRGBQuad);
if (TempLineSize > 0) then if (TempLineSize > 0) then
begin begin
TempSrcOffset := ((dirtyRects[n].y * Width) + dirtyRects[n].x) * SizeOf(TRGBQuad); TempSrcOffset := ((dirtyRects[n].y * aWidth) + dirtyRects[n].x) * SizeOf(TRGBQuad);
TempDstOffset := ((TempScanlineSize * pred(TempHeight)) - (dirtyRects[n].y * TempScanlineSize)) + TempDstOffset := ((TempScanlineSize * pred(TempHeight)) - (dirtyRects[n].y * TempScanlineSize)) +
(dirtyRects[n].x * SizeOf(TRGBQuad)); (dirtyRects[n].x * SizeOf(TRGBQuad));
src := @PByte(buffer)[TempSrcOffset]; src := @PByte(buffer)[TempSrcOffset];
dst := @PByte(TempBufferBits)[TempDstOffset]; dst := @PByte(TempBufferBits)[TempDstOffset];
i := 0; i := 0;
j := min(dirtyRects[n].height, TempHeight - dirtyRects[n].y); j := min(dirtyRects[n].height, TempHeight - dirtyRects[n].y);
while (i < j) do while (i < j) do
begin begin
Move(src^, dst^, TempLineSize); Move(src^, dst^, TempLineSize);
Inc(dst, DstStride); Inc(dst, DstStride);
Inc(src, SrcStride); Inc(src, SrcStride);
inc(i); inc(i);
end; end;
end; end;
end; end;
inc(n); inc(n);
end; end;
if FShowPopup and (FPopUpBitmap <> nil) then if FShowPopup and (FPopUpBitmap <> nil) then
begin begin
TempSrcRect := Rect(0, 0, TempSrcRect := Rect(0, 0,
min(FPopUpRect.Right - FPopUpRect.Left, FPopUpBitmap.Width), min(FPopUpRect.Right - FPopUpRect.Left, FPopUpBitmap.Width),
min(FPopUpRect.Bottom - FPopUpRect.Top, FPopUpBitmap.Height)); min(FPopUpRect.Bottom - FPopUpRect.Top, FPopUpBitmap.Height));
FPanel.BufferDraw(FPopUpBitmap, TempSrcRect, FPopUpRect); FPanel.BufferDraw(FPopUpBitmap, TempSrcRect, FPopUpRect);
end; end;
end; end;
FPanel.EndBufferDraw; FPanel.EndBufferDraw;
FPanel.InvalidatePanel;
if (kind = PET_VIEW) then if (kind = PET_VIEW) then
begin begin
if TempForcedResize or FPendingResize then PostThreadMessage(ThreadID, CEF_PENDINGRESIZE, 0, 0); if TempForcedResize or FPendingResize then
PostThreadMessage(ThreadID, CEF_PENDINGRESIZE, 0, 0);
FResizing := False; FResizing := False;
FPendingResize := False; FPendingResize := False;
end; end;
end; end;
finally finally
FResizeCS.Release; FResizeCS.Release;
end; end;
end; end;
procedure TCEFBrowserThread.Browser_OnGetViewRect(Sender: TObject; const browser: ICefBrowser; var rect: TCefRect); procedure TCEFBrowserThread.Browser_OnGetViewRect(Sender: TObject; const browser: ICefBrowser; var rect: TCefRect);
begin begin
rect.x := 0; if assigned(FPanel) then
rect.y := 0; begin
rect.width := DeviceToLogical(FPanel.Width, FScreenScale); rect.x := 0;
rect.height := DeviceToLogical(FPanel.Height, FScreenScale); rect.y := 0;
rect.width := DeviceToLogical(FPanel.Width, FScreenScale);
rect.height := DeviceToLogical(FPanel.Height, FScreenScale);
end;
end; end;
procedure TCEFBrowserThread.Browser_OnGetScreenPoint(Sender: TObject; const browser: ICefBrowser; viewX, viewY: Integer; var screenX, screenY: Integer; out Result: Boolean); procedure TCEFBrowserThread.Browser_OnGetScreenPoint(Sender: TObject; const browser: ICefBrowser; viewX, viewY: Integer; var screenX, screenY: Integer; out Result: Boolean);
@ -460,19 +535,22 @@ procedure TCEFBrowserThread.Browser_OnGetScreenInfo(Sender: TObject; const brows
var var
TempRect : TCEFRect; TempRect : TCEFRect;
begin begin
TempRect.x := 0; if assigned(FPanel) then
TempRect.y := 0; begin
TempRect.width := DeviceToLogical(FPanel.Width, FScreenScale); TempRect.x := 0;
TempRect.height := DeviceToLogical(FPanel.Height, FScreenScale); TempRect.y := 0;
TempRect.width := DeviceToLogical(FPanel.Width, FScreenScale);
TempRect.height := DeviceToLogical(FPanel.Height, FScreenScale);
screenInfo.device_scale_factor := FScreenScale; screenInfo.device_scale_factor := FScreenScale;
screenInfo.depth := 0; screenInfo.depth := 0;
screenInfo.depth_per_component := 0; screenInfo.depth_per_component := 0;
screenInfo.is_monochrome := Ord(False); screenInfo.is_monochrome := Ord(False);
screenInfo.rect := TempRect; screenInfo.rect := TempRect;
screenInfo.available_rect := TempRect; screenInfo.available_rect := TempRect;
Result := True; Result := True;
end;
end; end;
procedure TCEFBrowserThread.Browser_OnPopupShow(Sender: TObject; const browser: ICefBrowser; show: Boolean); procedure TCEFBrowserThread.Browser_OnPopupShow(Sender: TObject; const browser: ICefBrowser; show: Boolean);
@ -511,7 +589,7 @@ end;
procedure TCEFBrowserThread.Browser_OnLoadError(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; errorCode: Integer; const errorText, failedUrl: ustring); procedure TCEFBrowserThread.Browser_OnLoadError(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; errorCode: Integer; const errorText, failedUrl: ustring);
begin begin
if not(FClosing) and not(Terminated) and (frame <> nil) and frame.IsValid and frame.IsMain then if not(FClosing) and not(Terminated) and (frame <> nil) and frame.IsValid and frame.IsMain and assigned(FBrowserInfoCS) then
try try
FBrowserInfoCS.Acquire; FBrowserInfoCS.Acquire;
@ -531,37 +609,27 @@ begin
PostThreadMessage(ThreadID, CEF_WEBPAGE_LOADED_MSG, 0, 0); PostThreadMessage(ThreadID, CEF_WEBPAGE_LOADED_MSG, 0, 0);
end; end;
procedure TCEFBrowserThread.DoOnError;
begin
FOnError(self);
end;
procedure TCEFBrowserThread.DoOnSnapshotAvailable;
begin
FOnSnapshotAvailable(self);
end;
procedure TCEFBrowserThread.Resize; procedure TCEFBrowserThread.Resize;
begin begin
if FClosing or Terminated or (FPanel = nil) or (FResizeCS = nil) or (FBrowser = nil) then if FClosing or Terminated or not(Initialized) then exit;
exit;
try if assigned(FResizeCS) and assigned(FPanel) then
FResizeCS.Acquire; try
FResizeCS.Acquire;
if FResizing then if FResizing then
FPendingResize := True FPendingResize := True
else
if FPanel.BufferIsResized then
FBrowser.Invalidate(PET_VIEW)
else else
begin if FPanel.BufferIsResized then
FResizing := True; FBrowser.Invalidate(PET_VIEW)
FBrowser.WasResized; else
end; begin
finally FResizing := True;
FResizeCS.Release; FBrowser.WasResized;
end; end;
finally
FResizeCS.Release;
end;
end; end;
function TCEFBrowserThread.CreateBrowser : boolean; function TCEFBrowserThread.CreateBrowser : boolean;
@ -571,20 +639,20 @@ end;
procedure TCEFBrowserThread.LoadPendingURL; procedure TCEFBrowserThread.LoadPendingURL;
begin begin
if FClosing or Terminated or (FBrowser = nil) or (FBrowserInfoCS = nil) then if FClosing or Terminated or not(Initialized) then exit;
exit;
try if assigned(FBrowserInfoCS) then
FBrowserInfoCS.Acquire; try
FBrowserInfoCS.Acquire;
if (length(FPendingURL) > 0) then if (length(FPendingURL) > 0) then
begin begin
FBrowser.LoadURL(FPendingURL); FBrowser.LoadURL(FPendingURL);
FPendingURL := ''; FPendingURL := '';
end; end;
finally finally
FBrowserInfoCS.Release; FBrowserInfoCS.Release;
end; end;
end; end;
procedure TCEFBrowserThread.WebpagePostProcessing; procedure TCEFBrowserThread.WebpagePostProcessing;
@ -595,33 +663,58 @@ begin
if (FDelayMs > 0) then if (FDelayMs > 0) then
sleep(FDelayMs); sleep(FDelayMs);
TakeSnapshot; if TakeSnapshot and assigned(FOnSnapshotAvailable) then
begin
if assigned(FOnSnapshotAvailable) then if FSyncEvents then
Synchronize(DoOnSnapshotAvailable); Synchronize(DoOnSnapshotAvailable)
else
DoOnSnapshotAvailable;
end;
end; end;
procedure TCEFBrowserThread.TakeSnapshot; procedure TCEFBrowserThread.WebpageError;
begin begin
if (FPanel = nil) or (FPanel.Buffer = nil) or (FBrowserInfoCS = nil) then if not(FClosing) and not(Terminated) and assigned(FOnError) then
exit; begin
if FSyncEvents then
Synchronize(DoOnError)
else
DoOnError;
end;
end;
try function TCEFBrowserThread.TakeSnapshot : boolean;
FBrowserInfoCS.Acquire; begin
Result := False;
if (FSnapshot = nil) then if FClosing or Terminated or not(Initialized) then exit;
begin
FSnapshot := TBitmap.Create;
FSnapshot.PixelFormat := pf32bit;
FSnapshot.HandleType := bmDIB;
FSnapshot.Width := FPanel.BufferWidth;
FSnapshot.Height := FPanel.BufferHeight;
end;
FSnapshot.Assign(FPanel.Buffer); if assigned(FBrowserInfoCS) and assigned(FPanel) and FPanel.BeginBufferDraw then
finally try
FBrowserInfoCS.Release; FBrowserInfoCS.Acquire;
end;
if assigned(FPanel.Buffer) and not(FPanel.Buffer.Empty) then
begin
if (FSnapshot = nil) then
begin
FSnapshot := TBitmap.Create;
FSnapshot.PixelFormat := pf32bit;
FSnapshot.HandleType := bmDIB;
end;
if (FSnapshot.Width <> FPanel.BufferWidth) then
FSnapshot.Width := FPanel.BufferWidth;
if (FSnapshot.Height <> FPanel.BufferHeight) then
FSnapshot.Height := FPanel.BufferHeight;
FSnapshot.Canvas.Draw(0, 0, FPanel.Buffer);
Result := True;
end;
finally
FBrowserInfoCS.Release;
FPanel.EndBufferDraw;
end;
end; end;
procedure TCEFBrowserThread.CloseBrowser; procedure TCEFBrowserThread.CloseBrowser;
@ -633,6 +726,26 @@ begin
end; end;
end; end;
procedure TCEFBrowserThread.DoOnError;
begin
FOnError(self);
end;
procedure TCEFBrowserThread.DoOnSnapshotAvailable;
begin
FOnSnapshotAvailable(self);
end;
procedure TCEFBrowserThread.InitError;
begin
ErrorText := 'There was an error initializing the CEF browser.';
if FSyncEvents then
Synchronize(DoOnError)
else
DoOnError;
end;
procedure TCEFBrowserThread.Execute; procedure TCEFBrowserThread.Execute;
var var
TempCont : boolean; TempCont : boolean;
@ -646,17 +759,19 @@ begin
while TempCont and GetMessage(TempMsg, 0, 0, 0) and not(Terminated) do while TempCont and GetMessage(TempMsg, 0, 0, 0) and not(Terminated) do
begin begin
case TempMsg.Message of case TempMsg.Message of
WM_QUIT : TempCont := False;
CEF_PENDINGRESIZE : Resize; CEF_PENDINGRESIZE : Resize;
CEF_CLOSE_BROWSER_MSG : CloseBrowser; CEF_CLOSE_BROWSER_MSG : CloseBrowser;
CEF_LOAD_PENDING_URL_MSG : LoadPendingURL; CEF_LOAD_PENDING_URL_MSG : LoadPendingURL;
CEF_WEBPAGE_LOADED_MSG : WebpagePostProcessing; CEF_WEBPAGE_LOADED_MSG : WebpagePostProcessing;
CEF_WEBPAGE_ERROR_MSG : if assigned(FOnError) then Synchronize(DoOnError); CEF_WEBPAGE_ERROR_MSG : WebpageError;
WM_QUIT : TempCont := False;
end; end;
DispatchMessage(TempMsg); DispatchMessage(TempMsg);
end; end;
end; end
else
InitError;
end; end;
end. end.

View File

@ -115,6 +115,7 @@ begin
FThread := TCEFBrowserThread.Create(AddressEdt.Text, 1024, 768); FThread := TCEFBrowserThread.Create(AddressEdt.Text, 1024, 768);
FThread.OnError := Thread_OnError; FThread.OnError := Thread_OnError;
FThread.OnSnapshotAvailable := Thread_OnSnapshotAvailable; FThread.OnSnapshotAvailable := Thread_OnSnapshotAvailable;
FThread.SyncEvents := True;
FThread.Start; FThread.Start;
end end
else else

View File

@ -8,9 +8,8 @@
<Unit0> <Unit0>
<Filename Value="ConsoleBrowser2.lpr"/> <Filename Value="ConsoleBrowser2.lpr"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
<IsVisibleTab Value="True"/> <TopLine Value="83"/>
<TopLine Value="37"/> <CursorPos X="45" Y="84"/>
<CursorPos X="101" Y="71"/>
<UsageCount Value="20"/> <UsageCount Value="20"/>
<Loaded Value="True"/> <Loaded Value="True"/>
<DefaultSyntaxHighlighter Value="Delphi"/> <DefaultSyntaxHighlighter Value="Delphi"/>
@ -18,10 +17,12 @@
<Unit1> <Unit1>
<Filename Value="uEncapsulatedBrowser.pas"/> <Filename Value="uEncapsulatedBrowser.pas"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
<EditorIndex Value="-1"/> <IsVisibleTab Value="True"/>
<TopLine Value="203"/> <EditorIndex Value="1"/>
<CursorPos X="31" Y="225"/> <TopLine Value="141"/>
<CursorPos X="3" Y="222"/>
<UsageCount Value="20"/> <UsageCount Value="20"/>
<Loaded Value="True"/>
<DefaultSyntaxHighlighter Value="Delphi"/> <DefaultSyntaxHighlighter Value="Delphi"/>
</Unit1> </Unit1>
<Unit2> <Unit2>

View File

@ -10,7 +10,7 @@
// For more information about CEF4Delphi visit : // For more information about CEF4Delphi visit :
// https://www.briskbard.com/index.php?lang=en&pageid=cef // https://www.briskbard.com/index.php?lang=en&pageid=cef
// //
// Copyright © 2020 Salvador Diaz Fau. All rights reserved. // Copyright © 2020 Salvador Diaz Fau. All rights reserved.
// //
// ************************************************************************ // ************************************************************************
// ************ vvvv Original license and comments below vvvv ************* // ************ vvvv Original license and comments below vvvv *************
@ -35,7 +35,7 @@
* *
*) *)
unit uCEFBrowserThread; unit uCEFBrowserThread;
{$MODE Delphi} {$MODE Delphi}
@ -86,12 +86,15 @@ type
FErrorText : ustring; FErrorText : ustring;
FFailedUrl : ustring; FFailedUrl : ustring;
FPendingUrl : ustring; FPendingUrl : ustring;
FSyncEvents : boolean;
function GetErrorCode : integer; function GetErrorCode : integer;
function GetErrorText : ustring; function GetErrorText : ustring;
function GetFailedUrl : ustring; function GetFailedUrl : ustring;
function GetInitialized : boolean; function GetInitialized : boolean;
procedure SetErrorText(const aValue : ustring);
procedure Panel_OnResize(Sender: TObject); procedure Panel_OnResize(Sender: TObject);
procedure Browser_OnAfterCreated(Sender: TObject; const browser: ICefBrowser); procedure Browser_OnAfterCreated(Sender: TObject; const browser: ICefBrowser);
@ -106,13 +109,15 @@ type
procedure Browser_OnLoadError(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; errorCode: Integer; const errorText, failedUrl: ustring); procedure Browser_OnLoadError(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; errorCode: Integer; const errorText, failedUrl: ustring);
procedure Browser_OnLoadingStateChange(Sender: TObject; const browser: ICefBrowser; isLoading, canGoBack, canGoForward: Boolean); procedure Browser_OnLoadingStateChange(Sender: TObject; const browser: ICefBrowser; isLoading, canGoBack, canGoForward: Boolean);
procedure DoOnError;
procedure DoOnSnapshotAvailable;
procedure Resize; procedure Resize;
function CreateBrowser : boolean; function CreateBrowser : boolean;
procedure TakeSnapshot; function TakeSnapshot : boolean;
procedure CloseBrowser; procedure CloseBrowser;
procedure DoOnError;
procedure InitError; procedure InitError;
procedure WebpagePostProcessing; procedure WebpagePostProcessing;
procedure WebpageError;
procedure LoadPendingURL; procedure LoadPendingURL;
procedure Execute; override; procedure Execute; override;
@ -126,9 +131,11 @@ type
procedure LoadUrl(const aURL : ustring); procedure LoadUrl(const aURL : ustring);
property ErrorCode : integer read GetErrorCode; property ErrorCode : integer read GetErrorCode;
property ErrorText : ustring read GetErrorText; property ErrorText : ustring read GetErrorText write SetErrorText;
property FailedUrl : ustring read GetFailedUrl; property FailedUrl : ustring read GetFailedUrl;
property Initialized : boolean read GetInitialized; property Initialized : boolean read GetInitialized;
property Closing : boolean read FClosing;
property SyncEvents : boolean read FSyncEvents write FSyncEvents;
property OnSnapshotAvailable : TNotifyEvent read FOnSnapshotAvailable write FOnSnapshotAvailable; property OnSnapshotAvailable : TNotifyEvent read FOnSnapshotAvailable write FOnSnapshotAvailable;
property OnError : TNotifyEvent read FOnError write FOnError; property OnError : TNotifyEvent read FOnError write FOnError;
@ -180,6 +187,7 @@ begin
FOnSnapshotAvailable := nil; FOnSnapshotAvailable := nil;
FOnError := nil; FOnError := nil;
FClosing := False; FClosing := False;
FSyncEvents := False;
end; end;
destructor TCEFBrowserThread.Destroy; destructor TCEFBrowserThread.Destroy;
@ -236,23 +244,41 @@ end;
function TCEFBrowserThread.GetErrorCode : integer; function TCEFBrowserThread.GetErrorCode : integer;
begin begin
FBrowserInfoCS.Acquire; if assigned(FBrowserInfoCS) then
Result := FErrorCode; try
FBrowserInfoCS.Release; FBrowserInfoCS.Acquire;
Result := FErrorCode;
finally
FBrowserInfoCS.Release;
end
else
Result := 0;
end; end;
function TCEFBrowserThread.GetErrorText : ustring; function TCEFBrowserThread.GetErrorText : ustring;
begin begin
FBrowserInfoCS.Acquire; if assigned(FBrowserInfoCS) then
Result := FErrorText; try
FBrowserInfoCS.Release; FBrowserInfoCS.Acquire;
Result := FErrorText;
finally
FBrowserInfoCS.Release;
end
else
Result := '';
end; end;
function TCEFBrowserThread.GetFailedUrl : ustring; function TCEFBrowserThread.GetFailedUrl : ustring;
begin begin
FBrowserInfoCS.Acquire; if assigned(FBrowserInfoCS) then
Result := FFailedUrl; try
FBrowserInfoCS.Release; FBrowserInfoCS.Acquire;
Result := FFailedUrl;
finally
FBrowserInfoCS.Release;
end
else
Result := '';
end; end;
function TCEFBrowserThread.GetInitialized : boolean; function TCEFBrowserThread.GetInitialized : boolean;
@ -268,69 +294,85 @@ begin
end; end;
end; end;
procedure TCEFBrowserThread.SetErrorText(const aValue : ustring);
begin
if assigned(FBrowserInfoCS) then
try
FBrowserInfoCS.Acquire;
FErrorText := aValue;
finally
FBrowserInfoCS.Release;
end;
end;
function TCEFBrowserThread.CopySnapshot(var aSnapshot : TBitmap) : boolean; function TCEFBrowserThread.CopySnapshot(var aSnapshot : TBitmap) : boolean;
begin begin
Result := False; Result := False;
if FClosing or Terminated or (FBrowserInfoCS = nil) then exit; if FClosing or Terminated or not(Initialized) then exit;
try if assigned(FBrowserInfoCS) then
try try
FBrowserInfoCS.Acquire; try
FBrowserInfoCS.Acquire;
if assigned(FSnapshot) and not(FSnapshot.Empty) then if assigned(FSnapshot) and not(FSnapshot.Empty) then
begin begin
if (aSnapshot = nil) then if (aSnapshot = nil) then
begin begin
aSnapshot := TBitmap.Create; aSnapshot := TBitmap.Create;
aSnapshot.PixelFormat := pf32bit; aSnapshot.PixelFormat := pf32bit;
aSnapshot.HandleType := bmDIB; aSnapshot.HandleType := bmDIB;
aSnapshot.Width := FSnapshot.Width; end;
aSnapshot.Height := FSnapshot.Height;
end;
aSnapshot.Assign(FSnapshot); if (aSnapshot.Width <> FSnapshot.Width) then
Result := True; aSnapshot.Width := FSnapshot.Width;
end;
except if (aSnapshot.Height <> FSnapshot.Height) then
on e : exception do aSnapshot.Height := FSnapshot.Height;
if CustomExceptionHandler('TCEFBrowserThread.CopySnapshot', e) then raise;
aSnapshot.Canvas.Draw(0, 0, FSnapshot);
Result := True;
end;
except
on e : exception do
if CustomExceptionHandler('TCEFBrowserThread.CopySnapshot', e) then raise;
end;
finally
FBrowserInfoCS.Release;
end; end;
finally
FBrowserInfoCS.Release;
end;
end; end;
function TCEFBrowserThread.SaveSnapshotToFile(const aPath : ustring) : boolean; function TCEFBrowserThread.SaveSnapshotToFile(const aPath : ustring) : boolean;
begin begin
Result := False; Result := False;
if (FBrowserInfoCS = nil) then exit; if FClosing or Terminated or not(Initialized) then exit;
try if assigned(FBrowserInfoCS) and (length(aPath) > 0) then
try try
FBrowserInfoCS.Acquire; try
FBrowserInfoCS.Acquire;
if assigned(FSnapshot) and not(FSnapshot.Empty) then if assigned(FSnapshot) and not(FSnapshot.Empty) then
begin begin
FSnapshot.SaveToFile(aPath); FSnapshot.SaveToFile(aPath);
Result := True; Result := True;
end; end;
except except
on e : exception do on e : exception do
if CustomExceptionHandler('TCEFBrowserThread.SaveSnapshotToFile', e) then raise; if CustomExceptionHandler('TCEFBrowserThread.SaveSnapshotToFile', e) then raise;
end;
finally
FBrowserInfoCS.Release;
end; end;
finally
FBrowserInfoCS.Release;
end;
end; end;
procedure TCEFBrowserThread.LoadUrl(const aURL : ustring); procedure TCEFBrowserThread.LoadUrl(const aURL : ustring);
begin begin
if FClosing or Terminated or (FBrowserInfoCS = nil) then if FClosing or Terminated or not(Initialized) then exit;
exit;
if Initialized then if assigned(FBrowserInfoCS) then
try try
FBrowserInfoCS.Acquire; FBrowserInfoCS.Acquire;
FPendingUrl := aURL; FPendingUrl := aURL;
@ -353,9 +395,13 @@ end;
procedure TCEFBrowserThread.Browser_OnAfterCreated(Sender: TObject; const browser: ICefBrowser); procedure TCEFBrowserThread.Browser_OnAfterCreated(Sender: TObject; const browser: ICefBrowser);
begin begin
FBrowserInfoCS.Acquire; if assigned(FBrowserInfoCS) then
FInitialized := True; try
FBrowserInfoCS.Release; FBrowserInfoCS.Acquire;
FInitialized := True;
finally
FBrowserInfoCS.Release;
end;
end; end;
procedure TCEFBrowserThread.Browser_OnPaint(Sender: TObject; const browser: ICefBrowser; kind: TCefPaintElementType; dirtyRectsCount: NativeUInt; const dirtyRects: PCefRectArray; const buffer: Pointer; aWidth, aHeight: Integer); procedure TCEFBrowserThread.Browser_OnPaint(Sender: TObject; const browser: ICefBrowser; kind: TCefPaintElementType; dirtyRectsCount: NativeUInt; const dirtyRects: PCefRectArray; const buffer: Pointer; aWidth, aHeight: Integer);
@ -369,112 +415,116 @@ var
TempBitmap : TBitmap; TempBitmap : TBitmap;
TempSrcRect : TRect; TempSrcRect : TRect;
begin begin
try if assigned(FResizeCS) and assigned(FPanel) then
FResizeCS.Acquire; try
TempForcedResize := False; FResizeCS.Acquire;
TempForcedResize := False;
if FPanel.BeginBufferDraw then if FPanel.BeginBufferDraw then
begin begin
if (kind = PET_POPUP) then if (kind = PET_POPUP) then
begin begin
if (FPopUpBitmap = nil) or if (FPopUpBitmap = nil) or
(aWidth <> FPopUpBitmap.Width) or (aWidth <> FPopUpBitmap.Width) or
(aHeight <> FPopUpBitmap.Height) then (aHeight <> FPopUpBitmap.Height) then
begin begin
if (FPopUpBitmap <> nil) then FPopUpBitmap.Free; if (FPopUpBitmap <> nil) then FPopUpBitmap.Free;
FPopUpBitmap := TBitmap.Create; FPopUpBitmap := TBitmap.Create;
FPopUpBitmap.PixelFormat := pf32bit; FPopUpBitmap.PixelFormat := pf32bit;
FPopUpBitmap.HandleType := bmDIB; FPopUpBitmap.HandleType := bmDIB;
FPopUpBitmap.Width := aWidth; FPopUpBitmap.Width := aWidth;
FPopUpBitmap.Height := aHeight; FPopUpBitmap.Height := aHeight;
end; end;
TempBitmap := FPopUpBitmap; TempBitmap := FPopUpBitmap;
TempBitmap.BeginUpdate; TempBitmap.BeginUpdate;
TempWidth := FPopUpBitmap.Width; TempWidth := FPopUpBitmap.Width;
TempHeight := FPopUpBitmap.Height; TempHeight := FPopUpBitmap.Height;
end end
else else
begin begin
TempForcedResize := FPanel.UpdateBufferDimensions(aWidth, aHeight) or not(FPanel.BufferIsResized(False)); TempForcedResize := FPanel.UpdateBufferDimensions(aWidth, aHeight) or not(FPanel.BufferIsResized(False));
TempBitmap := FPanel.Buffer; TempBitmap := FPanel.Buffer;
TempBitmap.BeginUpdate; TempBitmap.BeginUpdate;
TempWidth := FPanel.BufferWidth; TempWidth := FPanel.BufferWidth;
TempHeight := FPanel.BufferHeight; TempHeight := FPanel.BufferHeight;
end; end;
SrcStride := aWidth * SizeOf(TRGBQuad); SrcStride := aWidth * SizeOf(TRGBQuad);
n := 0; n := 0;
while (n < dirtyRectsCount) do while (n < dirtyRectsCount) do
begin begin
if (dirtyRects^[n].x >= 0) and (dirtyRects^[n].y >= 0) then if (dirtyRects^[n].x >= 0) and (dirtyRects^[n].y >= 0) then
begin begin
TempLineSize := min(dirtyRects^[n].width, TempWidth - dirtyRects^[n].x) * SizeOf(TRGBQuad); TempLineSize := min(dirtyRects^[n].width, TempWidth - dirtyRects^[n].x) * SizeOf(TRGBQuad);
if (TempLineSize > 0) then if (TempLineSize > 0) then
begin begin
TempSrcOffset := ((dirtyRects^[n].y * aWidth) + dirtyRects^[n].x) * SizeOf(TRGBQuad); TempSrcOffset := ((dirtyRects^[n].y * aWidth) + dirtyRects^[n].x) * SizeOf(TRGBQuad);
TempDstOffset := (dirtyRects^[n].x * SizeOf(TRGBQuad)); TempDstOffset := (dirtyRects^[n].x * SizeOf(TRGBQuad));
src := @PByte(buffer)[TempSrcOffset]; src := @PByte(buffer)[TempSrcOffset];
i := 0; i := 0;
j := min(dirtyRects^[n].height, TempHeight - dirtyRects^[n].y); j := min(dirtyRects^[n].height, TempHeight - dirtyRects^[n].y);
while (i < j) do while (i < j) do
begin begin
TempBufferBits := TempBitmap.Scanline[dirtyRects^[n].y + i]; TempBufferBits := TempBitmap.Scanline[dirtyRects^[n].y + i];
dst := @PByte(TempBufferBits)[TempDstOffset]; dst := @PByte(TempBufferBits)[TempDstOffset];
Move(src^, dst^, TempLineSize); Move(src^, dst^, TempLineSize);
Inc(src, SrcStride); Inc(src, SrcStride);
inc(i); inc(i);
end; end;
end; end;
end; end;
inc(n); inc(n);
end; end;
TempBitmap.EndUpdate; TempBitmap.EndUpdate;
if FShowPopup and (FPopUpBitmap <> nil) then if FShowPopup and (FPopUpBitmap <> nil) then
begin begin
TempSrcRect := Rect(0, 0, TempSrcRect := Rect(0, 0,
min(FPopUpRect.Right - FPopUpRect.Left, FPopUpBitmap.Width), min(FPopUpRect.Right - FPopUpRect.Left, FPopUpBitmap.Width),
min(FPopUpRect.Bottom - FPopUpRect.Top, FPopUpBitmap.Height)); min(FPopUpRect.Bottom - FPopUpRect.Top, FPopUpBitmap.Height));
FPanel.BufferDraw(FPopUpBitmap, TempSrcRect, FPopUpRect); FPanel.BufferDraw(FPopUpBitmap, TempSrcRect, FPopUpRect);
end; end;
FPanel.EndBufferDraw; FPanel.EndBufferDraw;
if (kind = PET_VIEW) then if (kind = PET_VIEW) then
begin begin
if TempForcedResize or FPendingResize then if TempForcedResize or FPendingResize then
PostThreadMessage(ThreadID, CEF_PENDINGRESIZE, 0, 0); PostThreadMessage(ThreadID, CEF_PENDINGRESIZE, 0, 0);
FResizing := False; FResizing := False;
FPendingResize := False; FPendingResize := False;
end; end;
end; end;
finally finally
FResizeCS.Release; FResizeCS.Release;
end; end;
end; end;
procedure TCEFBrowserThread.Browser_OnGetViewRect(Sender: TObject; const browser: ICefBrowser; var rect: TCefRect); procedure TCEFBrowserThread.Browser_OnGetViewRect(Sender: TObject; const browser: ICefBrowser; var rect: TCefRect);
begin begin
rect.x := 0; if assigned(FPanel) then
rect.y := 0; begin
rect.width := DeviceToLogical(FPanel.Width, FScreenScale); rect.x := 0;
rect.height := DeviceToLogical(FPanel.Height, FScreenScale); rect.y := 0;
rect.width := DeviceToLogical(FPanel.Width, FScreenScale);
rect.height := DeviceToLogical(FPanel.Height, FScreenScale);
end;
end; end;
procedure TCEFBrowserThread.Browser_OnGetScreenPoint(Sender: TObject; const browser: ICefBrowser; viewX, viewY: Integer; var screenX, screenY: Integer; out Result: Boolean); procedure TCEFBrowserThread.Browser_OnGetScreenPoint(Sender: TObject; const browser: ICefBrowser; viewX, viewY: Integer; var screenX, screenY: Integer; out Result: Boolean);
@ -488,19 +538,22 @@ procedure TCEFBrowserThread.Browser_OnGetScreenInfo(Sender: TObject; const brows
var var
TempRect : TCEFRect; TempRect : TCEFRect;
begin begin
TempRect.x := 0; if assigned(FPanel) then
TempRect.y := 0; begin
TempRect.width := DeviceToLogical(FPanel.Width, FScreenScale); TempRect.x := 0;
TempRect.height := DeviceToLogical(FPanel.Height, FScreenScale); TempRect.y := 0;
TempRect.width := DeviceToLogical(FPanel.Width, FScreenScale);
TempRect.height := DeviceToLogical(FPanel.Height, FScreenScale);
screenInfo.device_scale_factor := FScreenScale; screenInfo.device_scale_factor := FScreenScale;
screenInfo.depth := 0; screenInfo.depth := 0;
screenInfo.depth_per_component := 0; screenInfo.depth_per_component := 0;
screenInfo.is_monochrome := Ord(False); screenInfo.is_monochrome := Ord(False);
screenInfo.rect := TempRect; screenInfo.rect := TempRect;
screenInfo.available_rect := TempRect; screenInfo.available_rect := TempRect;
Result := True; Result := True;
end;
end; end;
procedure TCEFBrowserThread.Browser_OnPopupShow(Sender: TObject; const browser: ICefBrowser; show: Boolean); procedure TCEFBrowserThread.Browser_OnPopupShow(Sender: TObject; const browser: ICefBrowser; show: Boolean);
@ -539,7 +592,7 @@ end;
procedure TCEFBrowserThread.Browser_OnLoadError(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; errorCode: Integer; const errorText, failedUrl: ustring); procedure TCEFBrowserThread.Browser_OnLoadError(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; errorCode: Integer; const errorText, failedUrl: ustring);
begin begin
if not(FClosing) and not(Terminated) and (frame <> nil) and frame.IsValid and frame.IsMain then if not(FClosing) and not(Terminated) and (frame <> nil) and frame.IsValid and frame.IsMain and assigned(FBrowserInfoCS) then
try try
FBrowserInfoCS.Acquire; FBrowserInfoCS.Acquire;
@ -561,25 +614,25 @@ end;
procedure TCEFBrowserThread.Resize; procedure TCEFBrowserThread.Resize;
begin begin
if FClosing or Terminated or (FPanel = nil) or (FResizeCS = nil) or (FBrowser = nil) then if FClosing or Terminated or not(Initialized) then exit;
exit;
try if assigned(FResizeCS) and assigned(FPanel) then
FResizeCS.Acquire; try
FResizeCS.Acquire;
if FResizing then if FResizing then
FPendingResize := True FPendingResize := True
else
if FPanel.BufferIsResized then
FBrowser.Invalidate(PET_VIEW)
else else
begin if FPanel.BufferIsResized then
FResizing := True; FBrowser.Invalidate(PET_VIEW)
FBrowser.WasResized; else
end; begin
finally FResizing := True;
FResizeCS.Release; FBrowser.WasResized;
end; end;
finally
FResizeCS.Release;
end;
end; end;
function TCEFBrowserThread.CreateBrowser : boolean; function TCEFBrowserThread.CreateBrowser : boolean;
@ -589,20 +642,20 @@ end;
procedure TCEFBrowserThread.LoadPendingURL; procedure TCEFBrowserThread.LoadPendingURL;
begin begin
if FClosing or Terminated or (FBrowser = nil) or (FBrowserInfoCS = nil) then if FClosing or Terminated or not(Initialized) then exit;
exit;
try if assigned(FBrowserInfoCS) then
FBrowserInfoCS.Acquire; try
FBrowserInfoCS.Acquire;
if (length(FPendingURL) > 0) then if (length(FPendingURL) > 0) then
begin begin
FBrowser.LoadURL(FPendingURL); FBrowser.LoadURL(FPendingURL);
FPendingURL := ''; FPendingURL := '';
end; end;
finally finally
FBrowserInfoCS.Release; FBrowserInfoCS.Release;
end; end;
end; end;
procedure TCEFBrowserThread.WebpagePostProcessing; procedure TCEFBrowserThread.WebpagePostProcessing;
@ -613,32 +666,58 @@ begin
if (FDelayMs > 0) then if (FDelayMs > 0) then
sleep(FDelayMs); sleep(FDelayMs);
TakeSnapshot; if TakeSnapshot and assigned(FOnSnapshotAvailable) then
begin
if assigned(FOnSnapshotAvailable) then FOnSnapshotAvailable(self); if FSyncEvents then
Synchronize(DoOnSnapshotAvailable)
else
DoOnSnapshotAvailable;
end;
end; end;
procedure TCEFBrowserThread.TakeSnapshot; procedure TCEFBrowserThread.WebpageError;
begin begin
if (FPanel = nil) or (FPanel.Buffer = nil) or (FBrowserInfoCS = nil) then if not(FClosing) and not(Terminated) and assigned(FOnError) then
exit; begin
if FSyncEvents then
Synchronize(DoOnError)
else
DoOnError;
end;
end;
try function TCEFBrowserThread.TakeSnapshot : boolean;
FBrowserInfoCS.Acquire; begin
Result := False;
if (FSnapshot = nil) then if FClosing or Terminated or not(Initialized) then exit;
begin
FSnapshot := TBitmap.Create;
FSnapshot.PixelFormat := pf32bit;
FSnapshot.HandleType := bmDIB;
FSnapshot.Width := FPanel.BufferWidth;
FSnapshot.Height := FPanel.BufferHeight;
end;
FSnapshot.Assign(FPanel.Buffer); if assigned(FBrowserInfoCS) and assigned(FPanel) and FPanel.BeginBufferDraw then
finally try
FBrowserInfoCS.Release; FBrowserInfoCS.Acquire;
end;
if assigned(FPanel.Buffer) and not(FPanel.Buffer.Empty) then
begin
if (FSnapshot = nil) then
begin
FSnapshot := TBitmap.Create;
FSnapshot.PixelFormat := pf32bit;
FSnapshot.HandleType := bmDIB;
end;
if (FSnapshot.Width <> FPanel.BufferWidth) then
FSnapshot.Width := FPanel.BufferWidth;
if (FSnapshot.Height <> FPanel.BufferHeight) then
FSnapshot.Height := FPanel.BufferHeight;
FSnapshot.Canvas.Draw(0, 0, FPanel.Buffer);
Result := True;
end;
finally
FBrowserInfoCS.Release;
FPanel.EndBufferDraw;
end;
end; end;
procedure TCEFBrowserThread.CloseBrowser; procedure TCEFBrowserThread.CloseBrowser;
@ -652,16 +731,22 @@ end;
procedure TCEFBrowserThread.DoOnError; procedure TCEFBrowserThread.DoOnError;
begin begin
if assigned(FOnError) then FOnError(self);
FOnError(self); end;
procedure TCEFBrowserThread.DoOnSnapshotAvailable;
begin
FOnSnapshotAvailable(self);
end; end;
procedure TCEFBrowserThread.InitError; procedure TCEFBrowserThread.InitError;
begin begin
FBrowserInfoCS.Acquire; ErrorText := 'There was an error initializing the CEF browser.';
FErrorText := 'There was an error initializing the CEF browser.';
FBrowserInfoCS.Release; if FSyncEvents then
DoOnError; Synchronize(DoOnError)
else
DoOnError;
end; end;
procedure TCEFBrowserThread.Execute; procedure TCEFBrowserThread.Execute;
@ -681,7 +766,7 @@ begin
CEF_CLOSE_BROWSER_MSG : CloseBrowser; CEF_CLOSE_BROWSER_MSG : CloseBrowser;
CEF_LOAD_PENDING_URL_MSG : LoadPendingURL; CEF_LOAD_PENDING_URL_MSG : LoadPendingURL;
CEF_WEBPAGE_LOADED_MSG : WebpagePostProcessing; CEF_WEBPAGE_LOADED_MSG : WebpagePostProcessing;
CEF_WEBPAGE_ERROR_MSG : DoOnError; CEF_WEBPAGE_ERROR_MSG : WebpageError;
WM_QUIT : TempCont := False; WM_QUIT : TempCont := False;
end; end;

View File

@ -152,6 +152,16 @@ begin
GlobalCEFApp.BrowserSubprocessPath := 'ConsoleBrowser2_sp.exe'; // This is the other EXE for the CEF subprocesses. It's on the same directory as this app. GlobalCEFApp.BrowserSubprocessPath := 'ConsoleBrowser2_sp.exe'; // This is the other EXE for the CEF subprocesses. It's on the same directory as this app.
GlobalCEFApp.BlinkSettings := 'hideScrollbars'; // This setting removes all scrollbars to capture a cleaner snapshot GlobalCEFApp.BlinkSettings := 'hideScrollbars'; // This setting removes all scrollbars to capture a cleaner snapshot
GlobalCEFApp.OnContextInitialized := GlobalCEFApp_OnContextInitialized; GlobalCEFApp.OnContextInitialized := GlobalCEFApp_OnContextInitialized;
{
// In case you use a custom directory for the CEF binaries you have to set these properties
// here and in the subprocess
GlobalCEFApp.FrameworkDirPath := 'c:\cef';
GlobalCEFApp.ResourcesDirPath := 'c:\cef';
GlobalCEFApp.LocalesDirPath := 'c:\cef\locales';
GlobalCEFApp.SetCurrentDir := True;
}
GlobalCEFApp.StartMainProcess; GlobalCEFApp.StartMainProcess;
end; end;
@ -208,17 +218,19 @@ begin
if (length(FThread.FailedUrl) > 0) then if (length(FThread.FailedUrl) > 0) then
FErrorText := FErrorText + ' - ' + FThread.FailedUrl; FErrorText := FErrorText + ' - ' + FThread.FailedUrl;
MainAppEvent.SetEvent; if assigned(MainAppEvent) then
MainAppEvent.SetEvent;
end; end;
procedure TEncapsulatedBrowser.Thread_OnSnapshotAvailable(Sender: TObject); procedure TEncapsulatedBrowser.Thread_OnSnapshotAvailable(Sender: TObject);
begin begin
// This code is executed in the TCEFBrowserThread thread context while the main application thread is waiting for MainAppEvent. // This code is executed in the TCEFBrowserThread thread context while the main application thread is waiting for MainAppEvent.
if not(FThread.SaveSnapshotToFile(FSnapshotPath)) then if (FThread = nil) or not(FThread.SaveSnapshotToFile(FSnapshotPath)) then
FErrorText := 'There was an error copying the snapshot'; FErrorText := 'There was an error copying the snapshot';
MainAppEvent.SetEvent; if assigned(MainAppEvent) then
MainAppEvent.SetEvent;
end; end;
initialization initialization

View File

@ -47,7 +47,9 @@
<Unit2> <Unit2>
<Filename Value="uWebpageSnapshot.pas"/> <Filename Value="uWebpageSnapshot.pas"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
<ComponentName Value="WebpageSnapshotFrm"/>
<HasResources Value="True"/> <HasResources Value="True"/>
<ResourceBaseClass Value="Form"/>
</Unit2> </Unit2>
</Units> </Units>
</ProjectOptions> </ProjectOptions>

View File

@ -4,12 +4,12 @@
<PathDelim Value="\"/> <PathDelim Value="\"/>
<Version Value="11"/> <Version Value="11"/>
<BuildModes Active="Default"/> <BuildModes Active="Default"/>
<Units Count="6"> <Units Count="8">
<Unit0> <Unit0>
<Filename Value="WebpageSnapshot.lpr"/> <Filename Value="WebpageSnapshot.lpr"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
<TopLine Value="45"/> <TopLine Value="45"/>
<CursorPos X="37" Y="58"/> <CursorPos Y="73"/>
<UsageCount Value="23"/> <UsageCount Value="23"/>
<Loaded Value="True"/> <Loaded Value="True"/>
<DefaultSyntaxHighlighter Value="Delphi"/> <DefaultSyntaxHighlighter Value="Delphi"/>
@ -18,9 +18,9 @@
<Filename Value="uCEFBrowserThread.pas"/> <Filename Value="uCEFBrowserThread.pas"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
<IsVisibleTab Value="True"/> <IsVisibleTab Value="True"/>
<EditorIndex Value="1"/> <EditorIndex Value="2"/>
<TopLine Value="637"/> <TopLine Value="471"/>
<CursorPos X="70" Y="657"/> <CursorPos X="66" Y="483"/>
<UsageCount Value="23"/> <UsageCount Value="23"/>
<Loaded Value="True"/> <Loaded Value="True"/>
<DefaultSyntaxHighlighter Value="Delphi"/> <DefaultSyntaxHighlighter Value="Delphi"/>
@ -28,11 +28,14 @@
<Unit2> <Unit2>
<Filename Value="uWebpageSnapshot.pas"/> <Filename Value="uWebpageSnapshot.pas"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
<ComponentName Value="WebpageSnapshotFrm"/>
<HasResources Value="True"/> <HasResources Value="True"/>
<EditorIndex Value="-1"/> <ResourceBaseClass Value="Form"/>
<TopLine Value="139"/> <EditorIndex Value="1"/>
<CursorPos X="74" Y="162"/> <TopLine Value="98"/>
<CursorPos X="71" Y="163"/>
<UsageCount Value="23"/> <UsageCount Value="23"/>
<Loaded Value="True"/>
<DefaultSyntaxHighlighter Value="Delphi"/> <DefaultSyntaxHighlighter Value="Delphi"/>
</Unit2> </Unit2>
<Unit3> <Unit3>
@ -52,112 +55,89 @@
<Unit5> <Unit5>
<Filename Value="..\..\..\source\uCEFBufferPanel.pas"/> <Filename Value="..\..\..\source\uCEFBufferPanel.pas"/>
<EditorIndex Value="-1"/> <EditorIndex Value="-1"/>
<TopLine Value="628"/> <TopLine Value="636"/>
<CursorPos Y="644"/> <CursorPos Y="652"/>
<UsageCount Value="10"/> <UsageCount Value="10"/>
</Unit5> </Unit5>
<Unit6>
<Filename Value="..\ConsoleBrowser2\uCEFBrowserThread.pas"/>
<EditorIndex Value="-1"/>
<TopLine Value="31"/>
<CursorPos X="17" Y="40"/>
<UsageCount Value="10"/>
<DefaultSyntaxHighlighter Value="Delphi"/>
</Unit6>
<Unit7>
<Filename Value="uCEFBrowserThread_v.pas"/>
<UnitName Value="uCEFBrowserThread"/>
<EditorIndex Value="-1"/>
<TopLine Value="321"/>
<CursorPos Y="338"/>
<UsageCount Value="10"/>
<DefaultSyntaxHighlighter Value="Delphi"/>
</Unit7>
</Units> </Units>
<JumpHistory Count="25" HistoryIndex="24"> <JumpHistory Count="15" HistoryIndex="14">
<Position1> <Position1>
<Filename Value="uCEFBrowserThread.pas"/> <Filename Value="uCEFBrowserThread.pas"/>
<Caret Line="381" TopLine="361"/> <Caret Line="348" TopLine="334"/>
</Position1> </Position1>
<Position2> <Position2>
<Filename Value="uCEFBrowserThread.pas"/> <Filename Value="uCEFBrowserThread.pas"/>
<Caret Line="383" TopLine="361"/> <Caret Line="95" Column="17" TopLine="86"/>
</Position2> </Position2>
<Position3> <Position3>
<Filename Value="uCEFBrowserThread.pas"/> <Filename Value="uCEFBrowserThread.pas"/>
<Caret Line="384" TopLine="361"/> <Caret Line="326" TopLine="292"/>
</Position3> </Position3>
<Position4> <Position4>
<Filename Value="uCEFBrowserThread.pas"/> <Filename Value="uCEFBrowserThread.pas"/>
<Caret Line="386" TopLine="363"/> <Caret Line="348" TopLine="334"/>
</Position4> </Position4>
<Position5> <Position5>
<Filename Value="uCEFBrowserThread.pas"/> <Filename Value="uCEFBrowserThread.pas"/>
<Caret Line="388" TopLine="365"/> <Caret Line="349" TopLine="334"/>
</Position5> </Position5>
<Position6> <Position6>
<Filename Value="uCEFBrowserThread.pas"/> <Filename Value="uCEFBrowserThread.pas"/>
<Caret Line="390" TopLine="367"/> <Caret Line="351" TopLine="334"/>
</Position6> </Position6>
<Position7> <Position7>
<Filename Value="uCEFBrowserThread.pas"/> <Filename Value="uCEFBrowserThread.pas"/>
<Caret Line="392" TopLine="369"/> <Caret Line="353" TopLine="334"/>
</Position7> </Position7>
<Position8> <Position8>
<Filename Value="uCEFBrowserThread.pas"/> <Filename Value="uCEFBrowserThread.pas"/>
<Caret Line="394" TopLine="371"/> <Caret Line="376" TopLine="363"/>
</Position8> </Position8>
<Position9> <Position9>
<Filename Value="uCEFBrowserThread.pas"/> <Filename Value="uCEFBrowserThread.pas"/>
<Caret Line="396" TopLine="373"/> <Caret Line="378" TopLine="363"/>
</Position9> </Position9>
<Position10> <Position10>
<Filename Value="uCEFBrowserThread.pas"/> <Filename Value="uCEFBrowserThread.pas"/>
<Caret Line="397" TopLine="374"/> <Caret Line="379" TopLine="363"/>
</Position10> </Position10>
<Position11> <Position11>
<Filename Value="uCEFBrowserThread.pas"/> <Filename Value="uCEFBrowserThread.pas"/>
<Caret Line="398" TopLine="375"/> <Caret Line="381" TopLine="363"/>
</Position11> </Position11>
<Position12> <Position12>
<Filename Value="uCEFBrowserThread.pas"/> <Filename Value="uCEFBrowserThread.pas"/>
<Caret Line="397" TopLine="375"/> <Caret Line="382" TopLine="363"/>
</Position12> </Position12>
<Position13> <Position13>
<Filename Value="uCEFBrowserThread.pas"/> <Filename Value="uCEFBrowserThread.pas"/>
<Caret Line="400" TopLine="377"/> <Caret Line="101" Column="62" TopLine="84"/>
</Position13> </Position13>
<Position14> <Position14>
<Filename Value="uCEFBrowserThread.pas"/> <Filename Value="uCEFBrowserThread.pas"/>
<Caret Line="401" TopLine="378"/> <Caret Line="515" Column="28" TopLine="397"/>
</Position14> </Position14>
<Position15> <Position15>
<Filename Value="uCEFBrowserThread.pas"/> <Filename Value="uCEFBrowserThread.pas"/>
<Caret Line="403" TopLine="380"/> <Caret Line="416" Column="50" TopLine="403"/>
</Position15> </Position15>
<Position16>
<Filename Value="uCEFBrowserThread.pas"/>
<Caret Line="404" TopLine="381"/>
</Position16>
<Position17>
<Filename Value="uCEFBrowserThread.pas"/>
<Caret Line="406" TopLine="383"/>
</Position17>
<Position18>
<Filename Value="uCEFBrowserThread.pas"/>
<Caret Line="595" TopLine="570"/>
</Position18>
<Position19>
<Filename Value="uCEFBrowserThread.pas"/>
<Caret Line="336" Column="203" TopLine="334"/>
</Position19>
<Position20>
<Filename Value="uCEFBrowserThread.pas"/>
<Caret Line="98" Column="191" TopLine="98"/>
</Position20>
<Position21>
<Filename Value="uCEFBrowserThread.pas"/>
<Caret Line="351" Column="65" TopLine="418"/>
</Position21>
<Position22>
<Filename Value="uCEFBrowserThread.pas"/>
<Caret Line="644" TopLine="630"/>
</Position22>
<Position23>
<Filename Value="uCEFBrowserThread.pas"/>
<Caret Line="337" TopLine="333"/>
</Position23>
<Position24>
<Filename Value="uCEFBrowserThread.pas"/>
<Caret Line="651" TopLine="637"/>
</Position24>
<Position25>
<Filename Value="uCEFBrowserThread.pas"/>
<Caret Line="653" TopLine="637"/>
</Position25>
</JumpHistory> </JumpHistory>
<RunParams> <RunParams>
<FormatVersion Value="2"/> <FormatVersion Value="2"/>

View File

@ -10,7 +10,7 @@
// For more information about CEF4Delphi visit : // For more information about CEF4Delphi visit :
// https://www.briskbard.com/index.php?lang=en&pageid=cef // https://www.briskbard.com/index.php?lang=en&pageid=cef
// //
// Copyright © 2020 Salvador Diaz Fau. All rights reserved. // Copyright © 2020 Salvador Diaz Fau. All rights reserved.
// //
// ************************************************************************ // ************************************************************************
// ************ vvvv Original license and comments below vvvv ************* // ************ vvvv Original license and comments below vvvv *************
@ -35,7 +35,7 @@
* *
*) *)
unit uCEFBrowserThread; unit uCEFBrowserThread;
{$MODE Delphi} {$MODE Delphi}
@ -47,7 +47,7 @@ uses
{$IFDEF DELPHI16_UP} {$IFDEF DELPHI16_UP}
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Classes, Vcl.Graphics, System.SyncObjs, System.Math, Winapi.Windows, Winapi.Messages, System.SysUtils, System.Classes, Vcl.Graphics, System.SyncObjs, System.Math,
{$ELSE} {$ELSE}
LCLIntf, LCLType, LMessages, Windows, Messages, SysUtils, Classes, Graphics, SyncObjs, Math, Windows, Messages, SysUtils, Classes, Graphics, SyncObjs, Math,
{$ENDIF} {$ENDIF}
uCEFChromium, uCEFTypes, uCEFInterfaces, uCEFConstants, uCEFBufferPanel, uCEFChromiumCore, uCEFMiscFunctions; uCEFChromium, uCEFTypes, uCEFInterfaces, uCEFConstants, uCEFBufferPanel, uCEFChromiumCore, uCEFMiscFunctions;
@ -56,7 +56,7 @@ type
protected protected
FCustomScale : single; FCustomScale : single;
function GetScreenScale : single; override; function GetScreenScale : single; override;
public public
property CustomScale : single read FCustomScale write FCustomScale; property CustomScale : single read FCustomScale write FCustomScale;
@ -86,12 +86,15 @@ type
FErrorText : ustring; FErrorText : ustring;
FFailedUrl : ustring; FFailedUrl : ustring;
FPendingUrl : ustring; FPendingUrl : ustring;
FSyncEvents : boolean;
function GetErrorCode : integer; function GetErrorCode : integer;
function GetErrorText : ustring; function GetErrorText : ustring;
function GetFailedUrl : ustring; function GetFailedUrl : ustring;
function GetInitialized : boolean; function GetInitialized : boolean;
procedure SetErrorText(const aValue : ustring);
procedure Panel_OnResize(Sender: TObject); procedure Panel_OnResize(Sender: TObject);
procedure Browser_OnAfterCreated(Sender: TObject; const browser: ICefBrowser); procedure Browser_OnAfterCreated(Sender: TObject; const browser: ICefBrowser);
@ -110,9 +113,11 @@ type
procedure DoOnSnapshotAvailable; procedure DoOnSnapshotAvailable;
procedure Resize; procedure Resize;
function CreateBrowser : boolean; function CreateBrowser : boolean;
procedure TakeSnapshot; function TakeSnapshot : boolean;
procedure CloseBrowser; procedure CloseBrowser;
procedure InitError;
procedure WebpagePostProcessing; procedure WebpagePostProcessing;
procedure WebpageError;
procedure LoadPendingURL; procedure LoadPendingURL;
procedure Execute; override; procedure Execute; override;
@ -122,12 +127,15 @@ type
procedure AfterConstruction; override; procedure AfterConstruction; override;
function TerminateBrowserThread : boolean; function TerminateBrowserThread : boolean;
function CopySnapshot(var aSnapshot : TBitmap) : boolean; function CopySnapshot(var aSnapshot : TBitmap) : boolean;
function SaveSnapshotToFile(const aPath : ustring) : boolean;
procedure LoadUrl(const aURL : ustring); procedure LoadUrl(const aURL : ustring);
property ErrorCode : integer read GetErrorCode; property ErrorCode : integer read GetErrorCode;
property ErrorText : ustring read GetErrorText; property ErrorText : ustring read GetErrorText write SetErrorText;
property FailedUrl : ustring read GetFailedUrl; property FailedUrl : ustring read GetFailedUrl;
property Initialized : boolean read GetInitialized; property Initialized : boolean read GetInitialized;
property Closing : boolean read FClosing;
property SyncEvents : boolean read FSyncEvents write FSyncEvents;
property OnSnapshotAvailable : TNotifyEvent read FOnSnapshotAvailable write FOnSnapshotAvailable; property OnSnapshotAvailable : TNotifyEvent read FOnSnapshotAvailable write FOnSnapshotAvailable;
property OnError : TNotifyEvent read FOnError write FOnError; property OnError : TNotifyEvent read FOnError write FOnError;
@ -179,6 +187,7 @@ begin
FOnSnapshotAvailable := nil; FOnSnapshotAvailable := nil;
FOnError := nil; FOnError := nil;
FClosing := False; FClosing := False;
FSyncEvents := False;
end; end;
destructor TCEFBrowserThread.Destroy; destructor TCEFBrowserThread.Destroy;
@ -235,23 +244,41 @@ end;
function TCEFBrowserThread.GetErrorCode : integer; function TCEFBrowserThread.GetErrorCode : integer;
begin begin
FBrowserInfoCS.Acquire; if assigned(FBrowserInfoCS) then
Result := FErrorCode; try
FBrowserInfoCS.Release; FBrowserInfoCS.Acquire;
Result := FErrorCode;
finally
FBrowserInfoCS.Release;
end
else
Result := 0;
end; end;
function TCEFBrowserThread.GetErrorText : ustring; function TCEFBrowserThread.GetErrorText : ustring;
begin begin
FBrowserInfoCS.Acquire; if assigned(FBrowserInfoCS) then
Result := FErrorText; try
FBrowserInfoCS.Release; FBrowserInfoCS.Acquire;
Result := FErrorText;
finally
FBrowserInfoCS.Release;
end
else
Result := '';
end; end;
function TCEFBrowserThread.GetFailedUrl : ustring; function TCEFBrowserThread.GetFailedUrl : ustring;
begin begin
FBrowserInfoCS.Acquire; if assigned(FBrowserInfoCS) then
Result := FFailedUrl; try
FBrowserInfoCS.Release; FBrowserInfoCS.Acquire;
Result := FFailedUrl;
finally
FBrowserInfoCS.Release;
end
else
Result := '';
end; end;
function TCEFBrowserThread.GetInitialized : boolean; function TCEFBrowserThread.GetInitialized : boolean;
@ -267,45 +294,85 @@ begin
end; end;
end; end;
procedure TCEFBrowserThread.SetErrorText(const aValue : ustring);
begin
if assigned(FBrowserInfoCS) then
try
FBrowserInfoCS.Acquire;
FErrorText := aValue;
finally
FBrowserInfoCS.Release;
end;
end;
function TCEFBrowserThread.CopySnapshot(var aSnapshot : TBitmap) : boolean; function TCEFBrowserThread.CopySnapshot(var aSnapshot : TBitmap) : boolean;
begin begin
Result := False; Result := False;
if FClosing or Terminated or (FBrowserInfoCS = nil) then exit; if FClosing or Terminated or not(Initialized) then exit;
try if assigned(FBrowserInfoCS) then
try try
FBrowserInfoCS.Acquire; try
FBrowserInfoCS.Acquire;
if assigned(FSnapshot) and not(FSnapshot.Empty) then if assigned(FSnapshot) and not(FSnapshot.Empty) then
begin begin
if (aSnapshot = nil) then if (aSnapshot = nil) then
begin begin
aSnapshot := TBitmap.Create; aSnapshot := TBitmap.Create;
aSnapshot.PixelFormat := pf32bit; aSnapshot.PixelFormat := pf32bit;
aSnapshot.HandleType := bmDIB; aSnapshot.HandleType := bmDIB;
aSnapshot.Width := FSnapshot.Width; end;
aSnapshot.Height := FSnapshot.Height;
end;
aSnapshot.Assign(FSnapshot); if (aSnapshot.Width <> FSnapshot.Width) then
Result := True; aSnapshot.Width := FSnapshot.Width;
end;
except if (aSnapshot.Height <> FSnapshot.Height) then
on e : exception do aSnapshot.Height := FSnapshot.Height;
if CustomExceptionHandler('TCEFBrowserThread.CopySnapshot', e) then raise;
aSnapshot.Canvas.Draw(0, 0, FSnapshot);
Result := True;
end;
except
on e : exception do
if CustomExceptionHandler('TCEFBrowserThread.CopySnapshot', e) then raise;
end;
finally
FBrowserInfoCS.Release;
end;
end;
function TCEFBrowserThread.SaveSnapshotToFile(const aPath : ustring) : boolean;
begin
Result := False;
if FClosing or Terminated or not(Initialized) then exit;
if assigned(FBrowserInfoCS) and (length(aPath) > 0) then
try
try
FBrowserInfoCS.Acquire;
if assigned(FSnapshot) and not(FSnapshot.Empty) then
begin
FSnapshot.SaveToFile(aPath);
Result := True;
end;
except
on e : exception do
if CustomExceptionHandler('TCEFBrowserThread.SaveSnapshotToFile', e) then raise;
end;
finally
FBrowserInfoCS.Release;
end; end;
finally
FBrowserInfoCS.Release;
end;
end; end;
procedure TCEFBrowserThread.LoadUrl(const aURL : ustring); procedure TCEFBrowserThread.LoadUrl(const aURL : ustring);
begin begin
if FClosing or Terminated or (FBrowserInfoCS = nil) then if FClosing or Terminated or not(Initialized) then exit;
exit;
if Initialized then if assigned(FBrowserInfoCS) then
try try
FBrowserInfoCS.Acquire; FBrowserInfoCS.Acquire;
FPendingUrl := aURL; FPendingUrl := aURL;
@ -328,9 +395,13 @@ end;
procedure TCEFBrowserThread.Browser_OnAfterCreated(Sender: TObject; const browser: ICefBrowser); procedure TCEFBrowserThread.Browser_OnAfterCreated(Sender: TObject; const browser: ICefBrowser);
begin begin
FBrowserInfoCS.Acquire; if assigned(FBrowserInfoCS) then
FInitialized := True; try
FBrowserInfoCS.Release; FBrowserInfoCS.Acquire;
FInitialized := True;
finally
FBrowserInfoCS.Release;
end;
end; end;
procedure TCEFBrowserThread.Browser_OnPaint(Sender: TObject; const browser: ICefBrowser; kind: TCefPaintElementType; dirtyRectsCount: NativeUInt; const dirtyRects: PCefRectArray; const buffer: Pointer; aWidth, aHeight: Integer); procedure TCEFBrowserThread.Browser_OnPaint(Sender: TObject; const browser: ICefBrowser; kind: TCefPaintElementType; dirtyRectsCount: NativeUInt; const dirtyRects: PCefRectArray; const buffer: Pointer; aWidth, aHeight: Integer);
@ -344,112 +415,116 @@ var
TempBitmap : TBitmap; TempBitmap : TBitmap;
TempSrcRect : TRect; TempSrcRect : TRect;
begin begin
try if assigned(FResizeCS) and assigned(FPanel) then
FResizeCS.Acquire; try
TempForcedResize := False; FResizeCS.Acquire;
TempForcedResize := False;
if FPanel.BeginBufferDraw then if FPanel.BeginBufferDraw then
begin begin
if (kind = PET_POPUP) then if (kind = PET_POPUP) then
begin begin
if (FPopUpBitmap = nil) or if (FPopUpBitmap = nil) or
(aWidth <> FPopUpBitmap.Width) or (aWidth <> FPopUpBitmap.Width) or
(aHeight <> FPopUpBitmap.Height) then (aHeight <> FPopUpBitmap.Height) then
begin begin
if (FPopUpBitmap <> nil) then FPopUpBitmap.Free; if (FPopUpBitmap <> nil) then FPopUpBitmap.Free;
FPopUpBitmap := TBitmap.Create; FPopUpBitmap := TBitmap.Create;
FPopUpBitmap.PixelFormat := pf32bit; FPopUpBitmap.PixelFormat := pf32bit;
FPopUpBitmap.HandleType := bmDIB; FPopUpBitmap.HandleType := bmDIB;
FPopUpBitmap.Width := aWidth; FPopUpBitmap.Width := aWidth;
FPopUpBitmap.Height := aHeight; FPopUpBitmap.Height := aHeight;
end; end;
TempBitmap := FPopUpBitmap; TempBitmap := FPopUpBitmap;
TempBitmap.BeginUpdate; TempBitmap.BeginUpdate;
TempWidth := FPopUpBitmap.Width; TempWidth := FPopUpBitmap.Width;
TempHeight := FPopUpBitmap.Height; TempHeight := FPopUpBitmap.Height;
end end
else else
begin begin
TempForcedResize := FPanel.UpdateBufferDimensions(aWidth, aHeight) or not(FPanel.BufferIsResized(False)); TempForcedResize := FPanel.UpdateBufferDimensions(aWidth, aHeight) or not(FPanel.BufferIsResized(False));
TempBitmap := FPanel.Buffer; TempBitmap := FPanel.Buffer;
TempBitmap.BeginUpdate; TempBitmap.BeginUpdate;
TempWidth := FPanel.BufferWidth; TempWidth := FPanel.BufferWidth;
TempHeight := FPanel.BufferHeight; TempHeight := FPanel.BufferHeight;
end; end;
SrcStride := aWidth * SizeOf(TRGBQuad); SrcStride := aWidth * SizeOf(TRGBQuad);
n := 0; n := 0;
while (n < dirtyRectsCount) do while (n < dirtyRectsCount) do
begin begin
if (dirtyRects^[n].x >= 0) and (dirtyRects^[n].y >= 0) then if (dirtyRects^[n].x >= 0) and (dirtyRects^[n].y >= 0) then
begin begin
TempLineSize := min(dirtyRects^[n].width, TempWidth - dirtyRects^[n].x) * SizeOf(TRGBQuad); TempLineSize := min(dirtyRects^[n].width, TempWidth - dirtyRects^[n].x) * SizeOf(TRGBQuad);
if (TempLineSize > 0) then if (TempLineSize > 0) then
begin begin
TempSrcOffset := ((dirtyRects^[n].y * aWidth) + dirtyRects^[n].x) * SizeOf(TRGBQuad); TempSrcOffset := ((dirtyRects^[n].y * aWidth) + dirtyRects^[n].x) * SizeOf(TRGBQuad);
TempDstOffset := (dirtyRects^[n].x * SizeOf(TRGBQuad)); TempDstOffset := (dirtyRects^[n].x * SizeOf(TRGBQuad));
src := @PByte(buffer)[TempSrcOffset]; src := @PByte(buffer)[TempSrcOffset];
i := 0; i := 0;
j := min(dirtyRects^[n].height, TempHeight - dirtyRects^[n].y); j := min(dirtyRects^[n].height, TempHeight - dirtyRects^[n].y);
while (i < j) do while (i < j) do
begin begin
TempBufferBits := TempBitmap.Scanline[dirtyRects^[n].y + i]; TempBufferBits := TempBitmap.Scanline[dirtyRects^[n].y + i];
dst := @PByte(TempBufferBits)[TempDstOffset]; dst := @PByte(TempBufferBits)[TempDstOffset];
Move(src^, dst^, TempLineSize); Move(src^, dst^, TempLineSize);
Inc(src, SrcStride); Inc(src, SrcStride);
inc(i); inc(i);
end; end;
end; end;
end; end;
inc(n); inc(n);
end; end;
TempBitmap.EndUpdate; TempBitmap.EndUpdate;
if FShowPopup and (FPopUpBitmap <> nil) then if FShowPopup and (FPopUpBitmap <> nil) then
begin begin
TempSrcRect := Rect(0, 0, TempSrcRect := Rect(0, 0,
min(FPopUpRect.Right - FPopUpRect.Left, FPopUpBitmap.Width), min(FPopUpRect.Right - FPopUpRect.Left, FPopUpBitmap.Width),
min(FPopUpRect.Bottom - FPopUpRect.Top, FPopUpBitmap.Height)); min(FPopUpRect.Bottom - FPopUpRect.Top, FPopUpBitmap.Height));
FPanel.BufferDraw(FPopUpBitmap, TempSrcRect, FPopUpRect); FPanel.BufferDraw(FPopUpBitmap, TempSrcRect, FPopUpRect);
end; end;
FPanel.EndBufferDraw; FPanel.EndBufferDraw;
if (kind = PET_VIEW) then if (kind = PET_VIEW) then
begin begin
if TempForcedResize or FPendingResize then if TempForcedResize or FPendingResize then
PostThreadMessage(ThreadID, CEF_PENDINGRESIZE, 0, 0); PostThreadMessage(ThreadID, CEF_PENDINGRESIZE, 0, 0);
FResizing := False; FResizing := False;
FPendingResize := False; FPendingResize := False;
end; end;
end; end;
finally finally
FResizeCS.Release; FResizeCS.Release;
end; end;
end; end;
procedure TCEFBrowserThread.Browser_OnGetViewRect(Sender: TObject; const browser: ICefBrowser; var rect: TCefRect); procedure TCEFBrowserThread.Browser_OnGetViewRect(Sender: TObject; const browser: ICefBrowser; var rect: TCefRect);
begin begin
rect.x := 0; if assigned(FPanel) then
rect.y := 0; begin
rect.width := DeviceToLogical(FPanel.Width, FScreenScale); rect.x := 0;
rect.height := DeviceToLogical(FPanel.Height, FScreenScale); rect.y := 0;
rect.width := DeviceToLogical(FPanel.Width, FScreenScale);
rect.height := DeviceToLogical(FPanel.Height, FScreenScale);
end;
end; end;
procedure TCEFBrowserThread.Browser_OnGetScreenPoint(Sender: TObject; const browser: ICefBrowser; viewX, viewY: Integer; var screenX, screenY: Integer; out Result: Boolean); procedure TCEFBrowserThread.Browser_OnGetScreenPoint(Sender: TObject; const browser: ICefBrowser; viewX, viewY: Integer; var screenX, screenY: Integer; out Result: Boolean);
@ -463,19 +538,22 @@ procedure TCEFBrowserThread.Browser_OnGetScreenInfo(Sender: TObject; const brows
var var
TempRect : TCEFRect; TempRect : TCEFRect;
begin begin
TempRect.x := 0; if assigned(FPanel) then
TempRect.y := 0; begin
TempRect.width := DeviceToLogical(FPanel.Width, FScreenScale); TempRect.x := 0;
TempRect.height := DeviceToLogical(FPanel.Height, FScreenScale); TempRect.y := 0;
TempRect.width := DeviceToLogical(FPanel.Width, FScreenScale);
TempRect.height := DeviceToLogical(FPanel.Height, FScreenScale);
screenInfo.device_scale_factor := FScreenScale; screenInfo.device_scale_factor := FScreenScale;
screenInfo.depth := 0; screenInfo.depth := 0;
screenInfo.depth_per_component := 0; screenInfo.depth_per_component := 0;
screenInfo.is_monochrome := Ord(False); screenInfo.is_monochrome := Ord(False);
screenInfo.rect := TempRect; screenInfo.rect := TempRect;
screenInfo.available_rect := TempRect; screenInfo.available_rect := TempRect;
Result := True; Result := True;
end;
end; end;
procedure TCEFBrowserThread.Browser_OnPopupShow(Sender: TObject; const browser: ICefBrowser; show: Boolean); procedure TCEFBrowserThread.Browser_OnPopupShow(Sender: TObject; const browser: ICefBrowser; show: Boolean);
@ -514,7 +592,7 @@ end;
procedure TCEFBrowserThread.Browser_OnLoadError(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; errorCode: Integer; const errorText, failedUrl: ustring); procedure TCEFBrowserThread.Browser_OnLoadError(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; errorCode: Integer; const errorText, failedUrl: ustring);
begin begin
if not(FClosing) and not(Terminated) and (frame <> nil) and frame.IsValid and frame.IsMain then if not(FClosing) and not(Terminated) and (frame <> nil) and frame.IsValid and frame.IsMain and assigned(FBrowserInfoCS) then
try try
FBrowserInfoCS.Acquire; FBrowserInfoCS.Acquire;
@ -534,37 +612,27 @@ begin
PostThreadMessage(ThreadID, CEF_WEBPAGE_LOADED_MSG, 0, 0); PostThreadMessage(ThreadID, CEF_WEBPAGE_LOADED_MSG, 0, 0);
end; end;
procedure TCEFBrowserThread.DoOnError;
begin
FOnError(self);
end;
procedure TCEFBrowserThread.DoOnSnapshotAvailable;
begin
FOnSnapshotAvailable(self);
end;
procedure TCEFBrowserThread.Resize; procedure TCEFBrowserThread.Resize;
begin begin
if FClosing or Terminated or (FPanel = nil) or (FResizeCS = nil) or (FBrowser = nil) then if FClosing or Terminated or not(Initialized) then exit;
exit;
try if assigned(FResizeCS) and assigned(FPanel) then
FResizeCS.Acquire; try
FResizeCS.Acquire;
if FResizing then if FResizing then
FPendingResize := True FPendingResize := True
else
if FPanel.BufferIsResized then
FBrowser.Invalidate(PET_VIEW)
else else
begin if FPanel.BufferIsResized then
FResizing := True; FBrowser.Invalidate(PET_VIEW)
FBrowser.WasResized; else
end; begin
finally FResizing := True;
FResizeCS.Release; FBrowser.WasResized;
end; end;
finally
FResizeCS.Release;
end;
end; end;
function TCEFBrowserThread.CreateBrowser : boolean; function TCEFBrowserThread.CreateBrowser : boolean;
@ -574,20 +642,20 @@ end;
procedure TCEFBrowserThread.LoadPendingURL; procedure TCEFBrowserThread.LoadPendingURL;
begin begin
if FClosing or Terminated or (FBrowser = nil) or (FBrowserInfoCS = nil) then if FClosing or Terminated or not(Initialized) then exit;
exit;
try if assigned(FBrowserInfoCS) then
FBrowserInfoCS.Acquire; try
FBrowserInfoCS.Acquire;
if (length(FPendingURL) > 0) then if (length(FPendingURL) > 0) then
begin begin
FBrowser.LoadURL(FPendingURL); FBrowser.LoadURL(FPendingURL);
FPendingURL := ''; FPendingURL := '';
end; end;
finally finally
FBrowserInfoCS.Release; FBrowserInfoCS.Release;
end; end;
end; end;
procedure TCEFBrowserThread.WebpagePostProcessing; procedure TCEFBrowserThread.WebpagePostProcessing;
@ -598,33 +666,58 @@ begin
if (FDelayMs > 0) then if (FDelayMs > 0) then
sleep(FDelayMs); sleep(FDelayMs);
TakeSnapshot; if TakeSnapshot and assigned(FOnSnapshotAvailable) then
begin
if assigned(FOnSnapshotAvailable) then if FSyncEvents then
Synchronize(DoOnSnapshotAvailable); Synchronize(DoOnSnapshotAvailable)
else
DoOnSnapshotAvailable;
end;
end; end;
procedure TCEFBrowserThread.TakeSnapshot; procedure TCEFBrowserThread.WebpageError;
begin begin
if (FPanel = nil) or (FPanel.Buffer = nil) or (FBrowserInfoCS = nil) then if not(FClosing) and not(Terminated) and assigned(FOnError) then
exit; begin
if FSyncEvents then
Synchronize(DoOnError)
else
DoOnError;
end;
end;
try function TCEFBrowserThread.TakeSnapshot : boolean;
FBrowserInfoCS.Acquire; begin
Result := False;
if (FSnapshot = nil) then if FClosing or Terminated or not(Initialized) then exit;
begin
FSnapshot := TBitmap.Create;
FSnapshot.PixelFormat := pf32bit;
FSnapshot.HandleType := bmDIB;
FSnapshot.Width := FPanel.BufferWidth;
FSnapshot.Height := FPanel.BufferHeight;
end;
FSnapshot.Assign(FPanel.Buffer); if assigned(FBrowserInfoCS) and assigned(FPanel) and FPanel.BeginBufferDraw then
finally try
FBrowserInfoCS.Release; FBrowserInfoCS.Acquire;
end;
if assigned(FPanel.Buffer) and not(FPanel.Buffer.Empty) then
begin
if (FSnapshot = nil) then
begin
FSnapshot := TBitmap.Create;
FSnapshot.PixelFormat := pf32bit;
FSnapshot.HandleType := bmDIB;
end;
if (FSnapshot.Width <> FPanel.BufferWidth) then
FSnapshot.Width := FPanel.BufferWidth;
if (FSnapshot.Height <> FPanel.BufferHeight) then
FSnapshot.Height := FPanel.BufferHeight;
FSnapshot.Canvas.Draw(0, 0, FPanel.Buffer);
Result := True;
end;
finally
FBrowserInfoCS.Release;
FPanel.EndBufferDraw;
end;
end; end;
procedure TCEFBrowserThread.CloseBrowser; procedure TCEFBrowserThread.CloseBrowser;
@ -636,6 +729,26 @@ begin
end; end;
end; end;
procedure TCEFBrowserThread.DoOnError;
begin
FOnError(self);
end;
procedure TCEFBrowserThread.DoOnSnapshotAvailable;
begin
FOnSnapshotAvailable(self);
end;
procedure TCEFBrowserThread.InitError;
begin
ErrorText := 'There was an error initializing the CEF browser.';
if FSyncEvents then
Synchronize(DoOnError)
else
DoOnError;
end;
procedure TCEFBrowserThread.Execute; procedure TCEFBrowserThread.Execute;
var var
TempCont : boolean; TempCont : boolean;
@ -649,17 +762,19 @@ begin
while TempCont and GetMessage(TempMsg, 0, 0, 0) and not(Terminated) do while TempCont and GetMessage(TempMsg, 0, 0, 0) and not(Terminated) do
begin begin
case TempMsg.Message of case TempMsg.Message of
WM_QUIT : TempCont := False;
CEF_PENDINGRESIZE : Resize; CEF_PENDINGRESIZE : Resize;
CEF_CLOSE_BROWSER_MSG : CloseBrowser; CEF_CLOSE_BROWSER_MSG : CloseBrowser;
CEF_LOAD_PENDING_URL_MSG : LoadPendingURL; CEF_LOAD_PENDING_URL_MSG : LoadPendingURL;
CEF_WEBPAGE_LOADED_MSG : WebpagePostProcessing; CEF_WEBPAGE_LOADED_MSG : WebpagePostProcessing;
CEF_WEBPAGE_ERROR_MSG : if assigned(FOnError) then Synchronize(DoOnError); CEF_WEBPAGE_ERROR_MSG : WebpageError;
WM_QUIT : TempCont := False;
end; end;
DispatchMessage(TempMsg); DispatchMessage(TempMsg);
end; end;
end; end
else
InitError;
end; end;
end. end.

View File

@ -1,24 +1,24 @@
object WebpageSnapshotFrm: TWebpageSnapshotFrm object WebpageSnapshotFrm: TWebpageSnapshotFrm
Left = 0 Left = 0
Height = 486
Top = 0 Top = 0
Width = 711
Caption = 'Web page snapshot' Caption = 'Web page snapshot'
ClientHeight = 486 ClientHeight = 486
ClientWidth = 711 ClientWidth = 711
Color = clBtnFace Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText Font.Color = clWindowText
Font.Height = -11 Font.Height = -11
Font.Name = 'Tahoma' Font.Name = 'Tahoma'
Font.Style = []
Position = poScreenCenter
OnCloseQuery = FormCloseQuery OnCloseQuery = FormCloseQuery
OnCreate = FormCreate OnCreate = FormCreate
PixelsPerInch = 96 Position = poScreenCenter
LCLVersion = '2.0.10.0'
object Image1: TImage object Image1: TImage
Left = 0 Left = 0
Height = 438
Top = 25 Top = 25
Width = 711 Width = 711
Height = 442
Align = alClient Align = alClient
AutoSize = True AutoSize = True
Center = True Center = True
@ -26,10 +26,10 @@ object WebpageSnapshotFrm: TWebpageSnapshotFrm
end end
object StatusBar1: TStatusBar object StatusBar1: TStatusBar
Left = 0 Left = 0
Top = 467 Height = 23
Top = 463
Width = 711 Width = 711
Height = 19 Panels = <
Panels = <
item item
Width = 1000 Width = 1000
end> end>
@ -37,27 +37,29 @@ object WebpageSnapshotFrm: TWebpageSnapshotFrm
end end
object NavigationPnl: TPanel object NavigationPnl: TPanel
Left = 0 Left = 0
Height = 25
Top = 0 Top = 0
Width = 711 Width = 711
Height = 25
Align = alTop Align = alTop
BevelOuter = bvNone BevelOuter = bvNone
ClientHeight = 25
ClientWidth = 711
TabOrder = 1 TabOrder = 1
object GoBtn: TButton object GoBtn: TButton
Left = 632 Left = 636
Height = 25
Top = 0 Top = 0
Width = 75 Width = 75
Height = 21
Align = alRight Align = alRight
Caption = 'Go' Caption = 'Go'
TabOrder = 0
OnClick = GoBtnClick OnClick = GoBtnClick
TabOrder = 0
end end
object AddressEdt: TEdit object AddressEdt: TEdit
Left = 0 Left = 0
Height = 25
Top = 0 Top = 0
Width = 632 Width = 636
Height = 21
Align = alClient Align = alClient
TabOrder = 1 TabOrder = 1
Text = 'https://www.google.com' Text = 'https://www.google.com'

View File

@ -117,6 +117,7 @@ begin
FThread := TCEFBrowserThread.Create(AddressEdt.Text, 1024, 768); FThread := TCEFBrowserThread.Create(AddressEdt.Text, 1024, 768);
FThread.OnError := Thread_OnError; FThread.OnError := Thread_OnError;
FThread.OnSnapshotAvailable := Thread_OnSnapshotAvailable; FThread.OnSnapshotAvailable := Thread_OnSnapshotAvailable;
FThread.SyncEvents := True;
FThread.Start; FThread.Start;
end end
else else

View File

@ -2,7 +2,7 @@
"UpdateLazPackages" : [ "UpdateLazPackages" : [
{ {
"ForceNotify" : true, "ForceNotify" : true,
"InternalVersion" : 207, "InternalVersion" : 208,
"Name" : "cef4delphi_lazarus.lpk", "Name" : "cef4delphi_lazarus.lpk",
"Version" : "87.1.12.0" "Version" : "87.1.12.0"
} }