Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Bitmap aus RTF erzeugen (https://www.delphipraxis.net/193129-bitmap-aus-rtf-erzeugen.html)

Hobbycoder 22. Jun 2017 18:34

Bitmap aus RTF erzeugen
 
Hi,

ich möchte aus einem RTF-Text eine Bitmap mit vorgegebenen Maßen erzeugen. Der RTF-Text liegt als MemoryStream in einem Object.
Mein erster Gedanke war, mir in einer Procedure im Object temporär ein TRichEdit zu erzeugen und dann (wie hier ) mir daraus eine das ganze in ein Bitmap zu kopieren.
Delphi-Quellcode:
var
   MyRTF: TRichEdit;
begin
   self.FArbeitenBitmap.Height:=Height;
   self.FArbeitenBitmap.Width:=Width;
   MyRTF:=TRichEdit.Create(nil);
   MyRTF.Width:=Width;
   MyRTF.Height:=Height;
   Self.FArbeiten.Position:=0;
   MyRTF.Lines.LoadFromStream(self.FArbeiten); // <---Hier knallt's dann mal

   with Self.FArbeitenBitmap.Canvas do
   begin
     Lock;
     try
       myRTF.Perform(WM_PRINT, Handle, PRF_CLIENT);
       //you can trying to change PRF_CLIENT with
       //PRF_CHILDREN or PRF_CLIENT or PRF_NONCLIENT or PRF_ERASEBKGND
       //or combine them. See what happen...
     finally
       Unlock
     end;
   end;
Allerdings kann ich mir den Stream nicht in das RichEdit laden, weil es kein Parent hat. Parent hab ich auch nicht, weil es ja nur ein Object ist. Jetzt dachte ich mir, ich könnte ja mittels CreateWnd sowas wie ein unsichtbares Fenster erzeugen, und das Richedit damit zufrieden stellen.
Wäre das so denkbar? Wenn ja, wie macht das das? Wenn nein, wie könnte man das besser machen?

DeddyH 22. Jun 2017 19:55

AW: Bitmap aus RTF erzeugen
 
Delphi-Quellcode:
MyRTF := TRichEdit.CreateParented(HWND_MESSAGE);
sollte eigentlich funktionieren.

Hobbycoder 23. Jun 2017 08:06

AW: Bitmap aus RTF erzeugen
 
Danke, das löst schon mal der erste Problem.

Leider bekomme ich so
Delphi-Quellcode:
var
  MyRTF: TRichEdit;
  img: HDC;
begin
   self.FArbeitenBitmap.Height:=Height;
   self.FArbeitenBitmap.Width:=Width;
   MyRTF:=TRichEdit.CreateParented(HWND_MESSAGE);
   MyRTF.Width:=Width;
   MyRTF.Height:=Height;
   Self.FArbeiten.Position:=0;
   MyRTF.Lines.LoadFromStream(self.FArbeiten);

   Self.FArbeitenBitmap.Canvas.Lock;
   try
     myRTF.Perform(WM_PRINT, Self.FArbeitenBitmap.Canvas.Handle, PRF_CLIENT);
     //you can trying to change PRF_CLIENT with
     //PRF_CHILDREN or PRF_CLIENT or PRF_NONCLIENT or PRF_ERASEBKGND
     //or combine them. See what happen...
   finally
     Self.FArbeitenBitmap.Canvas.Unlock
   end;
nur eine weiße Bitmap zurück.

Dann habe ich es noch mal so
Delphi-Quellcode:
var
  MyRTF: TRichEdit;
  img: HDC;
begin
   self.FArbeitenBitmap.Height:=Height;
   self.FArbeitenBitmap.Width:=Width;
   MyRTF:=TRichEdit.CreateParented(HWND_MESSAGE);
   MyRTF.Width:=Width;
   MyRTF.Height:=Height;
   Self.FArbeiten.Position:=0;
   MyRTF.Lines.LoadFromStream(self.FArbeiten);

   img := GetDC(MyRTF.Handle);
   BitBlt(Self.FArbeitenBitmap.Canvas.Handle,
     0, 0, MyRTF.Width, MyRTF.Height,
     img, 0, 0,
     SRCCOPY
   );
versucht, bekomme aber eine schwarze Bitmap.
Im Stream ist aber definitiv das richtige drin, den wenn ich mir das in ein Richedit lade, dass auf der Form liegt, wird es korrekt angezeigt.

Hast du da auch noch einen Tipp? Geht das so, außerhalb einer Form, überhaupt?

nahpets 23. Jun 2017 09:29

AW: Bitmap aus RTF erzeugen
 
Mein Vorgehen wäre hier eher von der faulen und uneleganten Sorte:

Wenn zur Laufzeit ein TRichEdit erstellt wird und das braucht ein Formular, auf dem es liegt, dann wird das eben auch erzeugt, Visible := False, damit der Anwender da nicht genervt wird.

Musste mal was ähnliches mit 'nem TChart in 'ner ISAPI.DLL machen, hat problemlos funktioniert. Vom TChart wurde auch nur das damit erstellte Bitmap benötigt. Und 'ne ISAPI.DLL mit 'nem Formular ist eher äußerst ungewöhnlich bzw. eigentlich vollkommen unsinnig.

Hobbycoder 23. Jun 2017 11:44

AW: Bitmap aus RTF erzeugen
 
Liste der Anhänge anzeigen (Anzahl: 3)
Habe ich grad mal versucht...keine Änderung.

Folgende Code funktioniert auf dem Formular und liefert mir eine Bitmap siehe Anhang 1:
Delphi-Quellcode:
var
  img: HDC;
begin
   richedit1.Lines.LoadFromStream(t.Arbeiten);
   t.ArbeitenBitmap.Height:=richedit1.Height;
   t.ArbeitenBitmap.Width:=richedit1.Width;
   img := GetDC(richedit1.Handle);
   BitBlt(t.ArbeitenBitmap.Canvas.Handle,
     0, 0, richedit1.Width, richedit1.Height,
     img, 0, 0,
     SRCCOPY
   );
   t.ArbeitenBitmap.SaveToFile(ExtractFilePath(Application.ExeName)+'arbeiten.bmp');
Und folgender Code im Object funktioniert nicht und liefert mir eine Bitmap siehe Anhang 2:

Delphi-Quellcode:
var
  MyRTF: TRichEdit;
  frm: TForm;
  img: HDC;
begin
   self.FArbeitenBitmap.Height:=Height;
   self.FArbeitenBitmap.Width:=Width;
   frm:=TForm.Create(Application);
   try
     //MyRTF:=TRichEdit.CreateParented(HWND_MESSAGE);
     MyRTF:=TRichEdit.Create(frm);
     Try
     MyRTF.Parent:=frm;
     MyRTF.Width:=Height;
     MyRTF.Height:=Width;
     Self.FArbeiten.Position:=0;
     MyRTF.Lines.LoadFromStream(self.FArbeiten);
     img := GetDC(MyRTF.Handle);
     BitBlt(Self.FArbeitenBitmap.Canvas.Handle,
       0, 0, MyRTF.Width, MyRTF.Height,
       img, 0, 0,
       SRCCOPY
     );
     finally
      MyRTF.free;
     End;
   finally
     frm.free;
   end;
Sollte doch eigentlich gehen. Woran kann das liegen?

Man kann das zweite Bild unten leder nicht so richtig sehen, ist aber da. Ist halt komplett weiß ;-)
Das linke Bild ist Anhang 1 und das rechte ist Anhang 2.

