Einzelnen Beitrag anzeigen

Benutzerbild von fkerber
fkerber
(CodeLib-Manager)

Registriert seit: 9. Jul 2003
Ort: Ensdorf
6.723 Beiträge
 
Delphi XE Professional
 
#1

TRichedit - Speichern inkl. Links

  Alt 18. Mai 2008, 10:29
Hi!

Da seitens Microsoft das Abspeichern von mit CFM_Link markierten Wörtern in einem RichEdit nicht unterstützt wird, hat taaktaak hier eine alternative Lösung vorgestellt:

Grundidee ist, die CFM_Link-Formatierung vor dem Speichern in eine andere Formatierung zu konvertieren und dies nach dem Einlesen aus der Datei wieder rückgängig zu machen. Diese "temporäre Hilfsformatierung" muss nun eine sein, die a) auch gespeichert und b) vom Anwender nicht vermisst wird.

Die Wahl fiel auf CFM_Revised. Insgesamt sind folgende 4 Prozeduren/Funktionen notwendig:

Delphi-Quellcode:
procedure SetLink(re:TRichEdit;Position:Integer);
  var NewRange : TCharRange;
  begin
    NewRange.cpMin:=Position;
    NewRange.cpMax:=Position+1;
    SendMessage(re.Handle,EM_ExSetSel,0,LParam(@NewRange));
    SendMessage(re.Handle,EM_SetCharFormat,SCF_Selection,LParam(@CF2Set));
  end;
Delphi-Quellcode:
function reIsLink(re:TRichEdit;Position:Integer):Boolean;
var CF2 : TCharFormat2;
    OldRange,NewRange : TCharRange;
begin
  FillChar(CF2,SizeOf(CF2),0);
  CF2.cbSize:=SizeOf(CF2);
  CF2.dwMask:=CFM_Link;

  NewRange.cpMin:=Position;
  NewRange.cpMax:=Position+1;

  SendMessage(re.Handle,EM_ExGetSel,0,LParam(@OldRange));
  SendMessage(re.Handle,EM_ExSetSel,0,LParam(@NewRange));
  SendMessage(re.Handle,EM_GetCharFormat,SCF_Selection,LParam(@CF2));
  SendMessage(re.Handle,EM_ExSetSel,0,LParam(@OldRange));

  Result:=CF2.dwEffects and CFE_Link=CFE_Link;
end;
Delphi-Quellcode:
procedure reSetRevised(re:TRichEdit;Start,Length:Integer;SwitchOn:Boolean);
var CF2 : TCharFormat2;
    OldRange,NewRange : TCharRange;
begin
  FillChar(CF2,SizeOf(CF2),0);
  CF2.cbSize :=SizeOf(CF2);
  CF2.dwMask :=CFM_Revised;
  if SwitchOn then CF2.dwEffects:=CFE_Revised;

  NewRange.cpMin:=Start;
  NewRange.cpMax:=Start+Length;

  SendMessage(re.Handle,EM_ExGetSel,0,LParam(@OldRange));
  SendMessage(re.Handle,EM_ExSetSel,0,LParam(@NewRange));
  SendMessage(re.Handle,EM_SetCharFormat,SCF_Selection,LParam(@CF2));
  SendMessage(re.Handle,EM_ExSetSel,0,LParam(@OldRange));
end;
Delphi-Quellcode:
function IsRevised(re:TRichEdit;Position:Integer):Boolean;
  var NewRange : TCharRange;
  begin
    NewRange.cpMin:=Position;
    NewRange.cpMax:=Position+1;
    SendMessage(re.Handle,EM_ExSetSel,0,LParam(@NewRange));
    SendMessage(re.Handle,EM_GetCharFormat,SCF_Selection,LParam(@CF2Get));
    Result:=CF2Get.dwEffects and CFE_Revised=CFE_Revised;
  end;
Beispielhaft könnte eine Prozedur zum Laden dann so aussehen:

Delphi-Quellcode:
procedure Load(var RE:TRichEdit;FName:String);
var i : Integer;
    CF2Get,
    CF2Set : TCharFormat2;
 
  FillChar(CF2Get,SizeOf(CF2Get),0);
  CF2Get.cbSize:=SizeOf(CF2Get);
  CF2Get.dwMask:=CFM_Revised;

  FillChar(CF2Set,SizeOf(CF2Set),0);
  CF2Set.cbSize :=SizeOf(CF2Set);
  CF2Set.dwMask :=CFM_Link;
  CF2Set.dwEffects:=CFE_Link;
 
  RE.Lines.BeginUpdate;
  RE.Lines.LoadFromFile(FName);

  for i:=0 to length(RE.Text)-1 do // konvertiere Revised-Attribut
    if IsRevised(RE,i) then SetLink(RE,i); // zurück in Link-Attribut

  RE.Lines.EndUpdate;

  // ...
end;
... und so zum Speichern:
Delphi-Quellcode:
procedure reSave(var RE:TRichEdit;FName:String);
var i : Integer;
begin
  for i:=0 to length(RE.Text)-1 do // konvertiere Link-Attribut
    if reIsLink(RE,i) then reSetRevised(RE,i,1,true); // in Revised-Attribut
  RE.Lines.SaveToFile(FName); // und nun Speichern
end;
Allerdings bleibt anzumerken, dass die Prozeduren / Funktionen nicht die schnellsten sind und durchaus noch Optimierungsbedarf besteht!
Frederic Kerber
  Mit Zitat antworten Zitat