uligerhardt 18 Posted October 20, 2022 I have an existing enhanced TMetafile in memory (technically speaking an array of them - it's a print preview) and want to add some text to it (page numbers). How can I best achieve that? First I tried creating a TMetafileCanvas for the MF and added my text. But creating the TMetafileCanvas clears the existing MF, so no luck. Could I supress the clearing somehow? The next idea was to clone the original MF: OrigMF := // my metafile in memory CloneMF := TMetafile.Create; try CloneMF.Assign(OrigMF); MFCanvas := TMetafileCanvas.Create(CloneMF, 0); try MFCanvas.Draw(0, 0, OrigMF); // Draw my stuff on MFCanvas finally MFCanvas.Free; end; OrigMF.Assign(CloneMF); finally CloneMF.Free; end; but I didn't manage to preserve the page dimensions, font sizes etc. The reference DC used to create OrigMF is gone and the combinations of properties like Width, MMWidth and Inch that I tried didn't help. How could I clone OrigMF retaining these informations (that must be stored inside)? PS: While writing this post I managed to dig out a reference DC that worked. But answers would be still interesting. Share this post Link to post
Remy Lebeau 1392 Posted October 20, 2022 I don't know if this is covered in the documentation (I can't find it), but in TMetaFile's source code is the following comment: Quote To create a metafile image from scratch, you must draw the image in a metafile canvas. When the canvas is destroyed, it transfers the image into the metafile object provided to the canvas constructor. After the image is drawn on the canvas and the canvas is destroyed, the image is 'playable' in the metafile object. Like this: MyMetafile := TMetafile.Create; MyMetafile.Width := 200; MyMetafile.Height := 200; with TMetafileCanvas.Create(MyMetafile, 0) do try Brush.Color := clRed; Ellipse(0,0,100,100); ... finally Free; end; Form1.Canvas.Draw(0,0,MyMetafile); (* 1 red circle *) To add to an existing metafile image, create a metafile canvas and play the source metafile into the metafile canvas. Like this: (* continued from previous example, so MyMetafile contains an image *) with TMetafileCanvas.Create(MyMetafile, 0) do try Draw(0,0,MyMetafile); Brush.Color := clBlue; Ellipse(100,100,200,200); ... finally Free; end; Form1.Canvas.Draw(0,0,MyMetafile); (* 1 red circle and 1 blue circle *) So, you just need to Draw() the existing TMetaFile onto the TMetafileCanvas before drawing anything else onto the Canvas - hmmm, but you are already doing that! Looking at the docs and the source code, TMetafileCanvas should not be clearing anything in the TMetaFile at all. Also, the ReferenceDC in the TMetaFileCanvas constructor can be 0, in which case the screen HDC will be used instead. Based on the info above, you don't need a clone at all, since modifications made to the Canvas will be applied to the original TMetaFile only when the Canvas is destroyed, eg: OrigMF := // my metafile in memory MFCanvas := TMetafileCanvas.Create(OrigMF, 0); try MFCanvas.Draw(0, 0, OrigMF); // Draw my stuff on MFCanvas finally MFCanvas.Free; end; 1 Share this post Link to post
uligerhardt 18 Posted October 21, 2022 21 hours ago, Remy Lebeau said: I don't know if this is covered in the documentation (I can't find it), but in TMetaFile's source code is the following comment: Thanks, I didn't see that comment. And indeed it mostly works without the cloning. However without passing a reference DC <> 0 resolution/size still get mixed up. But as mentioned in my postscriptum I found a compatible DC, so that's only a cosmetic problem. :-)) Share this post Link to post