Delphi Tutorial - Saving a RichEdit to a Metafile

'

Introduction

Sometimes, you may want to store the contents of a rich edit control in a metafile.

This article outlines an approach that stores this type of control's contents in enhanced metafiles, one page per metafile.

Metafiles are useful when you want the content to be scalable at different resolutions

The following code demonstrates one method to dump the contents of a rich edit control into EMF files (one per page):


The Delphi Source Code

unit RichEditEMFPrint;

interface

uses
  Windows, SysUtils, RichEdit, commdlg, classes, messages, Comctrls;

procedure RichEditToMetaFile(AControl : TRichEdit; AFileName : string);

implementation

// GetPrinterDC()
// returns a printer DC - uses Printer Common Dialog
function GetPrinterDC : HDC;
var
  pdlg : TPRINTDLG;
begin
  FillChar(pdlg, sizeof(TPRINTDLG), 0);
  pdlg.lStructSize := sizeof( TPRINTDLG );
  pdlg.Flags := PD_RETURNDC;
  PrintDlg(pdlg);
  Result := pdlg.hDC;
end;

// Get the length, in characters, of the text in the control
function GetRTFTextLength(hWndRTF : HWND) : integer;
begin
  Result := SendMessage(hWndRTF, WM_GETTEXTLENGTH, 0, 0 );
end;

// RTFToEMF - Tell the control to draw itself on the EMF
// Parameters:
//     hRefDC is used to create the EMF
//     pszMetaFileName is the file name of the new EMF (can be nil)
//     prcMeta is the RECT used to in CreateEnhMetaFile(), in 0.01mm
//          units (should not be nil)
//     hWndRTF is the control of interest
//     nStart is the starting character location
//     pEnd is a integer which receives the position of
//          the next character to print after this page 
function RTFToEMF(hRefDC : HDC; pszMetaFileName : LPCTSTR;  prcMeta : TRECT;
             hWndRTF : HWND; nStart : integer; var pEnd : integer) : HENHMETAFILE;
var
  hMetaDC : HDC;
  fr : FORMATRANGE;
  nTextPrinted : integer;
begin
    // Create the EMF
    hMetaDC := CreateEnhMetaFile( hRefDC, pszMetaFileName, @prcMeta, nil );
    if( hMetaDC = 0 ) then
     begin
        Result := 0;
        Exit;
     end;

    ZeroMemory(@fr, sizeof(fr));
    // Set up the page (convert 0.01mm to twips)
    fr.rcPage.top       := prcMeta.left*1440 div 2540;
    fr.rcPage.left      := prcMeta.top*1440 div 2540;
    fr.rcPage.right     := prcMeta.right*1440 div 2540;
    fr.rcPage.bottom    := prcMeta.bottom*1440 div 2540;
    // Set up no margins all around.
    fr.rc := fr.rcPage;
    // Set up the range of text to print as nStart to end of document
    fr.chrg.cpMin := nStart;
    fr.chrg.cpMax := -1;
    fr.hdcTarget := hMetaDC;
    fr.hdc := fr.hdcTarget;
    // Tell the control to draw itself on our (meta) DC
    nTextPrinted := SendMessage(hWndRTF, EM_FORMATRANGE, 1, integer(@(fr)));
    pEnd := nTextPrinted;
    Result :=  CloseEnhMetaFile( hMetaDC );
end;

// DumpRTFToPagedEMFs - demonstrates using RTFToEMF() to create an EMF
//                      for each page in an RTF control
// Parameters:
//     hWndRTFControl - the control
//     szEMFFileTitleBase - base filename for EMF files, number is appended
procedure DumpRTFToPagedEMFs(hWndRTFControl : HWND; szEMFFileTitleBase : LPTSTR);
var
  szMetaName : string;
  nRTFTextLength, nStart, nPage : integer;
  hRefDC : HDC;
  rcMeta : TRECT;
  hEMF :   HENHMETAFILE;

begin
    // First, determine how many chars are in the RTF
    nRTFTextLength := GetRTFTextLength( hWndRTFControl );
    // Get a reference DC (based on a printer)
    hRefDC := GetPrinterDC();
    // Set up the meta RECT for 0.01mm units
    rcMeta := Classes.Rect( 0, 0, GetDeviceCaps(hRefDC, HORZSIZE)*100,
                            GetDeviceCaps(hRefDC, VERTSIZE)*100 );

    nPage := 0;
    nStart := 0;
    while nStart<nRTFTextLength do
    // Loop while we've not reached the end of the text in the control
    begin
        // construct a file name for this page
        szMetaName := Format('%s%d.EMF', [szEMFFileTitleBase, nPage]);
        // call function above to draw this portion of the RTF on the EMF
        hEMF := RTFToEMF( hRefDC, PChar(szMetaName), rcMeta, hWndRTFControl,
                         nStart, nStart );
        // clean up
        DeleteEnhMetaFile( hEMF );
        inc(nPage);
        if nStart = 0 then
         break;
    end;
end;


procedure RichEditToMetaFile(AControl : TRichEdit; AFileName : string);
begin
   DumpRTFToPagedEMFs(AControl.Handle, PChar(AFileName));
end;

end.

This tutorial was kindly provided by serge perevoznyk


Google
Web www.Delphi-Central.com
Delphi Central - Delphi Programming Tutorials, Hints and Tips