nahpets 23. Jun 2017 12:03

AW: Bitmap aus RTF erzeugen
 
Kann gerade nicht testen, kein Delphi in der Nähe :-(

Gibt dem Formular bitte mal 'ne Höhe und Breite, die der des gewünschten Bitmaps plus Höhe von Caption, Border ... des Forms entspricht und mach' das Formular erstmal sichtbar, um so eine "quasioptische" Kontrolle zu haben, ob überhaupt was zu sehen ist.

Hobbycoder 23. Jun 2017 12:23

AW: Bitmap aus RTF erzeugen
 
Hab ich gemacht:
Delphi-Quellcode:
var
  MyRTF: TRichEdit;
  frm: TForm;
  img: HDC;
begin
   self.FArbeitenBitmap.Height:=Height;
   self.FArbeitenBitmap.Width:=Width;
   frm:=TForm.Create(Application);
   try
     frm.Width:=Width+50;
     frm.Height:=Height+80;
     //MyRTF:=TRichEdit.CreateParented(HWND_MESSAGE);
     MyRTF:=TRichEdit.Create(frm);
     Try
     MyRTF.Left:=10;
     MyRTF.Top:=20;
     MyRTF.Parent:=frm;
     MyRTF.Width:=Width;
     MyRTF.Height:=Height;
     frm.Visible:=True;
     Self.FArbeiten.Position:=0;
     MyRTF.Lines.LoadFromStream(self.FArbeiten);
     img := GetDC(MyRTF.Handle);
     BitBlt(Self.FArbeitenBitmap.Canvas.Handle,
       0, 0, MyRTF.Width, MyRTF.Height,
       img, 0, 0,
       SRCCOPY
     );
     finally
      //MyRTF.free;
     End;
   finally
     //frm.free;
   end;
Formular erscheint. RichEdit ist drauf und Text im Richedit ist korrekt.
Bitmap ist aber trotzdem nur weiß. Erklären kann ich mir das nicht.

Hobbycoder 23. Jun 2017 12:29

AW: Bitmap aus RTF erzeugen
 
Hab aber grad heraus gefunden, dass, wenn ich nach dem LoadFromStream ein Applicaiton.processMessages mache, dann wird die Bitmap korrekt erstellt ;-)

