AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Sonstige Fragen zu Delphi RichEdit: Seiten-Umbruch erkennen/auswerten/drucken
Thema durchsuchen
Ansicht
Themen-Optionen

RichEdit: Seiten-Umbruch erkennen/auswerten/drucken

Ein Thema von TERWI · begonnen am 8. Dez 2017 · letzter Beitrag vom 18. Dez 2017
Antwort Antwort
Benutzerbild von TERWI
TERWI

Registriert seit: 29. Mär 2008
Ort: D-49626
381 Beiträge
 
Delphi 11 Alexandria
 
#1

AW: RichEdit: Seiten-Umbruch erkennen/auswerten/drucken

  Alt 12. Dez 2017, 12:12
... es geht noch einfacher, besser und universeller.
Ein'\page' oder '\pagebb' steht immer irgendwo mit anderen Steuerzeichen vor dem Text, der auf die nächste Seite soll.
Ich ersetze nun einfach diese Steuerreichen mit einem Text (hier: '|NEWPAGE|'), der auch anschließend im RTF lesbar am Anfang der Zeike steht.
Anschließend loope ich alle Zeilen im Richedit und prüfe auf eben diesen Text.
Sofern vorhanden, wird ein Seitenwechsel vermerkt und der Text einfach wieder aus der Richedit-Zeile gelöscht.
Das funktioniert 1A - egal ob der Text plain oder irgendwie Formatiert ist, Umlaute oder Sonderzeichen hat.
Delphi-Quellcode:
///-----------------------------------------------------------------------------
procedure TForm1.Search4Pages(Datei : string);
var
  SS : TStringStream;
  MS : TMemoryStream;
  RTFplain : ANSIString; // shoulb be NOT a normal (wide) String !!!
  i, LineFrom : integer;
begin
  SS := TStringStream.Create('');
  MS := TMemoryStream.Create;
  ClearPagelList;
  Memo.Clear;
  RE_SRC.Clear;
  RE_PAGE.Clear;
  // ... load the file (or stream)
  SS.LoadFromFile(Datei);
  SetLength(RTFplain, SS.Size);
  SS.Read(RTFplain[1], SS.Size); // or SS.ReadBuffer !?
  RTFplain := StringReplace(RTFplain, '\pagebb', ' |NEWPAGE|', [rfReplaceAll]);
  RTFplain := StringReplace(RTFplain, '\page', ' |NEWPAGE|', [rfReplaceAll]);
  MS.Position := 0;
  MS.WriteBuffer(RTFplain[1],Length(RTFplain));
  MS.Position := 0;
  RE_SRC.Lines.LoadFromStream(MS);
  SS.Free; // no longer necessary
  MS.Free; // no longer necessary
  // ... now loop through (displayed) lines, recognize FormFeed and delete PlaceHolder
  LineFrom := 0;
  for i := 0 to RE_SRC.Lines.Count - 1 do
  begin
    RE_SRC.Lines.BeginUpdate;
    if Pos('|NEWPAGE|', RE_SRC.Lines[i]) > 0 then
    begin
      RE_SRC.Lines[i] := StringReplace(RE_SRC.Lines[i], '|NEWPAGE|', '', []); // [rfReplaceAll]);
      AddPage2List(LineFrom, i - 1); // Add Page to list:
      LineFrom := i; // LineTo + 1;
    end;
    RE_SRC.Lines.EndUpdate;
  end;
  AddPage2List(LineFrom, RE_SRC.Lines.Count - 1);
end;
Die procedure für die zu druckenden Seiten hab ich nun auch korrigiert/ergänzt:
Delphi-Quellcode:
// -----------------------------------------------------------------------------
// PageFrom: Min = 1, Max = FPageList.Count
// PageTo: Min = PageFrom, Max = FPageList.Count
procedure TForm1.PrepRTFtoPrint(PageFrom, PageTo : integer; All : boolean);
var
  i, ii, LF, LT : integer;
  MS : TMemoryStream;
