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

Added TFMXChromium.TakeSnapshot

- Added TFMXChromium.SaveAsBitmapStream
- Added TChromium.SaveAsBitmapStream
- Fixed bug #253
This commit is contained in:
Salvador Díaz Fau
2020-01-02 20:02:47 +01:00
parent fd1e936198
commit e53cc7ee5d
7 changed files with 321 additions and 47 deletions

View File

@ -83,6 +83,7 @@ type
procedure SetFormTopTo(const y : Integer);
function CreateBrowser(const aBrowserParent : TWinControl = nil; const aWindowName : ustring = ''; const aContext : ICefRequestContext = nil; const aExtraInfo : ICefDictionaryValue = nil) : boolean; overload; virtual;
function SaveAsBitmapStream(var aStream : TStream) : boolean;
function TakeSnapshot(var aBitmap : TBitmap) : boolean;
end;
@ -289,10 +290,34 @@ begin
Result := inherited CreateBrowser(TempHandle, TempRect, aWindowName, aContext, aExtraInfo);
end;
function TChromium.SaveAsBitmapStream(var aStream : TStream) : boolean;
{$IFDEF MSWINDOWS}
var
TempDC : HDC;
TempRect : TRect;
{$ENDIF}
begin
Result := False;
{$IFDEF MSWINDOWS}
if not(FIsOSR) and (FRenderCompHWND <> 0) and (aStream <> nil) then
begin
TempDC := GetDC(FRenderCompHWND);
if (TempDC <> 0) then
try
GetClientRect(FRenderCompHWND, TempRect);
Result := CopyDCToBitmapStream(TempDC, TempRect, aStream);
finally
ReleaseDC(FRenderCompHWND, TempDC);
end;
end;
{$ENDIF}
end;
function TChromium.TakeSnapshot(var aBitmap : TBitmap) : boolean;
{$IFDEF MSWINDOWS}
var
TempHWND : HWND;
TempDC : HDC;
TempRect : TRect;
TempWidth : Integer;
@ -302,30 +327,29 @@ begin
Result := False;
{$IFDEF MSWINDOWS}
if not(FIsOSR) then
if not(FIsOSR) and (FRenderCompHWND <> 0) then
begin
TempHWND := GetWindowHandle;
GetClientRect(FRenderCompHWND, TempRect);
if (TempHWND <> 0) then
begin
GetClientRect(TempHWND, TempRect);
TempWidth := TempRect.Right - TempRect.Left;
TempHeight := TempRect.Bottom - TempRect.Top;
TempWidth := TempRect.Right - TempRect.Left;
TempHeight := TempRect.Bottom - TempRect.Top;
if (TempWidth <= 0) or (TempHeight <= 0) then exit;
if (aBitmap <> nil) then FreeAndNil(aBitmap);
if (aBitmap <> nil) then FreeAndNil(aBitmap);
aBitmap := TBitmap.Create;
aBitmap.Height := TempHeight;
aBitmap.Width := TempWidth;
aBitmap := TBitmap.Create;
aBitmap.Height := TempHeight;
aBitmap.Width := TempWidth;
TempDC := GetDC(TempHWND);
try
Result := BitBlt(aBitmap.Canvas.Handle, 0, 0, TempWidth, TempHeight,
TempDC, 0, 0, SRCCOPY);
finally
ReleaseDC(TempHWND, TempDC);
end;
TempDC := GetDC(FRenderCompHWND);
if (TempDC <> 0) then
try
Result := BitBlt(aBitmap.Canvas.Handle, 0, 0, TempWidth, TempHeight,
TempDC, 0, 0, SRCCOPY);
finally
ReleaseDC(FRenderCompHWND, TempDC);
end;
end;
{$ENDIF}

View File

