2010-07-12 18 views
17

here'da tartışıldığı gibi metin dönüştürmeyi rtf gerçekleştirmek için çalışma zamanında bir TRichEdit kullanmam gerekir. Bunu yapmakta başarılı oldum ancak TRichedit.Lines'i yerleştiremediğim takdirde ebeveyn olarak kukla bir form ayarlamak zorunda kaldım. (Hata: ebeveyn eksik). Aşağıda benim funciton'ımı yapıştırıyorum, bir ebeveyn tanımlamaktan kaçınmanın bir yolu var mı? Bu konuda yorum yapabilir ve daha iyi bir fikir bulursanız söyler misiniz?Bir ebeveyn tanımlamaksızın TRichEdit'i kullanma

Not: Çıkış olarak TStrings'e değil, bir dizgiye ihtiyacım var, bu yüzden bu şekilde tasarlandı.

function RtfToText(const RTF: string;ReplaceLineFeedWithSpace: Boolean): string; 
var 
    RTFConverter: TRichEdit; 
    MyStringStream: TStringStream; 
    i: integer; 
    CustomLineFeed: string; 

begin 
    if ReplaceLineFeedWithSpace then 
    CustomLineFeed := ' ' 
    else 
    CustomLineFeed := #13; 
    try 
    RTFConverter := TRichEdit.Create(nil); 
    try 
     MyStringStream := TStringStream.Create(RTF); 
     RTFConverter.parent := Form4; // this is the part I don't like 
     RTFConverter.Lines.LoadFromStream(MyStringStream); 
     RTFConverter.PlainText := True; 
     for i := 0 to RTFConverter.Lines.Count - 1 do 
     begin 
     if i < RTFConverter.Lines.Count - 1 then 
      Result := Result + RTFConverter.Lines[i] + CustomLineFeed 
      else 
      Result := Result + RTFConverter.Lines[i]; 
     end; 
    finally 
     MyStringStream.Free; 
    end; 
    finally 
    RTFConverter.Free; 
    end; 

end; 

GÜNCELLEME: cevap sonra işlevini güncel ve başvuru için burada yazmak:

function RtfToText(const RTF: string;ReplaceLineFeedWithSpace: Boolean): string; 
var 
    RTFConverter: TRichEdit; 
    MyStringStream: TStringStream; 
begin 
    RTFConverter := TRichEdit.CreateParented(HWND_MESSAGE); 
    try 
    MyStringStream := TStringStream.Create(RTF); 
    try 
     RTFConverter.Lines.LoadFromStream(MyStringStream); 
     RTFConverter.PlainText := True; 
     RTFConverter.Lines.StrictDelimiter := True; 
     if ReplaceLineFeedWithSpace then 
     RTFConverter.Lines.Delimiter := ' ' 
     else 
     RTFConverter.Lines.Delimiter := #13; 
     Result := RTFConverter.Lines.DelimitedText; 
    finally 
     MyStringStream.Free; 
    end; 
    finally 
    RTFConverter.Free; 
    end; 
end; 
+0

Satır Besleme karakter numarası # 10 değil # 13, Taşıyıcının Dönüşü –

+0

Ayrı bir iş parçacığında bunu Senkronize etmenizi gerektirdiğini düşündüğüm bir görsel bileşene (TRichEdit) başvurmak zorunda kalmak rahatsız edici. RTF'yi bir sunucuda düz metne dönüştürmek istiyorum ve henüz kullanmadığım bir kod bulamadım. Ama bunu yayınladığın için teşekkürler. – Alister

+0

