2010-07-12 12 views
17

런타임시 TRichEdit을 사용하여 rtf에서 텍스트로 변환을 수행해야합니다 (here). 나는 이것을하기에 성공했지만, TRichedit.Lines를 채울 수 없다면 더미 폼을 부모로 설정해야했습니다. (오류 : 상위 항목이 누락되었습니다.) 아래에 내 funciton을 붙여 넣으십시오, 누군가는 부모를 정의하는 것을 피할 방법을 제안 할 수 있습니까? 당신은 또한 이것에 대해 논평 할 수 있고 더 좋은 아이디어를 찾았는지 말해 줄 수 있습니까?부모를 정의하지 않고 런타임시 TRichEdit 사용

참고 : TString을 출력으로 사용하지 말고 문자열이 필요합니다. 이것이 바로 이런 이유로 설계되었습니다.

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; 

UPDATE : 대답 후 나는 기능을 업데이트하고 참조를 위해 여기를 쓰기 :

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

줄 바꿈 문자는 # 13이 아닌 캐리지 리턴입니다. –

+0

시각적 구성 요소 (TRichEdit)를 참조해야하므로 귀찮습니다. 별도의 스레드에서이 작업을 수행 할 때 동기화를 호출해야합니다. RTF를 서버의 일반 텍스트로 변환하고 싶지만 아직 익숙하지 않은 코드를 찾지 못했습니다. 그러나 이것을 게시 해 주셔서 감사합니다. – Alister

+0

try/finally 블록 외부에서 Create 호출을 이동했습니다. 올바른 방법입니다.그렇지 않으면 Create 호출에 예외가있는 경우 코드는 초기화되지 않은 변수에서 Free를 호출하려고 시도합니다 (예외는 코드가 호출 문으로 되돌아 가지 않지만 except/finally 부분으로 직접 이동한다는 것을 의미 함을 기억하십시오. 변수는 결코 완료되지 않습니다). – HeartWare

답변

28

TRichEdit 컨트롤은 Windows의 RichEdit 컨트롤을 둘러싼 래퍼입니다. Windows의 컨트롤은 ... 잘 .. Windows이고, 그들은 창 핸들이 필요합니다. Delphi는 CreateWindow 또는 CreateWindowEx를 호출하여 Handle을 생성해야하며, 두 루틴 모두 유효한 부모 Window Handle이 필요합니다. Delphi는 컨트롤의 부모 핸들을 사용하려고합니다. 다행히 대체 생성자 (CreateParanted(HWND) 생성자)를 사용할 수 있으며 Microsoft의 멋진 사람들은 HWND_MESSAGE을 실제로 "창"(메시징 전용)이 필요하지 않은 창에 대한 부모로 사용하도록 구성했습니다.

이 코드는 예상대로 작동 : 저이 아닌 변환을, TRichEdit는 시작하는

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

위대한 트릭, 다시 질문을 업데이 트하자. – LaBracca

+1

부모를 정의하지 않고 TRichEdit 컨트롤 * 거의 *를 만드는 방법을 보여주기 때문에 이것을 수락 된 대답으로 설정했습니다. – LaBracca

+0

나에게도 CreateParented +1. – Despatcher

8

이것은 VCL이 작동하는 방식의 일부이며, 당신이하지 않을거야 무거운 임시 해결 방법없이 다르게 작동하도록하십시오. 하지만 부모가되기 위해 더미 양식을 정의 할 필요는 없습니다. 현재 양식을 사용하고 TRichEdit에 visible := false;을 설정하면됩니다.

성능을 향상시키려는 경우 결과 문자열을 작성하는 데 사용하는 루프를 제거 할 수 있습니다. 메모리를 많이 할당하고 복사해야합니다. TrichEdit.Lines의 Text 속성을 사용하여 각 행 사이에 CRLF를 가져오고 DelimitedText를 사용하여 공백과 같은 다른 항목을 가져옵니다. 그들은 한 번만 할당 된 내부 버퍼를 사용하므로 많은 텍스트로 작업하는 경우 연결 속도가 상당히 빨라집니다.

+0

+1에 대해 'Visible : = false' –

+0

TString의 이러한 기능에 대해 알지 못했습니다. 최종 버전을 올려서 질문을 업데이트하고, 런타임 생성 양식도 포함하여 함수가 "독립 실행 형"함수가됩니다. . – LaBracca

4

나는 DrawRichText을 사용하여 RichEdit 컨트롤없이 RTF를 그립니다. (IIRC이 Windowless Rich Edit Controls라고합니다.) 어쩌면 당신이 변환에도 사용할 수 있습니다 - 그러나 나는 이것을 시도 적이있다.

0

이 가장 helpfull을하고있다. 예상대로 그러나 이것은 작동하고 당신은 구분자 설정할 필요가 없습니다 :

// 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; 

어떻게 든 TStringStream 새로운 라인에있는 모든 단일 문자를두고 있기 때문에 일반에 변환의 TStringList를 "L"을 사용하고 있습니다를 .

편집 : 코드를 조금 더 멋지게 만들고 사용되지 않은 변수를 제거했습니다.

관련 문제