From:
renep@xs4all.nl (Rene Post)
Subject:
Re: Canvas from THandle (for metafiles) - Delphi
Date: Tue,
13 Jun 1995 06:05:56 GMT
lascaux@primenet.com
(Martin Lapidus) wrote:
>I need
to draw to a Windows metafile. Delphi does not directly support this,
>so I
plan to use API calls to create the metafile. Creating a Metafile returns
>a
THandle which can be cast to a DC.
>
>In
delphi, how can I use the THandle to get/create a Canvas for drawing?
I've asked
a similar question a few days ago but got no response, so
I figured
it out myself. Here's the code. (hope it's what you need).
unit
Metaform;
interface
uses
SysUtils, WinTypes, WinProcs, Messages,
Classes, Graphics, Controls,
Forms, Dialogs, StdCtrls, Buttons, ExtCtrls;
type
TForm1 = class(TForm)
Panel1: TPanel;
BitBtn1: TBitBtn;
Image1: TImage;
procedure BitBtn1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
type
TMetafileCanvas = class(TCanvas)
private
FClipboardHandle: THandle;
FMetafileHandle: HMetafile;
FRect: TRect;
protected
procedure CreateHandle; override;
function GetMetafileHandle: HMetafile;
public
constructor Create;
destructor Destroy; override;
property Rect: TRect read FRect write
FRect;
property MetafileHandle: HMetafile read
GetMetafileHandle;
end;
constructor
TMetafileCanvas.Create;
begin
inherited Create;
FClipboardHandle := GlobalAlloc(
GMEM_SHARE or GMEM_ZEROINIT,
SizeOf(TMetafilePict));
end;
destructor
TMetafileCanvas.Destroy;
begin
DeleteMetafile(CloseMetafile(Handle));
if Bool(FClipboardHandle) then
GlobalFree(FClipboardHandle);
if Bool(FMetafileHandle) then
DeleteMetafile(FMetafileHandle);
inherited Destroy;
end;
procedure
TMetafileCanvas.CreateHandle;
var
MetafileDC: HDC;
begin
{ Create a metafile DC in memory }
MetafileDC := CreateMetaFile(nil);
if Bool(MetafileDC) then
begin
{ Map the top,left corner of the displayed
rectangle to the
top,left of
the
device context. Leave a border of 10
logical units around the
picture. }
with FRect do SetWindowOrg(MetafileDC,
Left - 10, Top - 10);
{ Set the extent of the picture with a
border of 10 logical units.
}
with FRect do SetWindowExt(MetafileDC,
Right - Left + 20, Bottom -
Top + 20);
{ Play any valid metafile contents to it.
}
if Bool(FMetafileHandle) then
begin
PlayMetafile(MetafileDC,
FMetafileHandle);
end;
end;
Handle := MetafileDC;
end;
function
TMetafileCanvas.GetMetafileHandle: HMetafile;
var
MetafilePict: PMetafilePict;
IC: HDC;
ExtRect: TRect;
begin
if Bool(FMetafileHandle) then
DeleteMetafile(FMetafileHandle);
FMetafileHandle := CloseMetafile(Handle);
Handle := 0;
{ Prepair metafile for clipboard display. }
MetafilePict :=
GlobalLock(FClipboardHandle);
MetafilePict^.mm := mm_AnIsoTropic;
IC := CreateIC('DISPLAY', nil, nil, nil);
SetMapMode(IC, mm_HiMetric);
ExtRect := FRect;
DPtoLP(IC, ExtRect, 2);
DeleteDC(IC);
MetafilePict^.xExt := ExtRect.Right -
ExtRect.Left;
MetafilePict^.yExt := ExtRect.Top -
ExtRect.Bottom;
MetafilePict^.HMF := FMetafileHandle;
GlobalUnlock(FClipboardHandle);
{ I'm giving you this handle, but please do
NOT eat it. }
Result := FClipboardHandle;
end;
procedure
TForm1.BitBtn1Click(Sender: TObject);
var
MetafileCanvas : TMetafileCanvas;
begin
MetafileCanvas := TMetafileCanvas.Create;
MetafileCanvas.Rect := Rect(0,0,500,500);
MetafileCanvas.Ellipse(10,10,400,400);
Image1.Picture.Metafile.LoadFromClipboardFormat(
cf_MetafilePict,
MetafileCanvas.MetafileHandle, 0);
MetafileCanvas.Free;
end;
end.