Einzelnen Beitrag anzeigen

Redeemer

Registriert seit: 19. Jan 2009
Ort: Kirchlinteln (LK Verden)
1.018 Beiträge
 
Delphi 2009 Professional
 
#5

AW: SynPDF und TMetaFile

  Alt 2. Mär 2022, 21:57
Ich würde vermuten, dass sich SynPDF da irritieren lässt bzw. die Bugs einfach nicht kennt und daher keinen Workaround einsetzt. Wenn du WMF benutzt, schießt du möglicherweise schnell über die 16 Bit hinaus, die dieses Format maximal für Koordinaten vorsieht. EMF kann 32-Bit-Koordinaten (Enhanced := True). Die Koordinaten hängen von rclFrame ab und rclFrame hängt von der Bildschirmauflösung ab (Verhältnis von szlDevice zu szlMillimeters), genau weiß ich das aber nicht mehr. Das könnte erklären, warum die von dir genannten Grenzen sehr nahe an WQHD sind.
(Fun Fact: Was TMetafileCanvas im not-Enhanced-Modus produziert, ist eine EMF mit eingebetteter WMF (oder war es andersherum?). EMF-fähige Software ignoriert teilweise die WMF.)

Für TMetafileCanvas habe ich mir damals dieses Ding hier geschrieben. Da sind auch noch Relikte aus Windows 7 drin und auskommentiert, da diese Software nur noch unter Windows 10 laufen muss. (Parameter Handle ist irgendein DC, man kann sich z.B. eine leere Graphic erstellen, in meinem Fall ein TPNGImage mit Größe 1x1.)
Delphi-Quellcode:
procedure TSVGMetafile.FixRDPBug(const Handle: HDC);
var
  Temp: TMemoryStream;
  Header: PENHMETAHEADER;
begin
  // Workaround für einen Fehler in RDP, durch den szlMillimeters und rclFrame falsch sind, wenn der Hauptbildschirm des verbindenden Rechners nicht das Seitenverhältnis 4:3 hat
  // vgl. https://stackoverflow.com/a/1533053
  // Kann leider nicht beim geladenen Bild geändert werden, da man an szlDevice (HORZRES und VERTRES bei GetDeviceCaps) nicht im Speicher des vorhandenen Bildes ran kommt
  // Bug scheint in Windows 10 nicht mehr zu existieren.
  // Nachtrag 15.6.21: Dafür existiert ein ähnlicher, auf dieselbe Weise behebbarer Bug:
  // - Beim ursprünglichen RDP-Bug waren HORZSIZE und VERTSIZE zwar gleich szlMillimeters, aber falsch in Relation und im Verhältnis zu HORZRES und VERTRES.
  // - Beim neuen Bug sind HORZSIZE und VERTSIZE gleich szlMillimeters und korrekt, aber HORZRES und VERTRES sind ungleich szlDevice.

  // Besteht KEINE Remote-Desktop-Verbindung? Dann Abbruch.
  // Keine Ahnung, ob das Anfang August 2019 funktioniert hat, aber ich habe jetzt Ende Oktober 2019 keinen Self.Handle mehr, die Methode gibt daher 0 zurück, was anders als 320 bzw. 240 ist.
  // Daher wird der Handle von TMetafileCanvas übergeben.
  //if GetDeviceCaps(Handle, HORZSIZE) <> 320 then Exit;
  //if GetDeviceCaps(Handle, VERTSIZE) <> 240 then Exit;
  // Theoretisch können diese Werte auch ohne RDP auftreten, wenn der Nutzer einen 4:3-Bildschirm besitzt.
  // FixRDPBug macht korrekte Bilder nicht kaputt, daher geht es hier ausschließlich um die Performance, die bei einem Durchlauf des folgenden Codes verloren geht.
  // 15.6.21: Obige Zeilen auskommentiert da Kriterien für Bildschirmskalierungs-Bug unzureichend. Kriterien können erst nach dem Laden bestimmt werden.

  Temp := TMemoryStream.Create();
  try
    Self.SaveToStream(Temp);
    if Temp.Size > 0 then
    begin
      Temp.Position := 0;
      Header := Temp.Memory;

      if (Header^.szlDevice.cx = GetDeviceCaps(Handle, HORZRES)) and
         (Header^.szlDevice.cy = GetDeviceCaps(Handle, VERTRES)) then
      Exit;

      Header^.rclFrame.Right := (Header^.rclBounds.Right + 1) * 100;
      Header^.rclFrame.Bottom := (Header^.rclBounds.Bottom + 1) * 100;
      Header^.szlDevice.cx := 320; // gleiche Werte für beide szl-Felder machen es einfacher, Rundungsfehler hierüber zu vermeiden (man kann einfach mit 100 multiplizieren)
      Header^.szlDevice.cy := 240;
      Header^.szlMillimeters.cx := 320;
      Header^.szlMillimeters.cy := 240;

      inherited LoadFromStream(Temp);
    end;
  finally
    Temp.Free();
  end;
