Schrift beim Ausdruck zu klein bzw. übereinandergedruckt

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
and4more
Beiträge: 207
Registriert: Do 15. Nov 2012, 19:13
OS, Lazarus, FPC: Windows 10, Manjaro Linux, Lazarus 1.6.4 (32/64 Bit)
CPU-Target: 32 Bit / 64 Bit

Schrift beim Ausdruck zu klein bzw. übereinandergedruckt

Beitrag von and4more »

Liebes Forum, habe leider ein etwas seltsames Problem. Ich nutze Lazarus 1.0.2 unter Windows 7 (64 Bit), Linux (64 Bit) und Wine (32 Bit). Folgender Code führt unter Windows 7 und Wine zwar zu einer formatgerechten Druckausgabe allerdings mit einer Schriftgröße, die eher an eine Flohspur erinnert (durch Änderung der Fontgröße aber nicht korrigierbar), außerdem werden die Tabulatoren als Sonderzeichen ausgedruckt und nicht als Abstand. Unter Linux ist zwar die Schriftgröße korrekt doch wird nur eine Höhe von 6 Zeilen ausgedruckt und dafür mehrere Zeilen übereinander, so dass die Schrift nicht mehr erkennbar ist.
Code:

Code: Alles auswählen

  ....
  MemBewertung.Font.Height:=15;
  Application.Initialize;
  DruckDlg:=TPrintDialog.Create(NIL);
  ResultsForm.Hide;
  try
    DruckDlg.MinPage:=1;
    DruckDlg.MaxPage:=1;
    if DruckDlg.Execute then begin
      Printer.PaperSize.PaperName:='A4';
      Druckbereich:=Printer.PaperSize.PaperRect.WorkRect;
      Druckbereich.Left:=300;
      Druckbereich.Top:=200;
      Printer.Canvas.Font.Name:='Arial';
      Printer.Canvas.Font.Size:=15;
//      mult:=Canvas.Font.Size*30;
 
      //Druckvorgang starten
      Printer.BeginDoc;
      Printer.Canvas.FrameRect(Rect(Druckbereich.Left,Druckbereich.Top,    //dies wurde im Gegensatz zum Buch ergänzt, da sonst alles in einer Linie gedruckt wird
        (Canvas.Width-200),(Canvas.Height-200)));
      for i:=1 to MemBewertung.Lines.Count do
        Printer.Canvas.TextOut(Druckbereich.Left,
          Druckbereich.Top+i*2*Canvas.TextHeight(MemBewertung.Lines.Strings[i]),
          MemBewertung.Lines.Strings[i]);
 
      //Alternative
{      for i:=1 to InhaltListe.Count do
         Printer.Canvas.TextOut(Druckbereich.Left,Druckbereich.Top+i*mult,
          InhaltListe[i-1]);}        //funktioniert auch nicht
 
        //Druckvorgang beenden
      Printer.EndDoc;
    end;
  finally
//    ResultsForm.MemBewertung.Font.Size:=15; //Kein Effekt bzgl. Fontgröße b. Ausdruck
    ResultsForm.Show;
    //Speicher freigeben
    DruckDlg.Free;
  end;
Der Code entspricht weitgehend den Empfehlungen aus dem *Lazarusbuch" funktioniert aber wie gesagt trotzdem nicht korrekt. Habe auch schon verschiedene Drucker ausprobiert, immer das gleiche Ergebnis. Auch "googlen" brachte leider keine brauchbaren Informationen. Hat niemand das gleiche Problem? Kennt jemand eine Lösung?
Ich hoffe, die beigefügten Informationen sind ausreichend.
Schon mal vielen Dank für die Mühe
Zuletzt geändert von Lori am Fr 16. Nov 2012, 16:26, insgesamt 1-mal geändert.
Grund: Highlighter
Lazarus 1.6.4 32-Bit + 64-Bit, Windows 10 64-Bit, Manjaro Linux 64-Bit

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2825
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Schrift beim Ausdruck zu klein bzw. übereinandergedruckt

Beitrag von m.fuchs »

Ich kann das Problem reproduzieren.
Lass dir mal irgendwo den Inhalt von

Code: Alles auswählen

Printer.Canvas.Font.PixelsPerInch
ausgeben. Bei mir war unter Windows ein Wert von 96 eingetragen.
Allerdings habe ich einen 600 dpi Drucker. Mit