begin
  if (FPageList.Count < 1) then exit; // no page to print
  if All then // print all pages ...
  begin
    PageFrom := 1;
    PageTo := FPageList.Count;
  end;
  if (PageFrom < 0) then exit; // range to low
  if (PageFrom > FPageList.Count) then exit; // range to high
  if (PageTo < PageFrom) then exit; // range to low
  if (PageTo > FPageList.Count) then exit; // range to high
  // ... print valid pages
  for i := PageFrom to PageTo do
  begin
    LF := PRTFPageData(FPageList[i - 1]).LFrom;
    LT := PRTFPageData(FPageList[i - 1]).LTo;
    Memo.Lines.Add('... Printing page ' + inttostr(i) +
                   ' - Line ' + inttostr(LF) +
                   ' to ' + inttostr(LT));
    // 1st: copy RE_SRC to RE_PAGE
    MS := TMemoryStream.Create;
    try
      RE_SRC.Lines.SaveToStream(MS);
      MS.Position := 0;
      RE_PAGE.Lines.LoadFromStream(MS) ;
    finally
      MS.Free;
    end;
    // 2nd: Loop through all RE_SRC-lines and delete unwanted lines
    // !!! walking BACKWARDS through list of lines !!!
    for ii := RE_PAGE.Lines.Count - 1 downto 0 do
    begin
      if (ii < LF) then RE_PAGE.Lines.Delete(ii);
      if (ii > LT) then RE_PAGE.Lines.Delete(ii);
    end;
    // 3rd: call your favourite RTF-printing-service with RE_PAGE....
  end;
end;
  Mit Zitat antworten Zitat
Benutzerbild von TERWI
TERWI

Registriert seit: 29. Mär 2008
Ort: D-49626
381 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: RichEdit: Seiten-Umbruch erkennen/auswerten/drucken

  Alt 17. Dez 2017, 14:53
Ein Update:

Das mit den Zeilen löschen war ja schon recht praktikabel, aber wenn mann im (Source-) RE vergisst, das WordWrap abzustellen, geht das richtig in Hose.
Neue und bessere Idee:
Ich lösche nun im RE.Text betreffende Textstellen.
Hier mal ein Auszug aus meinem Test-Prog in Verbindung mit TPrintPreview:
Delphi-Quellcode:
// -----------------------------------------------------------------------------
// GLOBAL: - FFrameRect
// - RE_PAGE
// - RE_SRC
procedure TMainForm.RenderRichEdit(Files : TStringList);

  procedure RenderPage();
  var
    TextRect: TRect;
    Offset: Integer;
  begin
    Offset := 0;
    while (Offset >= 0) and
          (PrintPreview.PaintRichText(FFrameRect, RE_Page, 1, @Offset) <> 0) do
    begin
      Application.ProcessMessages;
      if (Offset >= 0) then PrintPreview.NewPage;
    end;
  end;

var
  SS : TStringStream;
  MS : TMemoryStream;
  RTFplain : ANSIString; // should be NOT a wide string !!!
  i, l, p : integer;
begin
  PrintPreview.BeginDoc;
  PrintPreview.Units := mmHiMetric; // All units are in 1/100th of millimeter
  CalcFrame;
  // ... loop the files
  for I := 1 to Files.Count do
  begin
    SS := TStringStream.Create('');
    MS := TMemoryStream.Create;
    RE_SRC.Clear;
    RE_PAGE.Clear;
    // ... load file to stream and copy to ANSI-STRING !!! (NOT WIDE)
    SS.LoadFromFile(Files[i-1]);
    SetLength(RTFplain, SS.Size);
    SS.Read(RTFplain[1], SS.Size);
    // - replace \page(bb) with ' |NEWPAGE|' as readable text for FORMFEED
    RTFplain := StringReplace(RTFplain, '\pagebb', ' |NEWPAGE|', [rfReplaceAll]);