Oluşturma/durma bloklarının dışındaki çağrıları oluşturmayı doğru bir şekilde yaptım.Aksi takdirde, Oluşturma çağrısında bir istisna varsa, kod başlatılmamış bir değişkeni serbest olarak aramaya çalışır (bir özel durumun kodun çağrı deyimine hiçbir zaman geri dönmediği, ancak doğrudan/nihayet parçasına atladığı anlamına gelir, öyleyse ödev değişkene asla yapılmaz. – HeartWare

cevap

28

TRichEdit denetimi, Windows'ta RichEdit denetimi etrafındaki sarıcıdır. Windows'un kontrolleri ... iyi .. Windows ve çalışmak için bir Pencere Sapına ihtiyaçları var. Delphi, Create'i oluşturmak için CreateWindow veya CreateWindowEx'i çağırmalıdır ve her iki yordamın çalışması için geçerli bir üst Window Handle'a gereksinimi vardır. Delphi, kontrolün ebeveyninin kolunu kullanmaya çalışır (ve mantıklıdır!). Hemen hemen bir alternatif kurucu (CreateParanted(HWND) yapıcı) kullanabilir ve Microsoft'taki güzel insanlar, aslında bir "pencere" (yalnızca mesajlaşma) istemeyen pencereler için ebeveyn olarak kullanılmak üzere HWND_MESSAGE'u oluşturdular.

Bu kod beklendiği gibi çalışır: Beni ancak dönüşüm ile, TRichedit başlamak için

procedure TForm2.Button2Click(Sender: TObject); 
var R:TRichEdit; 
    L:TStringList; 
begin 
    R := TRichEdit.CreateParented(HWND_MESSAGE); 
    try 
    R.PlainText := False; 
    R.Lines.LoadFromFile('C:\Temp\text.rtf'); 
    R.PlainText := True; 

    Memo1.Lines.Text := R.Lines.Text; 
    finally 
    R.Free; 
    end; 
end; 
+0

Harika Trick, soruları tekrar güncellememe izin verin. – LaBracca

+1

Bunu kabul edilen yanıt olarak ayarlıyorum çünkü bir ebeveyn tanımlamaksızın bir TRichEdit denetiminin * neredeyse * nasıl oluşturulacağını gösterir. Benden de Göndermiş için – LaBracca

+0

+1. – Despatcher

8

Bu VCL nasıl çalıştığı bir parçasıdır ve gitmiyorsun bazı geçici çözümler olmadan farklı şekilde çalışmasını sağlayın. Ancak ebeveyn olmak için bir kukla form tanımlamanız gerekmez; Sadece mevcut formunuzu kullanın ve TRichEdit'e visible := false;'u ayarlayın.

Performansı gerçekten geliştirmek istiyorsanız, yine de bir sonuç dizesi oluşturmak için kullandığınız döngüyü atabilirsiniz. Hafızayı yeniden tahsis etmek ve kopyalamak zorunda. Her satır arasında bir CRLF almak için TrichEdit.Lines öğesinin Text özelliğini ve boşluk gibi başka bir şey elde etmek için DelimitedText öğesini kullanın. Yalnızca bir kez ayrılan bir dahili arabellek kullanırlar, bu da çok fazla metinle çalışıyorsanız, birleştirme işlemini hızlandıracaktır.

+0

+1 'Visible: = false' –

+0

Bu özellik hakkında bilgi sahibi olmadım, son sürümü koyarak soruyu güncelleyeceğim, ayrıca bir çalışma zamanı oluşturulmuş form da ekledim, böylece işlev "bağımsız" bir işlev haline geliyor . – LaBracca

4

RichEdit denetimi olmadan RTF çizmek için DrawRichText kullanıyorum. (IIRC, buna Windowless Rich Edit Controls denir.) Belki bunu dönüştürmek için de kullanabilirsiniz - ancak bunu hiç denemedim.

0

Bu en yararlı olmuştur. beklendiği gibi bu ancak çalışır ve Hat Ayırıcıyı ayarlamak gerekmez:

// RTF to Plain: 
procedure TForm3.Button1Click(Sender: TObject); 
var 
    l:TStringList; 
    s:WideString; 
    RE:TRichEdit; 
    ss:TStringStream; 
begin 
    ss := TStringStream.Create; 
    s := Memo1.Text; // Input String 
    RE := TRichEdit.CreateParented(HWND_MESSAGE); 
    l := TStringList.Create; 
    l.Add(s); 
    ss.Position := 0; 
    l.SaveToStream(ss); 
    ss.Position := 0; 
    RE.Lines.LoadFromStream(ss); 
    Memo2.Text := RE.Text; // Output String 
end; 

// Plain to RTF: 
procedure TForm3.Button2Click(Sender: TObject); 
var 
    RE:TRichEdit; 
    ss:TStringStream; 
begin 
    RE := TRichEdit.CreateParented(HWND_MESSAGE); 
    RE.Text := Memo2.Text; // Input String 
    ss := TStringStream.Create; 
    ss.Position := 0; 
    RE.Lines.SaveToStream(ss); 
    ss.Position := 0; 
    Memo1.Text := ss.ReadString(ss.Size); // Output String 
end; 

nasılsa TStringStream yeni hat her karakter koyar çünkü düz dönüşüm içinde TStringList "l" kullanıyorum .

Düzenleme: Kodu biraz daha güzel yaptı ve kullanılmayan değişkenler kaldırıldı.