• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 837
  • Last Modified:

MetaFileCanvas and reference-device

I'm trying to create a Metafile and scale it in
width and height.
The metafile has MMWidth and MMHeight to scale it,
but I does not work the way I want it to.
The Create-method of the MetafileCanvas, which I need
to write into the metafile, needs a "reference-canvas" from which
it would take the width and height of the Metafile
(if the properties MMWidth and MMHeight are
NOT previously set to own values).
Now in the first example I use 0 as reference-device,
which leads to a metafile width MMWidth set to screen.width
(MMHeight = Screen.Height), although I previously set
the MMWidth and MMHeight-components.


function SaveMetafile(fn:string;wdt,hgt:longint):boolean;
var mtf:tMetafile;
    mtfCanv:tMetaFileCanvas;
begin
  Mtf:=tMetafile.Create;
  Mtf.MMWidth:=wdt;
  Mtf.MMHeight:=hgt;
  Mtf.Width:=wdt;
  Mtf.Height:=hgt;
  MtfCanv:= TMetafileCanvas.Create(mtf, 0);
  // paint on the MtfCanvas, e.g. MtfCanv.Rectangle(0,0,wdt,hgt);
  MtfCanv.Free;
  Mtf.SaveToFile(fn);
  Mtf.Free;
end;


In the second example I use an own reference, but this does not
work because I get a runtime-exception, that the canvas does
not permit painting.

function SaveMetafile(fn:string;wdt,hgt:longint):boolean;
var mtf:tMetafile;
    mtfCanv:tMetaFileCanvas;
    bmp:tBitmap;
begin
  Mtf:=tMetafile.Create;
  Mtf.MMWidth:=wdt;
  Mtf.MMHeight:=hgt;
  Mtf.Width:=wdt;
  Mtf.Height:=hgt;
  bmp:=tBitmap.create;
  bmp.Width:=wdt;
  bmp.Height:=hgt;
  MtfCanv:= TMetafileCanvas.Create(mtf, bmp.Canvas.Handle);
  // paint on the MtfCanvas, e.g. MtfCanv.Rectangle(0,0,wdt,hgt);
  MtfCanv.Free;
  Mtf.SaveToFile(fn);
  bmp.Free;
  Mtf.Free;
end;

So both examples don't work.
How can I get a metafilecanvas scaled to wdt and hgt and a
metafile in file fn, which has the correct size?

Thanks

Gamba
0
Gamba
Asked:
Gamba
1 Solution
 
PeterLarsenCommented:
Hi Gamba,

The following sample shows how to create a EnhancedMetafile. It is then possible to use this metafile to either print (to a printer) or to draw on a canvas (print preview).

The sample is not a ready-to-use program, but it shows you how to create a metafile and put different things in it.

I hope you will find something usefull here !!

Good luck
Peter



procedure TFormDiagramPrint.LavChartMetaFile;
var
 MetaCanvas : TMetafileCanvas;
 YMargin, XMargin, AntalLinjer, fortel1, XPos : integer;
 Margin : integer;
 DiagramPos : Trect;
 LegendBredde, LegendHojde : integer;
 NyLegendBredde, NyLegendHojde : integer;
 XProcent, Yprocent : integer;
 LegendPos : Trect;
 Videre : boolean;
 LData : TLegendInfo;
 Teller : integer;
 R1 : trect;
 LinjeHojde : integer;
 Meta2 : TMetafile;
 MetaCanvas2 : TMetafileCanvas;
begin
try
MetaCanvas:=nil;
meta.free;
meta:=nil;
MetaCanvas2:=nil;
Meta2:=nil;
Meta:=UseChart.TeeCreateMetafile(true, rect(0, 0, 640, 480));
MetaCanvas:=TMetafileCanvas.create(Meta, 0);
//
margin:=round((meta.width*(50-SetMargin)/100)/2);
DiagramPos.left:=0+margin;
DiagramPos.Right:=Meta.width-margin;
margin:=round((meta.height*(50-SetMargin)/100)/2);
DiagramPos.Top:=0+margin;
DiagramPos.Bottom:=meta.height-margin;;
//
MetaCanvas.StretchDraw(DiagramPos, Meta);
//write other canvas stuff
//write bottom text
Ymargin:=round((Meta.Height*SetBundMargin/100)/2);
YMargin:=Meta.Height-Ymargin;;
AntalLinjer:=MemoBund.Lines.Count;
MetaCanvas.Font.assign(BundTekstFont);
MetaCanvas.Brush.Style:=bsClear;
Ymargin:=YMargin-(Antallinjer*MetaCanvas.TextHeight('sadJHFDlfsd'));
for fortel1:=0 to AntalLinjer-1 do
begin
 XPos:=round((Meta.width-MetaCanvas.TextWidth(MemoBund.lines[fortel1]))/2);
 MetaCanvas.TextOut(Xpos, YMargin, MemoBund.lines[fortel1]);
 Ymargin:=YMargin+MetaCanvas.TextHeight('sadælfsd');
