RichEdit: Variable Druckfunktion

Mit der folgende Prozedur kann man den Inhalt eines RichEdit-Steuerelements ganz oder teilweise an beliebige Stellen auf einer Seite ausdrucken.

  • Der Parameter RichEditHandle ist das Handle des RichEdit-Steuerelements, also z.B RichEdit1.Handle.

  • Der Parameter PageRect gibt das Rechteck auf der aktuellen Druckseite an, in das gedruckt werden soll. Die Maßeinheit der Elemente dieses Rechtecks wird über den folgenden Parameter angegeben.

  • Der Parameter RectScaling gibt die Maßeinheit von PageRect an, in Einheiten je 100 Zoll. Einige Konstanten für Twips, Punkte, Millimeter und Druckerpixel sind im Quelltext definiert. Ist dieser Wert positiv, dann beschreibt das Rechteck absolute Koordinaten, sonst die Seitenränder.

    Beispiele:

    • PrintRichEditIntoRect(h, Rect(10, 20, 110, 60), PageRect_MM)
      Druckt den Text in ein Rechteck, das 1 cm von linken und 2 cm vom oberen Rand entfernt ist und das 10 cm breit und 4 cm hoch ist.

    • PrintRichEditIntoRect(h, Rect(25, 20, 25, 20), -PageRect_MM)
      Druckt den Text in ein Rechteck mit den Seitenrändern 2,5 cm links und rechts sowie 2 cm oben und unten.

  • Der Parameter StartPos ist der Index des ersten zu druckenden Zeichens, also z.B. RichEdit1.SelStart. Der Wert 0 druck ab dem ersten Zeichen.

  • Der Parameter EndPos ist der Index des letzten zu druckenden Zeichens, also z.B. RichEdit1.SelStart + RichEdit1.SelLength. Der Wert -1 druck alle Zeichen bis zum Ende des Textes.

  • Der Rückgabewert ist der Index des ersten Zeichens, dass nicht mehr in das Ausgaberechteck passte und somit nicht mehr gedruckt wurde. So kann man konsekutiv den Rückgabewert als nächsten Wert für StartPos benutzen, um den gesamten Text auszudrucken. Über einen Vergleich mit RichEdit1.GetTextLen kann man erfahren, ob der gesamte Inhalt ausgedruckt werden konnte.

Man sollte die Funktion nicht direkt für den Ausdruck eines einzigen Textes über viele Seiten benutzen, da durch den Aufruf von SendMessage(RichEditHandle, EM_FORMATRANGE, 0, 0) die Formatierungsinformationen jeweils wieder verworfen werden, und das geht auf die Performance. Allerdings kann man den Text für solche Fälle dennoch sehr gut als Vorlage für eigene Entwicklungen benutzen.

Die Druckerfunktionen Printer.BeginDoc, Printer.EndDoc sowie ggf. Printer.NewPage muss man selbst aufrufen - aber dadurch kann man z.B. auch den Inhalt von 7 RichEdit-Steuerelementen zusammen mit einer Grafik auf eine Seite drucken. Das Beispiel am Ende dieser Seite zeigt dies.

uses
  Windows, RichEdit;

const
  PageRect_Twips = 144000;  // 100 * twips/inch
  PageRect_Points = 7200;   // 100 * pt/inch
  PageRect_MM = 2540;       // 100 * mm/inch
  PageRect_Printer = 0;

function PrintRichEditIntoRect(RichEditHandle: HWND; const PageRect: TRect;
  RectScaling: Integer = PageRect_Printer; StartPos: Integer = 0;
  EndPos: Integer = -1): Integer;
var
  Range: TFormatRange;
  mm, lpx, lpy, pox, poy: Integer;
