Print RTF to EMF

Share your advanced PureBasic knowledge/code with the community.
javabean
User
User
Posts: 60
Joined: Sat Nov 08, 2003 10:29 am
Location: Austria

Print RTF to EMF

Post by javabean »

I translated a C++ example code on how to store the contents of an RTF control in EMF files to PureBasic.

RTF_to_EMF.pb

Code: Select all

;===========================================================
;How to Store the Contents of an RTF Control in an EMF File
;===========================================================
; javabean (March, 2010)
;-----------------------------------------------------------
; tested on PureBasic 4.40 (x86-Windows), Windows XP_SP3
;-----------------------------------------------------------
;Code translated from a C++ example, based on:
;http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/e1930c3b-b5c1-4de6-a541-d4981594d033
;http://support.microsoft.com/?scid=kb%3Ben-us%3B253262&x=7&y=15
;-----------------------------------------------------------
; This code is provided 'as is', without any expressed or
; implied warranty. In no event will the author be held liable
; for any damages arising from the use of this code.
;===========================================================
; RTF_to_EMF.pb
;-----------------------------------------------------------

; Use this include file for streaming-in the rtf
; and to make use of the OLE Interface
; see http://www.purebasic.fr/english/viewtopic.php?t=20691
XIncludeFile "OLEedit.pbi"

; returns a printer DC - uses Printer Common Dialog
Procedure GetPrinterDC()
  pdlg.PRINTDLG
  
  pdlg\lStructSize  = SizeOf(PRINTDLG)
  pdlg\Flags        = #PD_RETURNDC; #PD_RETURNDEFAULT
  PrintDlg_(@pdlg)
  ProcedureReturn pdlg\hDC
EndProcedure

; Get the length, in characters, of the text in the control
Procedure GetRTFTextLength(hWndRTF.l)
  gtlex.GETTEXTLENGTHEX
  
  gtlex\flags     = #GTL_PRECISE
  gtlex\codepage  = #CP_ACP
  ret = SendMessage_(hWndRTF, #EM_GETTEXTLENGTHEX, @gtlex, 0 )
  ProcedureReturn ret
EndProcedure

;RTFToEMF - Tell the control to draw itself on the EMF
;   Parameters:
;       hRefDC is used to create the EMF
;       MetaFileName$ is the file name of the new EMF (can be NULL)
;       prcMeta is the RECT used to in CreateEnhMetaFile(), in 0.01mm
;               units (should not be NULL)
;       hWndRTF is the RTF control of interest
;       nStart is the starting character location
;       *pEnd is a pointer to an int which receives the position of
;               the next character to print after this page (can be NULL)

Procedure.l RTFToEMF(hRefDC.l, MetaFileName$, *prcMeta.RECT, hWndRTF.l, nStart.l, *pEnd)
  fr.FORMATRANGE
  
; Create the EMF
  hMetaDC = CreateEnhMetaFile_(hRefDC, @MetaFileName$, *prcMeta.RECT, #Null )
  
  If hMetaDC = 0
    ProcedureReturn 0
  EndIf
  
  ;Set up the page (convert 0.01mm to twips)
  fr\rcPage\top       = *prcMeta\left  *1440/2540
  fr\rcPage\left      = *prcMeta\top   *1440/2540
  fr\rcPage\right     = *prcMeta\right *1440/2540
  fr\rcPage\bottom    = *prcMeta\bottom*1440/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, #True, @fr);
  If *pEnd <> 0
    ;pEnd = nTextPrinted
    PokeL(*pEnd, nTextPrinted)
    ProcedureReturn CloseEnhMetaFile_(hMetaDC)
  EndIf
EndProcedure

;DumpRTFToPagedEMFs - demonstrates using RTFToEMF() to create an EMF
;                     for each page in an RTF control
;   Parameters:
;     hWndRTFControl - handle to the RTF control
;     EMFFileTitleBase$ - base filename for EMF files, number is appended

Procedure DumpRTFToPagedEMFs(hWndRTFControl.l, EMFFileTitleBase$)
  rcMeta.RECT

; 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
  SetRect_(@rcMeta, 0, 0, GetDeviceCaps_(hRefDC, #HORZSIZE)*100, GetDeviceCaps_(hRefDC, #VERTSIZE)*100 )
  
; Loop While we've not reached the end of the text in the control
  nStart = 0
  nPage  = 0
  While nStart<nRTFTextLength
    ; construct a file name for this page
    MetaName$ = EMFFileTitleBase$+Str(nPage)+".EMF"
;   call function above to draw this portion of the RTF on the EMF
    hEMF = RTFToEMF(hRefDC, MetaName$, @rcMeta, hWndRTFControl, nStart, @nStart )
;   clean up
    DeleteEnhMetaFile_(hEMF)
    nPage+1
  Wend
EndProcedure


If OpenWindow(0, 0, 0, 600, 600, "RTF Control", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  hWndRTF = EditorGadget(0, 8, 8, 584, 550)
    SendMessage_(hWndRTF, #EM_SETTEXTMODE, #TM_RICHTEXT, 0)
    ;Set up the COM interface for the editor gadget.
    RichEdit_SetInterface(GadgetID(0))
  ButtonGadget(1,250,565,100,30,"Dump to RTF")
  
  LoadRTF(0, "C:\RTF_file.rtf", #SF_RTF, 1) ; Adjust path and filename of the rtf to stream in
   
  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
        quit=1
    
      Case #PB_Event_Gadget
        Select EventGadget()
          Case 1
            DumpRTFToPagedEMFs(hWndRTF, "C:\EMF_file_") ; Adjust path and basefilename
        EndSelect
    EndSelect
  Until quit=1
EndIf
End
For the include file 'OLEedit.pbi' please see: http://www.purebasic.fr/english/viewtopic.php?t=20691
Baie21
New User
New User
Posts: 1
Joined: Thu Feb 10, 2011 8:03 am

Re: Print RTF to EMF

Post by Baie21 »

Hi

I have tried to run C++ code but it only shows printer dialog box. it does not convert RTF into EMF.

Is there any way to convert RTF into EMF Metafile?
rsts
Addict
Addict
Posts: 2736
Joined: Wed Aug 24, 2005 8:39 am
Location: Southwest OH - USA

Re: Print RTF to EMF

Post by rsts »

It works for me.

Have you adjusted your paths?

cheers
javabean
User
User
Posts: 60
Joined: Sat Nov 08, 2003 10:29 am
Location: Austria

Re: Print RTF to EMF

Post by javabean »

Hi,

the rtf text you enter in the editor gadget will be converted to EMF.
The printer dialog is needed in order to get the right DC.
Of course you may have to adjust the output path for your needs, but after you have selected a printer in the printer dialog the EMF file will be generated.
This short example is just meant as a demonstration and is not a full featured application...

Btw, I haven't tried the original functions written C, but I can't see why it wouldn't work...

Cheers,
javabean
Post Reply