Entwickler-Ecke

Grafische Benutzeroberflächen (VCL & FireMonkey) - Fehler in TFindDialog ...!


Hochhaus - So 11.11.12 18:01
Titel: Fehler in TFindDialog ...!
Hallo allerseits !

im folgenden Code finde ich den Fehler nicht. Ich bitte um Hilfe ! Manchmal sieht man den Wald vor lauter Bäumen nicht mehr.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
Procedure TFrmChild.FindX(Sender: TObject);
var
  FoundAt: LongInt;
  StartPos, ToEnd: Integer;
  mySearchTypes : TSearchTypes;
  myFindOptions : TFindOptions;
begin
 With Sender as TFindDialog Do Begin
  mySearchTypes := [];
  with Memo1 do
  begin
    if frMatchCase in Options then
       mySearchTypes := mySearchTypes + [stMatchCase];
    if frWholeWord in Options then
       mySearchTypes := mySearchTypes + [stWholeWord];
    { Begin the search after the current selection, if there is one. }
    { Otherwise, begin at the start of the text. }
    if SelLength <> 0 then
      StartPos := SelStart + SelLength
    else
      StartPos := 0;
    { ToEnd is the length from StartPos through the end of the
      text in the rich edit control. }

    ToEnd := Length(Text) - StartPos;
    FoundAt := FindText(FindText, StartPos, ToEnd, mySearchTypes);      <------
    if FoundAt <> -1 then
    begin
      SetFocus;
      SelStart := FoundAt;
      SelLength := Length(FindText);
    end
    else Beep;
  end;
 End;
End{* FindX *}


Fehlermeldung des Compilers:
[DCC Fehler] CHILD.PAS(283): E2066 Operator oder Semikolon fehlt
[DCC Fehler] CHILD.PAS(283): E2010 Inkompatible Typen: 'Integer' und 'string'
[DCC Fataler Fehler] MAINX.PAS(124): F2063 Verwendete Unit 'CHILD.PAS' kann nicht compiliert werden


Vielen Dank für die Hilfe !


Hochhaus


Mathematiker - So 11.11.12 18:13

Hallo,

Delphi-Quelltext
1:
    FoundAt := FindText(FindText, StartPos, ToEnd, mySearchTypes);      <------                    

Soll FindText ein rekursiver Aufruf sein? Oder meinst Du

Delphi-Quelltext
1:
FindText(FindDialog1.FindText, StartPos, ToEnd, mySearchTypes);                    


Beste Grüße
Mathematiker


Hochhaus - So 11.11.12 18:27

Hallo,

ich habe den Text aus der Delphi-Hilfe kopiert und an mein Projekt adaptiert. Es sollte der Zeile

-->

Delphi-Quelltext
1:
FoundAt := FindText(FindDialog1.FindText, StartPos, ToEnd, mySearchTypes);                    


entsprechen.

Gruss,


Hochhaus


Mathematiker - So 11.11.12 18:37

Hallo,
nach meiner Kenntnis hat die Komponente memo keine Methode findtext, dagegen die Komponente richedit, d.h. mit

Delphi-Quelltext
1:
FoundAt := richedit1.FindText((Sender as TFindDialog).FindText, StartPos, ToEnd, mySearchTypes);                    

dürfte es keine Probleme geben.

Beste Grüße
Mathematiker


jaenicke - So 11.11.12 18:38

Mach erstmal das dämliche with weg, dann siehst du auch den Fehler... :roll:

Es gibt einmal die Funktion FindText (aber nur beim RichEdit, nicht bei einem Memo, falls Memo1 ein Memo ist) und einmal die Eigenschaft FindText des Dialogs. Das ist dann nun einmal nicht eindeutig, wenn du mit with herumspielst.
Nicht umsonst ist with in diversen Firmen verboten und wurde mit XE3 auch endlich aus den Delphiquelltexten entfernt.


Hochhaus - So 11.11.12 18:46

Moderiert von user profile iconNarses: Komplett-Zitat des letzten Beitrags entfernt.

Ich verwende tatsächlich ein Memo und nicht ein Richedit. Das Richedit brachte andere Probleme mit sich - siehe andere Themen von mir. Der Code ist also so oder so nicht lauffähig, selbst wenn ich das "With .. Do Begin " weglassen würde.

Gruss,


Hochhaus


Hochhaus - Mo 12.11.12 10:01

Hallo !

Ich habe nun doch wieder ein Richedit verwendet. Der Suchen-Dialog läuft nun korrekt (Ein Dankeschön an Mathematiker), der Ersetzen - Dialog jedoch nicht. Solange ein Suchbegriff durch einen total neuen ersetzt wird, funktioniert es prima. Sobald ich aber "XYZ" ersetze durch "XYZ!!", wird beim Alles ersetzen der erste Begriff unendlich oft mit !!!! wiederholt. Sieht jemand, warum ? Und was man tun kann ?


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
Procedure TFrmChild.FindX(Sender: TObject);
var
  FoundAt: LongInt;
  StartPos, ToEnd: Integer;
  mySearchTypes : TSearchTypes;
  myFindOptions : TFindOptions;