@ -390,6 +390,7 @@ type
procedure BrowserCompWndProc(var aMessage: TMessage);
procedure WidgetCompWndProc(var aMessage: TMessage);
procedure RenderCompWndProc(var aMessage: TMessage);
function CopyDCToBitmapStream(aSrcDC : HDC; const aSrcRect : TRect; var aStream : TStream) : boolean;
{$ENDIF}
procedure DragDropManager_OnDragEnter(Sender: TObject; const aDragData : ICefDragData; grfKeyState: Longint; pt: TPoint; var dwEffect: Longint);
@ -4928,26 +4929,28 @@ begin
begin
{$IFDEF MSWINDOWS}
OldBrowserCompHWND := FBrowserCompHWND;
OldWidgetCompHWND := FWidgetCompHWND;
OldRenderCompHWND := FRenderCompHWND;
OldWidgetCompHWND := FWidgetCompHWND;
OldRenderCompHWND := FRenderCompHWND;
{$ENDIF}
FBrowserCompHWND := browser.Host.WindowHandle;
{$IFDEF MSWINDOWS}
if (FBrowserCompHWND <> 0) then
begin
FWidgetCompHWND := FindWindowEx(FBrowserCompHWND, 0, 'Chrome_WidgetWin_0', '');
if (FWidgetCompHWND = 0) and FIsOSR and CefCurrentlyOn(TID_UI) then
begin
// The WidgetCompHWND window doesn't have a HwndParent (Owner). If we are in OSR mode this
// causes popup menus that are opened by CEF to stay open if the user clicks somewhere else.
// With this code we search for the Widget window in the UI Thread's window list and set
// the Browser window as its HwndParent. This works around the bug.
EnumThreadWindows(GetCurrentThreadId, @EnumProcOSRChromeWidgetWin0, NativeInt(@FWidgetCompHWND));
if FWidgetCompHWND <> 0 then
SetWindowLongPtr(FWidgetCompHWND, GWLP_HWNDPARENT, NativeInt(FBrowserCompHWND));
FWidgetCompHWND := FindWindowEx(FBrowserCompHWND, 0, 'Chrome_WidgetWin_0', '');
if (FWidgetCompHWND = 0) and FIsOSR and CefCurrentlyOn(TID_UI) then
begin
// The WidgetCompHWND window doesn't have a HwndParent (Owner). If we are in OSR mode this
// causes popup menus that are opened by CEF to stay open if the user clicks somewhere else.
// With this code we search for the Widget window in the UI Thread's window list and set
// the Browser window as its HwndParent. This works around the bug.
EnumThreadWindows(GetCurrentThreadId, @EnumProcOSRChromeWidgetWin0, NativeInt(@FWidgetCompHWND));
if (FWidgetCompHWND <> 0) then
SetWindowLongPtr(FWidgetCompHWND, GWLP_HWNDPARENT, NativeInt(FBrowserCompHWND));
end;
end;
end;
if (FWidgetCompHWND <> 0) then
FRenderCompHWND := FindWindowEx(FWidgetCompHWND, 0, 'Chrome_RenderWidgetHostHWND', 'Chrome Legacy Window');
@ -5389,4 +5392,71 @@ begin
if Initialized then FBrowser.Host.IMECancelComposition;
end;
{$IFDEF MSWINDOWS}
function TChromiumCore.CopyDCToBitmapStream(aSrcDC : HDC; const aSrcRect : TRect; var aStream : TStream) : boolean;
var
TempDstDC : HDC;
TempWidth : Integer;
TempHeight : Integer;
TempInfo : TBitmapInfo;
TempBits : Pointer;
TempNewBitmap : HBITMAP;
TempOldBitmap : HBITMAP;
TempHeader : TBitmapFileHeader;
begin
Result := False;
if (aSrcDC = 0) or (aStream = nil) then exit;
TempDstDC := CreateCompatibleDC(aSrcDC);
if (TempDstDC = 0) then exit;
TempWidth := aSrcRect.Right - aSrcRect.Left;
TempHeight := aSrcRect.Bottom - aSrcRect.Top;
TempBits := nil;
if (TempWidth > 0) and (TempHeight > 0) then
begin
ZeroMemory(@TempInfo, SizeOf(TBitmapInfo));
ZeroMemory(@TempHeader, SizeOf(TBitmapFileHeader));
TempInfo.bmiHeader.biSize := SizeOf(TBitmapInfoHeader);
TempInfo.bmiHeader.biWidth := TempWidth;
TempInfo.bmiHeader.biHeight := TempHeight;
TempInfo.bmiHeader.biPlanes := 1;
TempInfo.bmiHeader.biBitCount := 32;
TempInfo.bmiHeader.biCompression := BI_RGB;
TempInfo.bmiHeader.biSizeImage := TempWidth * TempHeight * SizeOf(TRGBQuad);
TempNewBitmap := CreateDIBSection(TempDstDC, TempInfo, DIB_RGB_COLORS, TempBits, 0, 0);
if (TempNewBitmap <> 0) then
try
TempOldBitmap := SelectObject(TempDstDC, TempNewBitmap);
if BitBlt(TempDstDC, 0, 0, TempWidth, TempHeight, aSrcDC, aSrcRect.Left, aSrcRect.Top, SRCCOPY) then
begin
TempHeader.bfType := $4D42; // "BM" bitmap header
TempHeader.bfOffBits := sizeof(BITMAPFILEHEADER) + TempInfo.bmiHeader.biSize + TempInfo.bmiHeader.biClrUsed * SizeOf(TRGBQuad);
TempHeader.bfSize := TempHeader.bfOffBits + TempInfo.bmiHeader.biSizeImage;
aStream.position := 0;
aStream.Write(TempHeader, SizeOf(TBitmapFileHeader));
aStream.Write(TempInfo.bmiHeader, SizeOf(TBitmapInfoHeader));
aStream.Write(TempBits^, TempInfo.bmiHeader.biSizeImage);
aStream.position := 0;
Result := True;
end;
SelectObject(TempDstDC, TempOldBitmap);
finally
DeleteObject(TempNewBitmap);
end;
end;
ReleaseDC(0, TempDstDC);
end;
{$ENDIF}
end.

View File

@ -49,7 +49,7 @@ uses
{$IFDEF MSWINDOWS}
WinApi.Windows, WinApi.Messages, FMX.Platform.Win,
{$ENDIF}
FMX.Types, FMX.Platform, FMX.Forms, FMX.Controls,
FMX.Types, FMX.Platform, FMX.Forms, FMX.Controls, FMX.Graphics,
uCEFTypes, uCEFInterfaces, uCEFChromiumCore;
type
@ -70,6 +70,8 @@ type
procedure SetFormTopTo(const y : Integer);
function CreateBrowser(const aWindowName : ustring = ''; const aContext : ICefRequestContext = nil; const aExtraInfo : ICefDictionaryValue = nil) : boolean; overload; virtual;
function SaveAsBitmapStream(var aStream : TStream; const aRect : System.Types.TRect) : boolean;
function TakeSnapshot(var aBitmap : TBitmap; const aRect : System.Types.TRect) : boolean;
end;
// *********************************************************
@ -251,4 +253,52 @@ begin
{$ENDIF}
end;
function TFMXChromium.SaveAsBitmapStream(var aStream : TStream; const aRect : System.Types.TRect) : boolean;
{$IFDEF MSWINDOWS}
var
TempDC : HDC;
TempRect : System.Types.TRect;
{$ENDIF}
begin
Result := False;
{$IFDEF MSWINDOWS}
if not(FIsOSR) and (FRenderCompHWND <> 0) and (aStream <> nil) then
begin
TempDC := GetDC(FRenderCompHWND);
if (TempDC <> 0) then
try
TempRect := aRect;
Result := OffsetRect(TempRect, - TempRect.Left, - TempRect.Top) and
CopyDCToBitmapStream(TempDC, TempRect, aStream);
finally
ReleaseDC(FRenderCompHWND, TempDC);
end;
end;
{$ENDIF}
end;
function TFMXChromium.TakeSnapshot(var aBitmap : TBitmap; const aRect : System.Types.TRect) : boolean;
var
TempStream : TMemoryStream;
begin
Result := False;
TempStream := nil;
if FIsOSR or (aBitmap = nil) then exit;
try
TempStream := TMemoryStream.Create;
if SaveAsBitmapStream(TStream(TempStream), aRect) then
begin
aBitmap.LoadFromStream(TempStream);
Result := True;
end;
finally
FreeAndNil(TempStream);
end;
end;
end.

View File

@ -250,6 +250,8 @@ function MoveFileList(const aFileList : TStringList; const aSrcDirectory, aDstDi
function CefGetDataURI(const aString, aMimeType : ustring) : ustring; overload;
function CefGetDataURI(aData : pointer; aSize : integer; const aMimeType : ustring; const aCharset : ustring = '') : ustring; overload;
implementation
uses
@ -1993,7 +1995,7 @@ begin
if ((aDragOperations and DRAG_OPERATION_COPY) <> 0) then aEffect := aEffect or DROPEFFECT_COPY;
if ((aDragOperations and DRAG_OPERATION_LINK) <> 0) then aEffect := aEffect or DROPEFFECT_LINK;
if ((aDragOperations and DRAG_OPERATION_MOVE) <> 0) then aEffect := aEffect or DROPEFFECT_MOVE;
end;
end;
{$ENDIF}
function DeviceToLogical(aValue : integer; const aDeviceScaleFactor : double) : integer;
@ -2174,5 +2176,5 @@ begin
Result := Result + ';base64,' + CefURIEncode(CefBase64Encode(aData, aSize), false);
end;
end.
end.