FastReport_2022_VCL/Source/frxOLE.pas
2024-01-01 16:13:08 +01:00

359 lines
8.6 KiB
ObjectPascal

{******************************************}
{ }
{ FastReport VCL }
{ OLE object }
{ }
{ Copyright (c) 1998-2021 }
{ by Fast Reports Inc. }
{ }
{******************************************}
unit frxOLE;
interface
{$I frx.inc}
uses
{$IFNDEF FPC}
Windows, Messages,
{$ENDIF}
SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
{$IFNDEF FPC}
OleCtnrs,
{$ENDIF}
StdCtrls, ExtCtrls, frxClass
{$IFNDEF FPC}
, ActiveX
{$ENDIF}
{$IFDEF FPC}
, LCLType, LCLIntf, LazHelper
{$ENDIF}
{$IFDEF Delphi6}
, Variants
{$ENDIF}
{$IFDEF FR_COM}
, FastReport_TLB
{$ENDIF};
type
TfrxSizeMode = (fsmClip, fsmScale);
{$IFDEF DELPHI16}
/// <summary>
/// The TfrxOLEObject allows the use of OLE objects in your report.
/// TfrxOLEObject is an empty component. It is used to add thefrxOLE.pas file
/// to the "uses" list. The main component is TfrxOLEView.
/// </summary>
[ComponentPlatformsAttribute(pidWin32 or pidWin64)]
{$ENDIF}
TfrxOLEObject = class(TComponent) // fake component
end;
{$IFDEF FR_COM}
TfrxOLEView = class(TfrxView, IfrxOLEView)
{$ELSE}
/// <summary>
/// The TfrxOLEView component represents an OLE object. Component can show
/// an OLE object from the DB field (you should set DataSet, DataField
/// properties).
/// </summary>
TfrxOLEView = class(TfrxView)
{$ENDIF}
private
FOleContainer: TOleContainer;
FSizeMode: TfrxSizeMode;
FStretched: Boolean;
procedure ReadData(Stream: TStream);
procedure SetStretched(const Value: Boolean);
procedure WriteData(Stream: TStream);
protected
procedure DefineProperties(Filer: TFiler); override;
{$IFDEF FR_COM}
function Get_OleContainer(out Value: IUnknown): HResult; stdcall;
function Get_SizeMode(out Value: Integer): HResult; stdcall;
function Set_SizeMode(Value: Integer): HResult; stdcall;
function Get_Stretched(out Value: WordBool): HResult; stdcall;
function Set_Stretched(Value: WordBool): HResult; stdcall;
{$ENDIF}
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure Draw(Canvas: TCanvas; ScaleX, ScaleY, OffsetX, OffsetY: Extended); override;
procedure GetData; override;
class function GetDescription: String; override;
/// <summary>
/// Reference to internal TOleContainer object.
/// </summary>
property OleContainer: TOleContainer read FOleContainer;
function IsEMFExportable: Boolean; override;
published
property BrushStyle;
property Color;
property Cursor;
property DataField;
property DataSet;
property DataSetName;
property FillType;
property Fill;
property Frame;
property SizeMode: TfrxSizeMode read FSizeMode write FSizeMode default fsmClip;
/// <summary>
/// Determines if it is necessary to stretch an OLE object to the area
/// occupied by the object in a report. It may be useful for showing MS
/// Excel objects.
/// </summary>
property Stretched: Boolean read FStretched write SetStretched default False;
property TagStr;
property URL;
end;
/// <summary>
/// This method copies the contents from ContFrom to ContTo OLE container.
/// </summary>
procedure frxAssignOle(ContFrom, ContTo: TOleContainer);
implementation
uses
frxOLERTTI,
{$IFNDEF NO_EDITORS}
frxOLEEditor,
{$ENDIF}
frxDsgnIntf, frxRes;
procedure frxAssignOle(ContFrom, ContTo: TOleContainer);
var
st: TMemoryStream;
begin
{$IFNDEF FPC}
if (ContFrom = nil) or (ContFrom.OleObjectInterface = nil) then
begin
ContTo.DestroyObject;
Exit;
end;
st := TMemoryStream.Create;
ContFrom.SaveToStream(st);
st.Position := 0;
ContTo.LoadFromStream(st);
st.Free;
{$ENDIF}
end;
function HimetricToPixels(const P: TPoint): TPoint;
begin
Result.X := MulDiv(P.X, Screen.PixelsPerInch, 2540);
Result.Y := MulDiv(P.Y, Screen.PixelsPerInch, 2540);
end;
{ TfrxOLEView }
constructor TfrxOLEView.Create(AOwner: TComponent);
begin
inherited;
Font.Name := 'Tahoma';
Font.Size := 8;
FOleContainer := TOleContainer.Create(nil);
with FOleContainer do
begin
Parent := frxParentForm;
{$IFNDEF FPC}
SendMessage(frxParentForm.Handle, WM_CREATEHANDLE, frxInteger(FOleContainer), 0);
AllowInPlace := False;
AutoVerbMenu := False;
BorderStyle := bsNone;
SizeMode := smClip;
{$ENDIF}
end;
end;
destructor TfrxOLEView.Destroy;
begin
{$IFNDEF FPC}
SendMessage(frxParentForm.Handle, WM_DESTROYHANDLE, frxInteger(FOleContainer), 0);
{$ENDIF}
FOleContainer.Free;
inherited;
end;
class function TfrxOLEView.GetDescription: String;
begin
Result := frxResources.Get('obOLE');
end;
procedure TfrxOLEView.DefineProperties(Filer: TFiler);
begin
inherited;
{$IFNDEF FPC}
Filer.DefineBinaryProperty('OLE', ReadData, WriteData,
OleContainer.OleObjectInterface <> nil);
{$ENDIF}
end;
procedure TfrxOLEView.ReadData(Stream: TStream);
begin
{$IFNDEF FPC}
FOleContainer.LoadFromStream(Stream);
{$ENDIF}
end;
procedure TfrxOLEView.WriteData(Stream: TStream);
begin
{$IFNDEF FPC}
FOleContainer.SaveToStream(Stream);
{$ENDIF}
end;
procedure TfrxOLEView.SetStretched(const Value: Boolean);
var
VS: TPoint;
begin
FStretched := Value;
{$IFNDEF FPC}
if not Stretched then
with FOleContainer do
if OleObjectInterface <> nil then
begin
Run;
VS.X := MulDiv(Width, 2540, Screen.PixelsPerInch);
VS.Y := MulDiv(Height, 2540, Screen.PixelsPerInch);
{$IFDEF WIN64}
OleObjectInterface.SetExtent(DVASPECT_CONTENT, @VS);
{$ELSE}
OleObjectInterface.SetExtent(DVASPECT_CONTENT, VS);
{$ENDIF}
end;
{$ENDIF}
end;
procedure TfrxOLEView.Draw(Canvas: TCanvas; ScaleX, ScaleY, OffsetX, OffsetY: Extended);
{$IFNDEF FPC}
var
DRect, R: TRect;
W, H: Integer;
ViewObject2: IViewObject2;
S, ViewSize: TPoint;
{$ENDIF}
begin
{$IFNDEF FPC}
BeginDraw(Canvas, ScaleX, ScaleY, OffsetX, OffsetY);
DRect := Rect(FX, FY, FX1, FY1);
OleContainer.Width := FDX;
OleContainer.Height := FDY;
DrawBackground;
if (FDX > 0) and (FDY > 0) then
with OleContainer do
if OleObjectInterface <> nil then
if Self.SizeMode = fsmClip then
OleDraw(OleObjectInterface, DVASPECT_CONTENT, Canvas.Handle, DRect)
else
begin
if Succeeded(OleObjectInterface.QueryInterface(IViewObject2,
ViewObject2)) then
begin
ViewObject2.GetExtent(DVASPECT_CONTENT, -1, nil, ViewSize);
W := DRect.Right - DRect.Left;
H := DRect.Bottom - DRect.Top;
S := HimetricToPixels(ViewSize);
if W * S.Y > H * S.X then
begin
S.X := S.X * H div S.Y;
S.Y := H;
end
else
begin
S.Y := S.Y * W div S.X;
S.X := W;
end;
R.Left := DRect.Left + (W - S.X) div 2;
R.Top := DRect.Top + (H - S.Y) div 2;
R.Right := R.Left + S.X;
R.Bottom := R.Top + S.Y;
OleDraw(OleObjectInterface, DVASPECT_CONTENT, Canvas.Handle, R);
end
end
else
frxResources.ObjectImages.Draw(Canvas, FX + 1, FY + 2, 22);
DrawFrame;
{$ENDIF}
end;
procedure TfrxOLEView.GetData;
var
s: TMemoryStream;
begin
inherited;
{$IFNDEF FPC}
if IsDataField then
begin
s := TMemoryStream.Create;
try
DataSet.AssignBlobTo(DataField, s);
FOleContainer.LoadFromStream(s);
finally
s.Free;
end;
end;
{$ENDIF}
end;
function TfrxOLEView.IsEMFExportable: Boolean;
begin
Result := False;
end;
{$IFDEF FR_COM}
function TfrxOLEView.Get_OleContainer(out Value: IUnknown): HResult; stdcall;
begin
Value := OleContainer;
Result := S_OK;
end;
function TfrxOLEView.Get_SizeMode(out Value: Integer): HResult; stdcall;
begin
Value := Integer(SizeMode);
Result := S_OK;
end;
function TfrxOLEView.Set_SizeMode(Value: Integer): HResult; stdcall;
begin
SizeMode := TfrxSizeMode(Value);
Result := S_OK;
end;
function TfrxOLEView.Get_Stretched(out Value: WordBool): HResult; stdcall;
begin
Value := Stretched;
Result := S_OK;
end;
function TfrxOLEView.Set_Stretched(Value: WordBool): HResult; stdcall;
begin
Stretched := Value;
Result := S_OK;
end;
{$ENDIF}
initialization
{$IFDEF DELPHI16}
StartClassGroup(TControl);
ActivateClassGroup(TControl);
GroupDescendentsWith(TfrxOLEObject, TControl);
{$ENDIF}
frxObjects.RegisterObject1(TfrxOLEView, nil, '', '', 0, 22);
finalization
frxObjects.UnRegister(TfrxOLEView);
end.