begin
 With Sender as TFindDialog Do Begin
  mySearchTypes := [];
  with RichEdit1 Do
  Begin
    If frMatchCase in Options then
       mySearchTypes := mySearchTypes + [stMatchCase];
    If frWholeWord in Options then
       mySearchTypes := mySearchTypes + [stWholeWord];
    { Begin the search after the current selection, if there is one. }
    { Otherwise, begin at the start of the text. }
    If SelLength <> 0 then
      StartPos := SelStart + SelLength
    Else
      StartPos := 0;
    { ToEnd is the length from StartPos through the end of the
      text in the rich edit control. }

    ToEnd := Length(Text) - StartPos;
    FoundAt := RichEdit1.FindText((Sender as TFindDialog).FindText,
     StartPos, ToEnd, mySearchTypes);
    If FoundAt <> -1 then
    Begin
      SetFocus;
      SelStart := FoundAt;
      SelLength := Length((Sender as TFindDialog).FindText);
    End
    Else Beep;
  End;
 End;
End{* FindX *}


Procedure TFrmChild.ReplaceX(Sender: TObject);
Begin
  With Sender As TReplaceDialog Do Begin
    While True Do Begin
      If RichEdit1.SelText <> FindText Then
        FindX(Sender);
      If RichEdit1.SelLength = 0 Then Break;
      RichEdit1.SelText := ReplaceText;
      If Not(frReplaceAll In Options) Then Break;
    End;
  End;
End{* ReplaceX *}



Danke und Gruss


Hochhaus


Mathematiker - Mo 12.11.12 10:43

Hallo Hochhaus,
warum verwendest Du nicht eine leicht modifizierte Variante der Delphi-Hilfe-Lösung:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
procedure TForm1.ReplaceDialog1Replace(Sender: TObject);
var SelPos: Integer;
begin
  with TReplaceDialog(Sender) do
  begin
    repeat
      SelPos := Pos((Sender As TReplaceDialog).FindText, richedit1.Lines.Text);
      if SelPos > 0 then
      begin
        richedit1.SelStart := SelPos - 1;
        richedit1.SelLength := Length(FindText);
        richedit1.SelText := ReplaceText;
      end;
    until selpos=0;
  end;
end;

Das müsste, meiner Meinung nach, funktionieren. Ein Problem wird noch die Berücksichtung der Groß- und Kleinschreibung werden, aber das lässt sich auch lösen.

@Jaenicke: Bevor Du wegen with meckerst (Du hast ja recht!). So, wie von mir angegeben, steht es in der Delphi-Hilfe.

Beste Grüße
Mathematiker


jaenicke - Mo 12.11.12 10:52

Es funktioniert auch wie er es hatte, nur ist die Markierung nach dem Setzen von SelText weg. Dementsprechend muss man die wieder setzen, wenn man daran festmacht, ob man von Beginn des Textes an sucht:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
function FindInRichEdit(const AFindDialog: TFindDialog; const ATargetRichEdit: TRichEdit): Boolean;
var
  FoundAt: LongInt;
  StartPos, ToEnd: Integer;
  mySearchTypes: TSearchTypes;
begin
  mySearchTypes := [];
  if frMatchCase in AFindDialog.Options then
    mySearchTypes := mySearchTypes + [stMatchCase];
  if frWholeWord in AFindDialog.Options then
    mySearchTypes := mySearchTypes + [stWholeWord];
  { Begin the search after the current selection, if there is one. }
  { Otherwise, begin at the start of the text. }
  if ATargetRichEdit.SelLength <> 0 then
    StartPos := ATargetRichEdit.SelStart + ATargetRichEdit.SelLength
  else
    StartPos := 0;
  { ToEnd is the length from StartPos through the end of the
    text in the rich edit control. }

  ToEnd := Length(ATargetRichEdit.Text) - StartPos;
  FoundAt := ATargetRichEdit.FindText(AFindDialog.FindText, StartPos, ToEnd, mySearchTypes);
  Result := FoundAt <> -1;
  if Result then
  begin
    ATargetRichEdit.SetFocus;
    ATargetRichEdit.SelStart := FoundAt;
    ATargetRichEdit.SelLength := Length(AFindDialog.FindText);
  end;
end;

procedure TForm408.FindX(Sender: TObject);
begin
  if not FindInRichEdit(Sender as TFindDialog, RichEdit1) then
    Beep;
end;

procedure TForm408.ReplaceX(Sender: TObject);
var
  ReplaceDlg: TReplaceDialog;
begin
  ReplaceDlg := Sender As TReplaceDialog;
  while FindInRichEdit(ReplaceDlg, RichEdit1) Do
  begin
    RichEdit1.SelText := ReplaceDlg.ReplaceText;
    RichEdit1.SelStart := RichEdit1.SelStart - Length(ReplaceDlg.ReplaceText);
    RichEdit1.SelLength := Length(ReplaceDlg.ReplaceText);
    if not(frReplaceAll in ReplaceDlg.Options) then
      Break;
  end;
end;

// EDIT:
user profile iconMathematiker hat folgendes geschrieben Zum zitierten Posting springen:
@Jaenicke: Bevor Du wegen with meckerst (Du hast ja recht!). So, wie von mir angegeben, steht es in der Delphi-Hilfe.
Schlimm genug, das wurde in den VCL-/RTL-Quelltexten aber mit XE3 wohl endlich geändert...


Hochhaus - Mo 12.11.12 10:58

Super ! Du bist ein Super-Progrmmiierer ! Es geht auf Anhieb, fehlerfrei !

Danke !!!


Hochhaus