Nur ein Application.ProcessMessages in einem Object......ist nicht wirklich eine gute Idee.

Wie kann ich dem RichEdit sage, dass es seinen geladenen Stream aufbereiten soll, damit ich danach das Bitmap erstellen kann?

[Edit] und wenn ich das Visible für die frm wieder rausnehme, ist meine Bitmap wieder schwarz :-( [/Edit]

nahpets 23. Jun 2017 12:36

AW: Bitmap aus RTF erzeugen
 
Blöd das Ganze:

Left des Formulars auf -1000 oder sowas setzen, dann kann es sichtbar bleiben, ist aber außerhalb des sichtbaren Bereiches.

Kann RichEdit Repaint, Update oder sowas?

Weiß, meine Vorschläge sind irgendwie wieder grenzwertig, zumindest mir gefallen sie nicht :-(

HolgerX 23. Jun 2017 12:37

AW: Bitmap aus RTF erzeugen
 
Hmm..

Hab mal nen bischen gegooglet und zusmmengeschripselt:
(Vergessen die Quellen zu notieren.. )


Delphi-Quellcode:
uses
  Windows, Classes, Graphics, ComCtrls, RichEdit;

procedure DrawRTF(DestDCHandle: HDC; const R: TRect;
  RichEdit: TRichEdit; PixelsPerInch: Integer);
var
  TwipsPerPixel: Integer;
  Range: TFormatRange;
begin
  TwipsPerPixel := 1440 div PixelsPerInch;

  Range.hDC := DestDCHandle; {DC handle}
  Range.hdcTarget := DestDCHandle; {ditto}
  {Convert the coordinates to twips (1/1440")}
  Range.rc.Left := R.Left * TwipsPerPixel;
  Range.rc.Top := R.Top * TwipsPerPixel;
  Range.rc.Right := R.Right * TwipsPerPixel;
  Range.rc.Bottom := R.Bottom * TwipsPerPixel;
  Range.rcPage := Range.rc;
  {Start at character zero}
  Range.chrg.cpMin := 0;
  {Display all Characters}
  Range.chrg.cpMax := -1; {RichEdit.GetTextLen;}
  {Free cached information}
  RichEdit.Perform(EM_FORMATRANGE, 0, 0);
  {First measure the text, to find out how high the format rectangle will be.
  The call sets fmtrange.rc.bottom to the actual height required, if all
  characters in the selected range will fit into a smaller rectangle}
  RichEdit.Perform(EM_FORMATRANGE, 0, DWord(@Range));
  {Now render the text}
  RichEdit.Perform(EM_FORMATRANGE, 1, DWord(@Range));
  {Free cached information}
  RichEdit.Perform(EM_FORMATRANGE, 0, 0);
end;


procedure RTFToBmp(MainWND : HWND;AFileName : string;var ABitMap : TBitmap);
var
  RichEdit: TRichEdit;
  DestDCHandle: HDC;
begin
  RichEdit :=TRichEdit.CreateParented(MainWND);
  try
    RichEdit.Width := GetDeviceCaps(GetDC(RichEdit.Handle),VERTRES);
    RichEdit.Height := GetDeviceCaps(GetDC(RichEdit.Handle),HORZRES);

    RichEdit.Visible := False;
    RichEdit.Lines.LoadFromFile(AFileName);

    ABitMap.width := RichEdit.Width;
    ABitMap.height := RichEdit.Height;
    DestDCHandle := ABitMap.Canvas.Handle;

    DrawRTF(DestDCHandle, Rect(0, 0, ABitMap.Width, ABitMap.Height), RichEdit, 96);
  finally
    RichEdit.Free;
  end;
end;

Aufruf:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  tmpBMP : TBitMap;
begin
  if OpenDialog1.Execute then begin
    tmpBMP := TBitMap.Create;
    try
      RTFToBmp(self.Handle,OpenDialog1.FileName,tmpBMP);
      Image1.Picture.Assign(tmpBMP);
    finally
      tmpBMP.Free;
    end;
  end;
end;
Damit erhalte ich ein Bitmap der ersten Seite des RTF Dokumentes...

(Getestet mit D6...)

Hobbycoder 23. Jun 2017 13:09

AW: Bitmap aus RTF erzeugen
 
Ich hab das mal so ziemlich unverändert übernommen. Ich erhalte leider nur eine leere, weiße Bitmap in (ca. A4-Größe)

Der einzige Unterschied ist, dass ich die Bitmap bereit in meinem Objekt habe, und demnach nicht übergeben muss, und dass ich das Richedit aus einem MemoryStream lade.

HolgerX 23. Jun 2017 15:12

AW: Bitmap aus RTF erzeugen
 
Hmm..

Mach mal ein neues Project, pappe da nen Button, OpenDialog und ein TImage drauf und verwende mal meinen Src. (Nur um zu prüfen)

Wenn dann das bmp nicht mehr weiß ist und das PDF enthält, gehst Du hin und testest, mit deinem Stream.

Somit kannst Du schonmal ausschließen, ob es die Routine mit dem RichEdit ist. Oder dass der Stream leer ist..

Schritt für Schritt.. ;)

Hobbycoder 23. Jun 2017 15:23

AW: Bitmap aus RTF erzeugen
 
mach ich gleich mal. Aber dass der Stream nicht leer ist, habe ich schon geprüft, und sichergesellt (s. einem der oberen Posts).
Aber ich probier das jetzt mit einem neuen Projekt mal aus.

Hobbycoder 23. Jun 2017 16:20

AW: Bitmap aus RTF erzeugen
 
Danke Holger,

ich habe das jetzt noch mal in einem neuen Projekt gemacht. Und natürlich funktioniert's ;-)
Warum es vorher in meine Zielprojekt nicht funktioniert hat ich auch herausgefunden. Jetzt muss ich das nur noch so abändern, dass ich die Bitmap.Height und .Width übergeben kann. :-)

HolgerX 23. Jun 2017 17:36

AW: Bitmap aus RTF erzeugen
 
Gut.. :thumb:

Ich mache mir bei so Problemen immer ein kleines Testprogramm, indem ich die Funktionen oder auch Klassen in einer minimalen Umgebung teste, somit kann ich sicherstellen, dass diese Funktionieren und kann meine Suche dann in eine Andere Richtung bewegen.. ;)

Apropo, woran hat es denn nun gelegen?

Hobbycoder 24. Jun 2017 18:13

AW: Bitmap aus RTF erzeugen
 
Mach ich des Öfteren auch. Allerdings war der Code sehr überschaubar, dass ich annahm, einen Testprojekt sei nicht notwendig.
Tja...ich hatte nur ein Assign vergessen ;-)

