Text ersetzen


Um Text ersetzen zu können, müssen wir diesen auch erst einmal suchen. Am Prinzip, das wir im letzten Kapitel besprochen haben, ändert sich also nicht viel. Interessant wird es erst, wenn wir den gesuchten alten Text gefunden haben. Wie gehabt, auch er wird markiert:

FindRec.chrg.cpMin := FindPos;
FindRec.chrg.cpMax := FindPos + lstrlen(OldText);
SendMessage(rEdit,EM_EXSETSEL,0,LPARAM(@FindRec.chrg));

Aber dann ersetzen wir ihn mit Hilfe der Nachricht "EM_REPLACESEL" durch den neuen Text:

SendMessage(rEdit,EM_REPLACESEL,WPARAM(true),LPARAM(NewText));

Der wParam-Wert TRUE sagt in diesem Fall aus, dass dieses Ersetzen ggf. rückgängig gemacht werden kann. Dazu muss Ihr Programm über eine entsprechende Undo-Funktion verfügen. Der lParam-Wert ist, wie Sie sehen können, ein Zeiger auf den Textpuffer mit dem neuen String.

Ebenfalls interessant ist die Gestaltung der Prozedur "ReplText". Da der Anwender im Ersetzendialog auch den Button "Alles ersetzen" anklicken kann, müssen wir die Suche in diesem Fall entsprechend oft wiederholen. Ich habe mich für eine repeat-Schleife entschieden, die erst verlassen wird, wenn das gesuchte Wort nicht (mehr) vorhanden ist, bzw. wenn der Anwender nur den Button "Ersetzen" benutzt hat:

repeat
  { Text suchen }
if(FindPos > 0) then begin { Text ersetzen } end else begin { Fehlermeldung } end; until(FindPos <= 0) or (not ReplaceAll);

Alles, was ich eben erwähnte (das Suchen, das Markieren und das Ersetzen), spielt sich innerhalb dieser Schleife ab.


Ich möchte daher an dieser Stelle noch einmal kurz auf die, auch im letzten Kapitel erwähnte Nachricht FINDMSGSTRING eingehen. Natürlich wird sie auch hier gesendet, wenn wir den Ersetzendialog benutzen.
Der Ersetzendialog des Systems bietet übrigens auch einen "Weiter suchen"-Button an. Da wir diese Funktion bereits implementiert haben, müssen wir uns darum nicht kümmern. Es steht allerdings keine Richtungswahl zur Verfügung; es wird also generell in Richtung Textende gesucht.

Um nun die eigentliche Ersetzenfunktion des Editors aufrufen zu können, müssen wir also wieder nur die Flags berücksichtigen. Wir prüfen, ob die Flags FR_REPLACE (Button "Ersetzen") oder FR_REPLACEALL (Button "Alles ersetzen") vorhanden sind und rufen in dem Fall die neue Prozedur "ReplText" auf:

if(FindParam.Flags and FR_REPLACE = FR_REPLACE) or
  (FindParam.Flags and FR_REPLACEALL = FR_REPLACEALL) then
ReplText(FindParam.hWndOwner,FindParam.lpstrFindWhat,
  FindParam.lpstrReplaceWith,
  FindParam.Flags and FR_DOWN = FR_DOWN,
  FindParam.Flags and FR_MATCHCASE = FR_MATCHCASE,
  FindParam.Flags and FR_WHOLEWORD = FR_WHOLEWORD,
  FindParam.Flags and FR_REPLACEALL = FR_REPLACEALL);

Die unterscheidet sich von der Suchenfunktion aus dem letzten Kapitel eigentlich nur darin, dass hier der neue String, der anstelle des alten eingefügt werden soll, angegeben werden muss, und dass der letzte Parameter darüber entscheidet, ob nur eins oder alle Vorkommen des alten Strings ersetzt werden sollen.