end;
Die hier "behandelten" Metafiles wurden von einer angepassten Version meines RedeemerSVG in der o.g. Klasse TSVGMetafile = class (TMetafile) erzeugt und per List & Label ausgegeben. List & Label basiert selbst komplett auf EMF, sprich alle angezeigten Dokumente liegen im Temp-Ordner mit einer EMF pro Seite.

Zurück zu meinem Problem: Der Fehler äußerte sich vorrangig darin, dass das Bild gestaucht wurde (ein quadratisches Bild wurde hochkant), wenn man mit einem Breitbildmonitor über RDP verbunden war. Die Koordinaten zu korrigieren brachte nichts, denn dann waren horizontale Linien dicker als vertikale. Laut PENHMETAHEADER verwendet Windows RDP hardcoded eine Auflösung von 320x240.

Für alle, die es interessiert, ein paar wirre Informationen aus meinem OneNote, größtenteils über Windows 7:
Zitat:
RDP-Bug: Runde 1 "RDP"
Vor dem Erstellen von TMetaFileCanvas
Width x Height: 187x47
MMWidth x MMHeight: 0x0

Nach dem Erstellen von TMetaFileCanvas
Width x Height: 0x0
MMWidth x MMHeight: 1558x551


OFFSETS in EMF-Header (Little Endian):
OffsetHeader-NameZumindest bei 100% und (bei Win7) ohne RDP gleich
32rclFrame.RightSelf.MMWIDTH
36rclFrame.BottomSelf.MMHEIGHT
72szlDevice.cxGetDeviceCaps(Handle, HORZRES)
76szlDevice.cyGetDeviceCaps(Handle, VERTRES)
80szlMillimeters.cxGetDeviceCaps(Handle, HORZSIZE)
84szlMillimeters.cyGetDeviceCaps(Handle, VERTSIZE)
100szlMicrometers.cxGetDeviceCaps(Handle, HORZSIZE) * 1000
104szlMicrometers.cyGetDeviceCaps(Handle, VERTSIZE) * 1000
Die letzten zwei sind (als einzige Felder) in Delphi 2010 noch nicht definiert (wohl aber in 10.4).
nSize ist dennoch 108 und die Felder sind in der Windows-API-Dokumentation von Delphi 2010 drin.
Ein Nutzen ist mir nicht bekannt, der Korrektur-Algorithmus von mir schreibt sie somit auch nicht.

Rechner von Jannik: 3840x2048
Code:
HORZSIZE 320
HORZRES  3840
VERTSIZE 240
VERTRES  2048
Rechner von mir: 1920?x1080
Code:
HORZSIZE 677
HORZRES  1920
VERTSIZE 381
VERTRES  1080
RDP-Bug: Runde 2 "Bildschirmskalierung" (geht auch ohne RDP nicht)
Rechner von mir: 2560x1440 100%
Code:
HORZSIZE 527
HORZRES  2560
VERTSIZE
VERTRES  1440
Rechner von mir: 2560x1440 125%
Code:
HORZSIZE 527
HORZRES  2048
VERTSIZE 296
VERTRES  1152
In der Datei sind aber HORZRES an 72 und VERTRES an 76 die Werte von 100%.
Janni
2005 PE, 2009 PA, XE2 PA

Geändert von Redeemer ( 2. Mär 2022 um 22:00 Uhr)
  Mit Zitat antworten Zitat