TPrintPreview - simple fix for scaling for High DPI monitors

Please post bug reports, feature requests, or any question regarding the DELPHI AREA projects here.

TPrintPreview - simple fix for scaling for High DPI monitors

Postby VPC16 » February 1st, 2018, 4:30 pm

I think this is a potential simple fix for Hi DPI issues on Windows 8.1 and on. Simply replace the 'CreateMetafileCanvas' proc in the unit with the one below.
The code will automatically adjust for Hi DPI displays that need scaling of the Metafile to the Main Monitor (Monitor 0).
Once the Preview is rendered on a form the form may be moved from one screen to another, just scaling needed on creation.
The other option is to use a Manifest as described in this forum, but that requires changes to existing code to handle high dpi issues.
I found hints of this method online for other programs. Tested on Delphi 7 Windows 10. Should be ok on other versions.
One other issue is mousewheel scrolling in the PrintPreview ScrollBox, WMMouseWheel, in high dpi monitor situation will have invalid Pt values. Seems you could ignore the Pt value as this is always from the ScrollBox.
I added header footer to the demo as shown in the screenshot below.
Comment if you have problems with this suggestion. Hope this helps.
Great and very useful VCL, thanks for providing it and your other units to the community.

Code: Select all
{ Changes to handle Hi DPI scaling mods }
procedure TPrintPreview.CreateMetafileCanvas(out AMetafile: TMetafile; out ACanvas: TCanvas);

  { Scale to Main Monitor }
  function ScaleToMainMontRes(ValI: Integer): Integer;
    var  TempH: HDC;
    begin
      TempH := GetDC(0);     { Scale to DF (Main) Monitor 0 }
      try
        Result := Round((ValI * GetDeviceCaps(TempH, VERTRES)) / GetDeviceCaps(TempH, DESKTOPVERTRES));
      finally
        ReleaseDC(0, TempH);
      end;
    end;

begin
  AMetafile := TMetafile.Create;
  try
    AMetafile.Width := ScaleToMainMontRes(FDeviceExt.X);
    AMetafile.Height := ScaleToMainMontRes(FDeviceExt.Y);

    ACanvas := TMetafileCanvas.CreateWithComment(AMetafile, 0,
      Format('%s - http://www.delphiarea.com', [ClassName]), PrintJobTitle);

    if ACanvas.Handle = 0 then 
    begin
      ACanvas.Free;
      ACanvas := nil;
      RaiseOutOfMemory;
    end;
  except
    AMetafile.Free;
    AMetafile := nil;
    raise;
  end;

  ACanvas.Font.Assign(Font);
  ScaleCanvas(ACanvas);
  SetBkColor(ACanvas.Handle, RGB(255, 255, 255));
  SetBkMode(ACanvas.Handle, TRANSPARENT);
end;


Here is a screenshot of the General Demo on a high DPI system with the main monitor at 175%, normally the Preview would be shrunk in size.
Attachments
TPrintPreview General Scr Shot.png
Screenshot
TPrintPreview General Scr Shot.png (97.06 KiB) Viewed 826 times
VPC16
Active Member
Active Member
 
Posts: 13
Joined: August 30th, 2016, 2:26 pm

Re: TPrintPreview - simple fix for scaling for High DPI moni

Postby Kambiz » March 4th, 2018, 11:48 am

Thank you so much for posting this solution. I used your code in the component.

I just uploaded an update of the component, addressing both scaling and mouse wheel issues.
Kambiz
User avatar
Kambiz
Administrator
Administrator
 
Posts: 2421
Joined: March 7th, 2003, 7:10 pm

Re: TPrintPreview - simple fix for scaling for High DPI moni

Postby VPC16 » March 6th, 2018, 6:43 pm

Thanks for checking out this suggestion and finding it useful. Great component, thank you for all your work on this and all the others you have posted for the community. Great examples of thoughtful OO programming others can learn a lot from.
VPC16
Active Member
Active Member
 
Posts: 13
Joined: August 30th, 2016, 2:26 pm


Return to DELPHI AREA Projects

Who is online

Users browsing this forum: Bing [Bot] and 1 guest

cron