end;
//
//write legend
if UseLegend<>nil then
begin
 //
 LegendBredde:=uselegend.Width;
 LegendHojde:=uselegend.Height;
 //
 XProcent:=round(LegendXPos/panel5.Width*100);
 YProcent:=round(LegendYPos/panel5.Height*100);
 //
 NyLegendBredde:=round(LegendBredde*LegendSize/100);
 NyLegendHojde:=round(LegendHojde*LegendSize/100);
 //
 LegendPos.left:=round(meta.Width/100*XProcent);
 LegendPos.Right:=round(meta.Width/100*XProcent)+NyLegendBredde;
 LegendPos.Top:=round(meta.Height/100*YProcent);
 LegendPos.Bottom:=round(meta.Height/100*YProcent)+NyLegendHojde;
 //
 Meta2:=tmetafile.create;
 Meta2.Width:=LegendBredde;
 Meta2.Height:=LegendHojde;
 MetaCanvas2:=TMetafileCanvas.create(Meta2, 0);
 MetaCanvas2.Font.assign(LegendFont);
 //
 if MedFarver = true then
  MetaCanvas2.Brush.Color:=clGray
 else
  MetaCanvas2.Brush.Color:=clwhite;
 //
 MetaCanvas2.FillRect(rect(0, 0, LegendBredde, LegendHojde));
 MetaCanvas2.Brush.Color:=clBlack;
 MetaCanvas2.FrameRect(rect(0, 0, LegendBredde, LegendHojde));
 //write legend content
 Videre:=false;
 Teller:=0;
 LinjeHojde:=MetaCanvas2.TextHeight('asdflkjhØÆÅP');
 Repeat
  Ldata:=LegendInfo[Teller];
  if Ldata.InUse=false then
   break;
  //
  MetaCanvas2.Brush.Color:=Ldata.Farve;
  MetaCanvas2.Brush.Style:=bsSolid;
  R1.left:=10;
  R1.right:=20;
  R1.top:=11+(Teller*LinjeHojde);
  R1.Bottom:=9+Linjehojde+(Teller*LinjeHojde);
  MetaCanvas2.FillRect(R1);
  MetaCanvas2.Brush.Color:=clBlack;
  MetaCanvas2.FrameRect(R1);
  //
  MetaCanvas2.Brush.Style:=bsClear;
  MetaCanvas2.TextOut(R1.left+30, R1.top, Ldata.Navn);
  //
  Teller:=teller+1;
 until videre = true;
 //
 MetaCanvas2.Free;
 MetaCanvas.StretchDraw(LegendPos, Meta2);
 Meta2.Free;
end; //end if, write legend
//
MetaCanvas.free;
//
except
 if MetaCanvas<>nil then
  MetaCanvas.free;
 if MetaCanvas2<>nil then
  MetaCanvas2.free;
 if Meta2<>nil then
  Meta2.free;
end; //end try
end;
0
 
AswCommented:
Listening.
0
 
vanbeekCommented:
The native format of the Metafilecanvas are MM_HEIGHT and MM_WIDTH. However the relation between the internal mapping of Metafilecanvas and the outside world is controlled by the mapping modes (MM_TEXT, MM_LOMETRIC, MM_HIMETRIC, MM_LOENGLISH, MM_HIENGLISH, MM_TWIPS, MM_ISOTROPIC and MM_ANISOTROPIC) (see msdn for more information on these mapping modes). Unfortunately I don't think it is possible to draw using MM_ coordinates, hence you will need to scale the Pixel coordinates to MM_ dimensions before drawing.
0
 
RadlerCommented:
Listening...
0
 
vanbeekCommented:
Gamba,

Here is a code snippet using MetafileCanvas and MM_HIMETRIC. Note that the y-axis definition of MM_HIMETRIC is opposite of that used by Rectangle! I use Clipboard to transport the metafile into MS Word.

// create canvas of size 20 mm by 50 mm
mtf := TMetaFile.Create;
mtf.MMWidth := 2000;
mtf.MMHeight := 5000;
mtfcv := TMetaFileCanvas.Create(mtf, 0);
rect.Top := 0;
rect.Left := 0;
rect.Bottom := -4000; // positive Y is up for HIMETRIC!
   
rect.Right := 1000;
SetMapMode(mtfcv.Handle, MM_HIMETRIC);
mtfcv.Rectangle(rect);
mtfcv.Free;
Clipboard.Clear;
ClipBoard.Assign(mtf);
mtf.Free;


0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Tackle projects and never again get stuck behind a technical roadblock.
Join Now