Code: Alles auswählen

Printer.Canvas.Font.PixelsPerInch := 600;
stimmt dann auch die Schriftgröße.
Unter Linux ist sie bei dir vermutlich bereits richtig.

Den verschobenen Ausdruck habe ich dann auch unter Windows. Das liegt daran, dass

Code: Alles auswählen

Canvas.TextHeight(MemBewertung.Lines.Strings[i])
seltsamerweise 13 zurückliefert. Das finde ich ein wenig klein. Woran das liegt? Leider keine Ahnung.

BTW: Du benutzt

Code: Alles auswählen

for i:=1 to MemBewertung.Lines.Count do
, dann solltest du später per

Code: Alles auswählen

MemBewertung.Lines.Strings[i-1]
auf dein Memo zugreifen. Sonst verpasst du ja die erste Zeile.

BTW2: Bitte benutze das nächste Mal den Highlighter, wenn du hieer Code reinstellst. Das liest sich dann auch besser.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2825
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Schrift beim Ausdruck zu klein bzw. übereinandergedruckt

Beitrag von m.fuchs »

Ganz vergessen:
and4more hat geschrieben:außerdem werden die Tabulatoren als Sonderzeichen ausgedruckt und nicht als Abstand
Das könntest du wie folgt lösen:

Code: Alles auswählen

p := Classes.Rect(Druckbereich.Left, i * 2 * 100, 5000, i * 2 * 100  + 100);
DrawText(Printer.Canvas.Handle, PChar(MemBewertung.Lines.Strings[i-1]), -1, p, DT_SINGLELINE OR DT_LEFT OR DT_TOP OR DT_EXPANDTABS OR DT_NOCLIP );
Allerdings wird dafür die Unit Windows benötigt. Keine Ahnung ob das dann unter Linux läuft.
p ist übrigens vom Typ TRect, die Werte dafür musst du sicherlich noch anpassen
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

Heinrich Wolf
Beiträge: 323
Registriert: Di 12. Apr 2011, 13:21
OS, Lazarus, FPC: WinXP + VMWare Player mit Fedora14, L 1.1, FPC 2.7.1
CPU-Target: 1core 1,8GHz 32Bit
Wohnort: Fürth
Kontaktdaten:

Re: Schrift beim Ausdruck zu klein bzw. übereinandergedruckt

Beitrag von Heinrich Wolf »

Du vermischt in Deinem Code Canvas mit Printer.Canvas . Die haben unterschiedliche DPI Werte!

volker
Beiträge: 25
Registriert: Mi 14. Nov 2012, 14:36
OS, Lazarus, FPC: Linux Kernel 6.6 (L 3.0 FPC 3.2.2)
CPU-Target: x86_64 Linux gtk2

Re: Schrift beim Ausdruck zu klein bzw. übereinandergedruckt

Beitrag von volker »

Ich weiß nicht ob es damit was zu tun hat, nur so eine Idee, denn ich hatte in einer älteren Lazarus/FPC Version ähnliche Probleme:
Unter Linux geht das ganze Drucken über Postscript, die arbeiten intern mit einer ganz groben Auflösung (72 dpi ??), damals konnte man nur Integer setzen und alles ging "Treppenweise". Man konnte weder vernünftig skalieren noch positionieren. Dann wurde das in FPC geändert, die grobe Auflösung bleibt (!) aber man kann jetzt Fließkommazahlen für Skalierung und Positionierung auf die Printer.Canvas nehmen.

and4more
Beiträge: 207
Registriert: Do 15. Nov 2012, 19:13
OS, Lazarus, FPC: Windows 10, Manjaro Linux, Lazarus 1.6.4 (32/64 Bit)
CPU-Target: 32 Bit / 64 Bit

Re: Schrift beim Ausdruck zu klein bzw. übereinandergedruckt

Beitrag von and4more »

@Michael
Danke, dein Vorschlag hat's gebracht, es lag an den DPI, die waren bei mir 96. Nach der entsprechenden Änderung und kleineren Anpassungen sieht das Druckbild fast so aus wie ich's wollte. Leider hat der Tipp mit der 'Windows' Unit nicht den gewünschten Erfolg gezeigt. Umlaute sind nun Sonderzeichen und der Druck begann in der rechten Hälfte des Blattes, oberer 1/3-Punkt und nur eine Zeile und zwar die letzte. Ich gebe noch mal meinen Code an und hoffe das mit dem highlighten klappt jetzt, sorry:

Code: Alles auswählen

 
      //Druckvorgang starten
      Printer.BeginDoc;
      Printer.Canvas.FrameRect(Rect(Druckbereich.Left,Druckbereich.Top,
        (Canvas.Width-200),(Canvas.Height-200)));
      for i:=1 to MemBewertung.Lines.Count do
{
        Printer.Canvas.TextOut(Druckbereich.Left,
          Druckbereich.Top+i*10*Canvas.TextHeight(MemBewertung.Lines.Strings[i-1]),
          MemBewertung.Lines.Strings[i-1]);
}
          p := Classes.Rect(Druckbereich.Left, i * 2 * 100, 5000, i * 2 * 100  + 100);
          DrawText(Printer.Canvas.Handle, PChar(MemBewertung.Lines.Strings[i-1]),
            -1, p,DT_SINGLELINE OR DT_LEFT OR DT_TOP OR DT_EXPANDTABS OR DT_NOCLIP );
 
        //Druckvorgang beenden
      Printer.EndDoc;
 
Ich hab deinen Code wie oben zu sehen platziert, bin absoluter Neuling im programmieren, ich hoffe es ist so korrekt.
Lazarus 1.6.4 32-Bit + 64-Bit, Windows 10 64-Bit, Manjaro Linux 64-Bit

Benutzeravatar
theo
Beiträge: 10927
Registriert: Mo 11. Sep 2006, 19:01

Re: Schrift beim Ausdruck zu klein bzw. übereinandergedruckt

Beitrag von theo »

Da braucht man keinen extra Windows-Code, dafür gibt es die plattformübergreifende Funktion Canvas.TextRect mit TTextStyle

http://lazarus-ccr.sourceforge.net/docs ... trect.html
http://lazarus-ccr.sourceforge.net/docs ... style.html

EDIT: Theoretisch. Leider sehe ich erst jetzt, dass das mit den Tabs im Moment nicht unterstützt ist.
ExpandTabs: boolean; currently ignored
Dann ersetzt du die Tabs entweder "von Hand" mit StringReplace und rfReplaceAll http://lazarus-ccr.sourceforge.net/docs ... place.html oder du benützt die Windows Funktion
DrawTextW und übergibst einen WideString mit UTF8Decode(MemBewertung.Lines.Strings[i-1])

and4more
Beiträge: 207
Registriert: Do 15. Nov 2012, 19:13
OS, Lazarus, FPC: Windows 10, Manjaro Linux, Lazarus 1.6.4 (32/64 Bit)
CPU-Target: 32 Bit / 64 Bit

Re: Schrift beim Ausdruck zu klein bzw. übereinandergedruckt

Beitrag von and4more »

@Heinrich
Der Einwand ist korrekt. Wenn ich allerdings Printer.Canvas... nehme, muss der Multiplikator für die Zeilenhöhe eine Komma- oder Punktnotatation im Sinne von 1.3 oder 1,3 zeigen. Irgendwie führt das beim Kompilieren zu einem Fehler. Außerdem gibt es da meines Erachtens noch einen Bug in Lazarus, was die plattformübergreifende Kodierung anbelangt. Datentypen vom Typ 'Float' oder 'Double' brauchen unter Windows ein Komma, unter Linux aber einen Punkt! Für mich war's schlussendlich einfacher 'Canvas' ohne 'Printer.' zu nehmen, da hierbei mit vollen Zahlen gearbeitet werden kann. Aber besten Dank für den Einwand.
Lazarus 1.6.4 32-Bit + 64-Bit, Windows 10 64-Bit, Manjaro Linux 64-Bit

and4more
Beiträge: 207
Registriert: Do 15. Nov 2012, 19:13
OS, Lazarus, FPC: Windows 10, Manjaro Linux, Lazarus 1.6.4 (32/64 Bit)
CPU-Target: 32 Bit / 64 Bit

Re: Schrift beim Ausdruck zu klein bzw. übereinandergedruckt

Beitrag von and4more »

@theo
Danke für den Tipp. Allerdings möchte ich die Ausgabe formatiert, sprich ordentlich haben und wenn ich den Tabulator durch Leerzeichen ersetze haut das wegen der etwas unterschiedlichen Abstände nicht so richtig hin. Es müsste also für jede Zeile eine individuell angepasste Ausgabe erfolgen. Das halte ich für programmiertechnisch unangemessen aufwendig.
Nachtrag: Das Programm sollte aber auch unter Linux laufen, wie ist es denn da mit den Windows spezifischen Funktionen?
Lazarus 1.6.4 32-Bit + 64-Bit, Windows 10 64-Bit, Manjaro Linux 64-Bit

Benutzeravatar
theo
Beiträge: 10927
Registriert: Mo 11. Sep 2006, 19:01

Re: Schrift beim Ausdruck zu klein bzw. übereinandergedruckt

Beitrag von theo »

and4more hat geschrieben: Nachtrag: Das Programm sollte aber auch unter Linux laufen, wie ist es denn da mit den Windows spezifischen Funktionen?
Wie du erahnen kannst, solltest du dazu die oben genannten plattformunabhängigen Funktionen verwenden.

Die Tabs nach deinen Vorstellungen wirst du aber wohl selber implementieren müssen.

soerensen3
Beiträge: 104
Registriert: Fr 22. Jun 2012, 01:51
OS, Lazarus, FPC: Fedora-Linux 23 (Korora) Lazarus 1.6 FPC 3.0
CPU-Target: 64Bit
Wohnort: Bonn

Re: Schrift beim Ausdruck zu klein bzw. übereinandergedruckt

Beitrag von soerensen3 »

Und wenn du die Strings an den Tabs trennst und dann sowas wie ein Gitter benutzt, an denen du dann die x-Koordinaten der TabStrings ausrichtest?

Also z.b. alle 30 Pixel oder so

Code: Alles auswählen

x:= x - x mod 30; //immer abrunden
//oder
x:= x div 30 * 30; //auf und abrunden
Es gibt da aber auch bestimmt noch bessere funktionen für.

Das hätte den Effekt, das zumindest alles gleich ausgerichtet wäre. Und es ist nicht so aufwendig, du kannst ja einfach eine eigene TextOut Funktion schreiben.
Mit TextWidth bekommst du immer die Breite eines Strings in Pixeln. Von da aus kannst du dann eine bestimmte Zahl an Pixeln für dein Tab drauf rechnen und dann runden.
Das machst du solange bis Pos kein Tab mehr findet.

and4more
Beiträge: 207
Registriert: Do 15. Nov 2012, 19:13
OS, Lazarus, FPC: Windows 10, Manjaro Linux, Lazarus 1.6.4 (32/64 Bit)
CPU-Target: 32 Bit / 64 Bit

Re: Schrift beim Ausdruck zu klein bzw. übereinandergedruckt

Beitrag von and4more »

[GELÖST]
Einen lieben Dank an Alle die sich so viel Mühe gemacht haben und für die ganzen super Vorschläge.
Leider kann ich mich erst jetzt wieder melden (Viel Arbeit und ganz viel Try and Error). Aber schließlich habe ich doch irgendwie eine Lösung gefunden:

Code: Alles auswählen

 
      ...
      if (Printer.Canvas.Font.PixelsPerInch<300) then
        Printer.Canvas.Font.PixelsPerInch:=600;
      Printer.PaperSize.PaperName:='A4';
      Druckbereich:=Printer.PaperSize.PaperRect.WorkRect;
      Druckbereich.Left:=300;
      Druckbereich.Top:=200;
      Printer.Canvas.Font.Name:='Arial';
      Printer.Canvas.Font.Size:=10;
      Printer.Canvas.FrameRect(Rect(Druckbereich.Left,Druckbereich.Top,
        (Printer.Canvas.Width-200),(Printer.Canvas.Height-200)));
      TextStil:=Printer.Canvas.TextStyle;
      TextStil.Wordbreak:=True;
      TextStil.Singleline:=False;
      TextStil.ExpandTabs:=True;
      for i:=1 to MemBewertung.Lines.Count do
        Printer.Canvas.TextRect(Druckbereich,Druckbereich.Left,Druckbereich.Top+i*
          5*Canvas.TextHeight(MemBewertung.Lines.Strings[i-1]),
          MemBewertung.Lines.Strings[i-1],TextStil);
        Printer.Canvas.TextOut(Druckbereich.Left,Druckbereich.Top+i*10*
          Canvas.TextHeight(MemBewertung.Lines.Strings[i-1]),
          MemBewertung.Lines.Strings[i-1]);
     ... 
 