UliTs 29. Aug 2020 22:38

AW: Bitmap aus RTF erzeugen
 
Zitat:

Zitat von HolgerX (Beitrag 1375241)
Hmm..

Hab mal nen bischen gegooglet und zusmmengeschripselt:
...

Hallo HolgerX,
vielen Dank für Deinen Beitrag, der mir schon sehr weiter geholfen hat. Das einzige Problem, dass ich noch habe, ist, dass ich das Bitmap mit einer höheren Auflösung erstellen möchte.
Das gelingt mir insofern nicht, dass sich die Pixelauflösung des RtfTextes in der Bitmap nicht erhöht. Ich habe heute viele Stunden dran gesessen, finde aber nicht die Lösung :( .

Hast Du oder jemand anders eine Idee, wie man Dein Beispiel korrekt anpasst?

Uli

UliTs 30. Aug 2020 14:02

AW: Bitmap aus RTF erzeugen
 
Ich meine, es geht mit ViewPort. Nur wie?

Edit: nach einem kompletten Wochenende der Rumsucherei habe ich gestern Abend kurz vor dem zu Bett gehen auf dem iPhone die Lösung gefunden. Und siehe da, beim Suchen nach "Delphi" und "Viewport" fand ich einen vielversprechenden Link auf einen Faden in diesem Forum: https://www.delphipraxis.net/40461-k...as-zoomen.html
Ich denke, damit werde ich schnell mein Problem lösen.
-
Bleibt die Frage, warum ich über das Suchfeld und sonstige Suchen den Faden nicht früher gefunden habe. Klar, das Problem sitzt vor dem Bildschirm ... Ich habe im Suchfeld nicht gemerkt, dass immer nur nach ganzen Wörtern gesucht wird und nicht nach Teilworten. Ein "*" hinter "Viewport" hinzugefügt und schon habe ich aus so die entscheidenden Fäden gefunden.

cs.rumpelstilzchen 3. Jan 2024 17:11

AW: Bitmap aus RTF erzeugen
 
Hallo Uli,
ich stehe grad selbst vor dem gleichen Problem.
Es wäre schön, wenn du deine Lösung hier allen zur Verfügung stellst um wiederholte "Rumsucherei" zu erübrigen. ;)

UliTs 29. Mär 2024 13:55

AW: Bitmap aus RTF erzeugen
 
Sorry, die Lösung, die ich da gefunden hatte, war im Endeffekt auch nicht besonders gut. Ich habe es dann komplett selbst programmiert.

Redeemer 30. Mär 2024 21:02

AW: Bitmap aus RTF erzeugen
 
Zitat:

Zitat von UliTs (Beitrag 1472621)
Bleibt die Frage, warum ich über das Suchfeld und sonstige Suchen den Faden nicht früher gefunden habe.

Weil die Suchfunktionen innerhalb von Seiten unbrauchbar sind im Vergleich zur Suche eines Unternehmens, das damit seit Jahren Geld verdient, genau das auf die Kette zu kriegen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:50 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz