RTF zu EMF konvertieren

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
javabean
Beiträge: 29
Registriert: 16.12.2004 18:47

RTF zu EMF konvertieren

Beitrag von javabean »

Ich hab' einen C++ Code nach PureBasic übersetzt. Damit ist es möglich einen RTF-Inhalt in EMF Dateien zu speichern:

RTF_to_EMF.pb

Code: Alles auswählen

;===========================================================
;Inhalt eines RTF Controls in EMF Dateien speichern
;===========================================================
; javabean (März, 2010)
;-----------------------------------------------------------
; getestet auf PureBasic 4.40 (x86-Windows), Windows XP_SP3
;-----------------------------------------------------------
;Code nach PureBasic übersetzt, basierend auf:
;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
;-----------------------------------------------------------

; Include Datei wird benötigt, um die RTF-Datei in das RTF Control zu streamen
; und um das OLE Interface des RTF Controls nutzen zu können
; siehe: http://www.purebasic.fr/english/viewtopic.php?t=20691
XIncludeFile "OLEedit.pbi"

; gibt einen 'printer DC' zurück - benutzt 'Printer Common Dialog'
Procedure GetPrinterDC()
  pdlg.PRINTDLG
 
  pdlg\lStructSize  = SizeOf(PRINTDLG)
  pdlg\Flags        = #PD_RETURNDC; #PD_RETURNDEFAULT
  PrintDlg_(@pdlg)
  ProcedureReturn pdlg\hDC
EndProcedure

; Länge (in Zeichen) des Texts im RTF control ermitteln
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 - Veranlasst das RTF control sich selbst auf ein EMF zu zeichnen
;   Parameter:
;       hRefDC wird benötigt, um das EMF zu erzeugen
;       MetaFileName$ ist der Dateiname des erzeugten EMF
;       prcMeta ist die RECT Struktur für die CreateEnhMetaFile()-Funktion in 0.01mm
;               Einheiten
;       hWndRTF ist das Handle des RTF controls
;       nStart Position des ersten Zeichens
;       *pEnd Pointer zu einer Variable (Long) in der die Position des nächsten zu druckenden Zeichens (nach dieser Seite)
;               gespeichert wird

Procedure.l RTFToEMF(hRefDC.l, MetaFileName$, *prcMeta.RECT, hWndRTF.l, nStart.l, *pEnd)
  fr.FORMATRANGE
 
; DasEMF erzeugen
  hMetaDC = CreateEnhMetaFile_(hRefDC, @MetaFileName$, *prcMeta.RECT, #Null )
 
  If hMetaDC = 0
    ProcedureReturn 0
  EndIf
 
  ;Seite einrichten (konvertiert 0.01mm zu 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

  ;Keine Ränder rundherum
  fr\rc = fr\rcPage

  ;Zu druckenden Textbereich (nStart bis Dokumentenende)
  fr\chrg\cpMin = nStart
  fr\chrg\cpMax = -1
  fr\hdcTarget  = hMetaDC
  fr\hdc        = fr\hdcTarget
 
  ;Veranlasst das RTF Control sich selbst auf unseren (meta)DC zu zeichnen
  nTextPrinted = SendMessage_(hWndRTF, #EM_FORMATRANGE, #True, @fr);
  If *pEnd <> 0
    ;pEnd = nTextPrinted
    PokeL(*pEnd, nTextPrinted)
    ProcedureReturn CloseEnhMetaFile_(hMetaDC)
  EndIf
EndProcedure

;DumpRTFToPagedEMFs - Demonstration von RTFtoEMF() um eine EMF Datei für jede
;                     Seite des RTF Controls zu erzeugen
;   Parameters:
;     hWndRTFControl - Handle zum RTF Control
;     EMFFileTitleBase$ - Basisname der RTF Dateien; die Seitenzahl wird an den Namen angehängt

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

; Zuerst ermitteln wieviele Zeichen der Text im RTF umfasst
  nRTFTextLength = GetRTFTextLength(hWndRTFControl)
 
; Referenz-DC (basierend auf einem Drucker) ermitteln
  hRefDC = GetPrinterDC()

; meta RECT Struktur (0.01mm Einheiten) einrichten
  SetRect_(@rcMeta, 0, 0, GetDeviceCaps_(hRefDC, #HORZSIZE)*100, GetDeviceCaps_(hRefDC, #VERTSIZE)*100 )
 
; Solange die Schleife durchlaufen bis das Textende im RTF Control erreicht wird
  nStart = 0
  nPage  = 0
  While nStart<nRTFTextLength
    ; Einen Dateinamen für die Seite generieren
    MetaName$ = EMFFileTitleBase$+Str(nPage)+".EMF"
;   obige Funktion aufrufen, um diesen Textteil des RTF auf das EMF zu zeichnen
    hEMF = RTFToEMF(hRefDC, MetaName$, @rcMeta, hWndRTFControl, nStart, @nStart )
;   aufräumen
    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)
    ;Das COM Interface für das RTF Control einrichten
    RichEdit_SetInterface(GadgetID(0))
  ButtonGadget(1,250,565,100,30,"Dump to RTF")
 
  LoadRTF(0, "C:\RTF_file.rtf", #SF_RTF, 1) ; Dateinamen (und -pfad) anpassen
   
  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
        quit=1
   
      Case #PB_Event_Gadget
        Select EventGadget()
          Case 1
            DumpRTFToPagedEMFs(hWndRTF, "C:\Emf_file_")  ; Dateinamen (und -pfad) anpassen
        EndSelect
    EndSelect
  Until quit=1
EndIf
End
Das Include File 'OLEedit.pbi' stammt von hier: http://www.purebasic.fr/english/viewtopic.php?t=20691