begin
  Range.hdc := Printer.Handle;
  Range.hdcTarget := Range.hdc;

  // Get printer resolution
  lpx := 100 * GetDeviceCaps(Range.hdc, LOGPIXELSX);
  lpy := 100 * GetDeviceCaps(Range.hdc, LOGPIXELSY);

  // Convert to device coordinates
  if RectScaling <> PageRect_Printer then
  begin
    // Get physical printing offset
    pox := GetDeviceCaps(Range.hdc, PHYSICALOFFSETX);
    poy := GetDeviceCaps(Range.hdc, PHYSICALOFFSETY);

    if RectScaling < 0 then
    begin
      Range.rc.Left := MulDiv(PageRect.Left, lpx, -RectScaling) - pox;
      Range.rc.Top  := MulDiv(PageRect.Top,  lpy, -RectScaling) - poy;
      Range.rc.Right  := GetDeviceCaps(Range.hdc, PHYSICALWIDTH) -
        MulDiv(PageRect.Right,  lpx, -RectScaling);
      Range.rc.Bottom := GetDeviceCaps(Range.hdc, PHYSICALHEIGHT) -
        MulDiv(PageRect.Bottom, lpy, -RectScaling);
    end
    else
    begin
      Range.rc.Left   := MulDiv(PageRect.Left,   lpx, RectScaling) - pox;
      Range.rc.Top    := MulDiv(PageRect.Top,    lpy, RectScaling) - poy;
      Range.rc.Right  := MulDiv(PageRect.Right,  lpx, RectScaling) - pox;
      Range.rc.Bottom := MulDiv(PageRect.Bottom, lpy, RectScaling) - poy;
    end;
  end
  else
    Range.rc := PageRect;

  // Convert to twips
  Range.rc.Left   := MulDiv(Range.rc.Left,   144000, lpx);
  Range.rc.Top    := MulDiv(Range.rc.Top,    144000, lpy);
  Range.rc.Right  := MulDiv(Range.rc.Right,  144000, lpx);
  Range.rc.Bottom := MulDiv(Range.rc.Bottom, 144000, lpy);

  Range.rcPage := Range.rc;
  Range.chrg.cpMin := StartPos;
  Range.chrg.cpMax := EndPos;

  mm := SetMapMode(Printer.Handle, MM_TEXT);
  try
    SendMessage(RichEditHandle, EM_FORMATRANGE, 0, 0);
    Result := SendMessage(RichEditHandle, EM_FORMATRANGE, 1, Integer(@Range));
    if Result < 0 then
      Result := SendMessage(RichEditHandle, WM_GETTEXTLENGTH, 0, 0);
  finally
    SendMessage(RichEditHandle, EM_FORMATRANGE, 0, 0);
    SetMapMode(Printer.Handle, mm);
  end;
end;

Beispiel

Das folgende Beispiel druckt den Inhalt von RichEdit1 in vier 10 cm große Quadrate in der Reihenfolge links oben, rechts unten, links unten, rechts oben.

procedure TForm1.Print1Click(Sender: TObject);
var
  h: THandle;
  pp: Integer;
begin
  h := RichEdit1.Handle;

  Printer.BeginDoc;
  try
    pp := 0;
    pp := PrintRichEditIntoRect(h, Rect( 10,  10, 100, 100), PageRect_MM, pp);
    pp := PrintRichEditIntoRect(h, Rect(110, 110, 200, 200), PageRect_MM, pp);
    pp := PrintRichEditIntoRect(h, Rect( 10, 110, 100, 200), PageRect_MM, pp);
    pp := PrintRichEditIntoRect(h, Rect(110,  10, 200, 100), PageRect_MM, pp);

    Printer.EndDoc;
  except
    Printer.Abort;
    raise;
  end;

  MessageDlg('Ausdruck erfolgte bis Zeichen ' + IntToStr(pp),
    mtInformation, [mbOk], 0);
end;
Flocke's Garage
Valid HTML 4.01 Transitional Valid CSS!
(C) 2005-2013 Volker Siebert.
Creative Commons-LizenzvertragDer gesamte Inhalt dieser Webseite steht unter einer Creative Commons-Lizenz (sofern nicht anders angegeben).