... und das funktioniert ganz gut. Wenn jemand noch Codeverbesserungen/-optimierungen hat wäre ich natürlich hoch erfreut und dankbar.

@soerensen
..das ist eine super Idee. Werde ich mal bei Gelegenheit antesten. Danke
EDIT: Es wäre z. B. eine Möglichkeit sich die Länge einer Zeile ausgeben zu lassen und den zweiten Teil des Ergebnisses (das nach dem Tabulator) nach Löschen der Tabs in
"'Länge der Zeile' - x(Pixel)" beginnen zu lassen.
Lazarus 1.6.4 32-Bit + 64-Bit, Windows 10 64-Bit, Manjaro Linux 64-Bit

and4more
Beiträge: 207
Registriert: Do 15. Nov 2012, 19:13
OS, Lazarus, FPC: Windows 10, Manjaro Linux, Lazarus 1.6.4 (32/64 Bit)
CPU-Target: 32 Bit / 64 Bit

Re: Schrift beim Ausdruck zu klein bzw. übereinandergedruckt

Beitrag von and4more »

[GELÖST]
...inspiriert durch den Hinweis von soerensen und im Hinblick auf ein Drucker- und formatunabhäniges Schriftbild beim Ausdruck habe ich jetzt folgendes gemacht:
Erst die Tabs auf eines reduzieren:

Code: Alles auswählen

 
const tab = #9;
      ...
      ...
function TResultsForm.Entferne_Tabs(s:string):string;
var
  a, b, len: integer;
 
begin
  result:='';
  b:=0;
  a:=1;
  len:=Length(s);
  SetLength(result, Length(s));
  While a<len+1 do begin
    if (s[a]=tab) and (a>1) and (s[a-1]<>tab) then begin
      b:=b+1;
      result[b]:=s[a];
    end
    else if s[a]<>tab then begin
      b:=b+1;
      result[b]:=s[a];
    end;
    a:=a+1;
  end;
  SetLength(result, b);
end;
 
 
...dann den verbleibenden Tab als "Trennzeichen" nutzen um sie Resultate während des Drucks zu formatieren:

Code: Alles auswählen

 
       ...
      TextStil.Wordbreak:=True;
      TextStil.Singleline:=False;
      TextStil.ExpandTabs:=True;
      for i:=1 to MemBewertung.Lines.Count do
        if (MemBewertung.Lines.Strings[i-1]<>'') then begin
          str_Tmp:=Entferne_Tabs(MemBewertung.Lines.Strings[i-1]);
          i_StrPos:=pos(tab,str_Tmp);
          if (i_StrPos<>0) then begin
            str_1:=copy(str_Tmp,1,i_StrPos-1);
            str_2:=copy(str_Tmp,i_StrPos+1,Length(str_Tmp));
            Printer.Canvas.TextRect(Druckbereich,Druckbereich.Left,Druckbereich.Top+i*
              4*Canvas.TextHeight(MemBewertung.Lines.Strings[i-1]),str_1,TextStil);
            Printer.Canvas.TextOut(Druckbereich.Left,Druckbereich.Top+i*4*
              Canvas.TextHeight(MemBewertung.Lines.Strings[i-1]),str_1);
            Printer.Canvas.TextOut(Druckbereich.Left+900,Druckbereich.Top+i*4*
              Canvas.TextHeight(MemBewertung.Lines.Strings[i-1]),str_2);
            end
            else begin
            Printer.Canvas.TextRect(Druckbereich,Druckbereich.Left,Druckbereich.Top+i*
              4*Canvas.TextHeight(MemBewertung.Lines.Strings[i-1]),
              MemBewertung.Lines.Strings[i-1],TextStil);
            Printer.Canvas.TextOut(Druckbereich.Left,Druckbereich.Top+i*4*
              Canvas.TextHeight(MemBewertung.Lines.Strings[i-1]),
              MemBewertung.Lines.Strings[i-1]);
            end;
          end;
       ...
 
Ich hab's hier nochmal reingegeben vielleicht findet's der Eine oder Andere hilfreich. Danke noch mal an Alle
Lazarus 1.6.4 32-Bit + 64-Bit, Windows 10 64-Bit, Manjaro Linux 64-Bit

Antworten