We help IT Professionals succeed at work.

Metafile scaling - how do I get real size?

sfb
sfb asked
on
Medium Priority
2,055 Views
Last Modified: 2008-03-10
Here's a weird one.  In VB5, when you import and print a WMF, the thing prints original size (of course you'd have to use VB which takes the fun away.<g>)

In Delphi (2), the size is shrunk by a huge amount.  It looks like it is taking the pixel resolution?  I can stretch it to fit the page, but I want to keep the original's size so I can write on the graphic form.


var
   Wmf1: TMetaFile;
   r: TRect;
begin
     Wmf1 := TMetaFile.Create;
     Wmf1.LoadFromFile('D:\BACKUP\DELPHI\FormPrint\7501.wmf');
     // Wmf1.Inch := 1440;
     // In Pixels for some reason.  96 pixels per inch
     if PrintDialog1.Execute then begin;
        Printer.BeginDoc;                               { begin to send print job to printer }
        Printer.NewPage;
        r:=Printer.Canvas.ClipRect;
        Printer.Canvas.Draw(0,0,Wmf1);
        // Printer.Canvas.StretchDraw(Printer.Canvas.ClipRect, Wmf1);
        Printer.EndDoc;
Comment
Watch Question

Do you try Wmf1.Width and Height after Loading from file ?
sfb

Author

Commented:
Yes Mirek.  I tried looking at it through debug - I don't have the exact value with me, but it was a height of around 900 to just over 1000.  At 96 pixels per inch, it appears as though the WMF is about right for screen display.  Roughly 6.5 times smaller than what is needed for a 600dpi printer.

In Delphi2 and 3 You can Use GetEnhMetafileHeader the last value in this header is szlMillimeters which specifies the resolution of the reference device, in millimeters The previus value szlDevice specifies the resolution of the reference device, in pixels.

This can help you ?


CERTIFIED EXPERT

Commented:
 StretchDrawing a Metafile like this will result in a small image because as you say the pixel resolution of the printer is very high. The solution I use is to take the X and Y resolutions of the printer and then calculate the actual size of the rectangle that the metafile should be drawn into in printer units. The pixel units in a metafile correspond to 1/100 mm so the conversion is very simple.
  I'm in a hurry right now so I'll leave this as an answer. If you think I'm on the right track then leave a message, and I'll post up the code to do all this.

  Steven.

sfb

Author

Commented:
Hi Steven,

I think you're on the right track, but I want to clarify a few points.  1) The stretchdraw is commented out - the 'straight' draw produces the small image.  2) I don't want to stretch the image to fit available space ... I want to convert it back to original size.

The metafile is a form - complete with text in certain point sizes.  I want to fill in the blanks within my print routine - so I need the metafile in it's exact size and proportion to hit the blank spaces correctly.

I figured there was an easy way to get the printer resolution and perform a stretch based on the conversion factor of the original wmf.

If that's what you have, post away!!!

Thanks,

Scott
CERTIFIED EXPERT

Commented:
 It is pretty simple, I'll post it on Monday, cause I've got some examples at work.

Steven.
CERTIFIED EXPERT

Commented:
Hi Scott,

  Try this:

  Make a new application, add a button and link it to this method (you'll have to add Printers to the Uses also):


procedure TForm1.Button1Click(Sender: TObject);
var
  ADevice,ADriver,APort : ARRAY [0..255] of Char;
  DeviceHandle : THandle;
  DevMode : PDeviceMode;
  DPIx,DPIy : Integer;
  XSc,YSc : Double;
  XSize,YSize : Integer;
  AMetaMMWidth,AMetaMMHeight : Integer;
  Printer : TPrinter;
  AMetafile : TMetafile;
  AnOpenDialog : TOpenDialog;
begin
  try
    AMetaFile := TMetafile.Create;
    Printer := TPrinter.Create;
    AnOpenDialog := TOpenDialog.Create(Self);
    If AnOpenDialog.Execute then begin

      Printer.GetPrinter(ADevice,ADriver,APort,DeviceHandle); // Initialise everything
      AMetafile.LoadFromFile(AnOpenDialog.FileName);

      If DeviceHandle = 0 then begin
        Printer.PrinterIndex := Printer.PrinterIndex;
        Printer.GetPrinter(ADevice,ADriver,APort,DeviceHandle);
      end;
      If DeviceHandle = 0 then
        Raise Exception.Create('Could Not Initialize Printer')
      else
        DevMode := GlobalLock(DeviceHandle);

      with DevMode^ do begin
        dmFields := dmFields or DM_PRINTQUALITY; // Calculate scaling in dots per inch
        DPIx := dmPrintQuality;
        dmFields := dmFields or DM_YRESOLUTION;
        DPIy := dmYResolution;
      end;

      XSc := DPIx/2540; // Convert to dots per hundredth of mm
      YSc := DPIy/2540;

      AMetaMMWidth := round(AMetaFile.Width/(Screen.PixelsPerInch/2540)); // Calculate size of metafile in 100ths mm
      AMetaMMHeight := round(AMetaFile.Width/(Screen.PixelsPerInch/2540));
      {Using AMetafile.MMWidth should have the same effect, however it seems to screw up too often}

      XSize := round(AMetaMMWidth*XSc); // Calculate sizes in printer units
      YSize := round(AMetaMMHeight*YSc);


      Printer.BeginDoc; // draw to the Printer Canvas
      try
        Printer.Canvas.StretchDraw(Rect(0,0,XSize,YSize),AMetaFile);
      finally
        Printer.EndDoc;
      end;
    end;
  finally
    Printer.Free;
    AMetaFile.Free;
    AnOpenDialog.Free;
  end;

end;



  Hopefully this should do what you're after. If it does then the code should be pretty obvious to translate to your application. If you've any more questions then fire away.

  Steven.
CERTIFIED EXPERT

Commented:
 I assure you that this code was indented with much more skill prior to pressing the submit button.

  Steven.
CERTIFIED EXPERT
Commented:
 Hello Scott,

  Are you still out there? Perhaps you'll notice an answer.

  Steven.

Not the solution you were looking for? Getting a personalized solution is easy.

Ask the Experts
sfb

Author

Commented:
Sorry for the delay.  I put the code in and ran it as is - I kept getting GPF type errors, and there was a slight problem because the height calculation was using AMetaFile.Width.

All the guts are there though!

Thanks,

Scott
CERTIFIED EXPERT

Commented:
 Oops, your right. Sorry about that, That'll teach me to only test the thing on square images. Have the faults stopped? What was causing them?

  Steven.
Access more of Experts Exchange with a free account
Thanks for using Experts Exchange.

Create a free account to continue.

Limited access with a free account allows you to:

  • View three pieces of content (articles, solutions, posts, and videos)
  • Ask the experts questions (counted toward content limit)
  • Customize your dashboard and profile

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.