// RTFplain := StringReplace(RTFplain, '\page', ' |NEWPAGE|', [rfReplaceAll]);
    MS.Position := 0;
    MS.WriteBuffer(RTFplain[1],Length(RTFplain)); // load back to stream
    MS.Position := 0;
    RE_SRC.Lines.LoadFromStream(MS); // load back to RTF-Source
    SS.Free;
    // ... now look for the new placeHolder(s)
    repeat
      MS.Clear;
      // ... copy source-RTF to print-RTF | RE_PAGE := RE_SRC DOESN'T WORK !!!
      RE_SRC.Lines.SaveToStream(MS);
      MS.Position := 0;
      RE_PAGE.Lines.LoadFromStream(MS) ;
      // ... search placeholder
      l := RE_SRC.GetTextLen;
      p := RE_SRC.FindText('|NEWPAGE|', 0, l, [stMatchCase]);
      if (p > -1) then
      begin // ... found it
        RE_PAGE.Lines.BeginUpdate; // DELETE text after placeholder in print
        RE_PAGE.SelSTart := p;
        RE_PAGE.SelLength := l - p;
        RE_PAGE.SetSelText('');
        RE_PAGE.Lines.EndUpdate;
        RE_SRC.Lines.BeginUpdate; // DELETE text upto/incl. placeholder in source
        RE_SRC.SelSTart := 0;
        RE_SRC.SelLength := p + 9;
        RE_SRC.SetSelText('');
        RE_SRC.Lines.EndUpdate;
        RenderPage; //RenderRichEdit; // Render print-RTF
        PrintPreview.NewPage; // DON'T FORGET !
      end;
    until (p < 0);
    MS.Free;
    RenderPage; //RenderRichEdit; // Render rest of / complete print-RTF
  end;
  PrintPreview.EndDoc;
end;
Wie das mit der Compo TPrintPreview sauber mit Multi-File funzt, kommt in einem neuen Fred.
  Mit Zitat antworten Zitat
Benutzerbild von TERWI
TERWI

Registriert seit: 29. Mär 2008
Ort: D-49626
381 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: RichEdit: Seiten-Umbruch erkennen/auswerten/drucken

  Alt 18. Dez 2017, 10:44
.... und noch ein UpDate:

Gestern beim herumspielen mit TPrintPreview (arbeitet mit TCustomRichEdit) ist mir plötzlich aufgefallen, das RichEdit offensichtlich doch einen Seitenumbruch beherscht - allerdings nur via Control '\page' und NICHT per '\pagebb'.
Zur Erinnerung:
... ich wollte mit LibreOffice erstellte Seiten auch so wie generiert mit Seitenumbruch anzeigen/drucken.
LO baut allerdings in den Plaintext ein PageBreakBefore ein. Keine Ahnung ob MS-Office oder andere Text-Proggies das auch so machen, ich hab z.Zt. kein anderes.

Das vereinfacht die Sache natürlich nochmals. Man muss nun nach wie vor im Plaintext nach '\pagebb' suchen, braucht aber nichts einzubauen und wieder darauf zu testen o. ä., sondern einfach nur mit '\page' ersetzen.
Ich kam drauf, weil ich eine meiner Test-Dateien schon manuell daraufhin editiert hatte...
Delphi-Quellcode:
// -----------------------------------------------------------------------------
// GLOBAL: FFrameRect, RichEdit
procedure TMainForm.RenderRichEdit(Files : TStringList);
var
  SS : TStringStream;
  RTFplain : ANSIString; // fails if wide string !!!
  i : integer;
  Offset : Integer;
begin
  CalcFrame; // set print-rectangle with given borders
  PrintPreview.Units := mmHiMetric; // All units are in 1/100th of millimeter
  PrintPreview.BeginDoc;
  // ... loop the files
  for I := 1 to Files.Count do
  begin
    if (i > 1) then
      PrintPreview.NewPage; // new file -> new page
    // ----- check for PrintPageBefore
    SS := TStringStream.Create('');
    // ... load file to stream and copy to ANSI-STRING !!! (NOT WIDE)
    SS.LoadFromFile(Files[i-1]);
    SetLength(RTFplain, SS.Size);
    SS.Read(RTFplain[1], SS.Size);
    // ... replace \pagebb with '\page'
    RTFplain := StringReplace(RTFplain, '\pagebb', '\page', [rfReplaceAll]);
    SS.Clear;
    SS.WriteBuffer(RTFplain[1],Length(RTFplain)); // load plain back to stream
    SS.Position := 0;
    RichEdit.Lines.LoadFromStream(SS); // load stream to RTF
    SS.Free;
    // -----
    // render RTF (similar as in org. TPrintPreview 'RichTextDemo')
    Offset := 0;
    while (Offset >= 0) and
          (PrintPreview.PaintRichText(FFrameRect, RichEdit, 1, @Offset) <> 0) do
    begin
      Application.ProcessMessages;
      if (Offset >= 0) then
        PrintPreview.NewPage;
    end;
  end;
  PrintPreview.EndDoc;
end;
Es fehlte übrigends noch der 'Seitenvorschub', wenn mehr als eine Datei aus der FileList gedruckt wurde.

Geändert von TERWI (18. Dez 2017 um 16:07 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:44 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz