Entwickler-Ecke

Sonstiges (Delphi) - Strings farblich hervorheben


SweeT_C - Mi 21.03.07 17:59
Titel: Strings farblich hervorheben
Moin,

kann man einzelne abschnitte aus einem Text zB mit strings farblich hervorheben ?

Mfg n Thx


ZeitGeist87 - Mi 21.03.07 18:29

Hallo!

Mit einem Richedit (Palette Win32):


Delphi-Quelltext
1:
2:
3:
 richedit1.selattributes.color:= clred;
 richedit1.selattributes.style:= [fsbold];
 richedit1.selText:= 'Dieser Text wird rot und fett dargestellt';


Über richedit1.selStart und richedit1.SelLength kannst du bestenden Text markieren und dann wie oben über


Delphi-Quelltext
1:
2:
 richedit1.selattributes.color:= clred;
 richedit1.selattributes.style:= [fsbold];


diesen "gestalten".

Hoffe ich hab dir einen kleinen Denkanstoss geben können!

LG
Stefan

//Edit: Ich denk ich programmier dir mal schnell n Beispiel


SweeT_C - Mi 21.03.07 18:39

user profile iconZeitGeist87 hat folgendes geschrieben:


//Edit: Ich denk ich programmier dir mal schnell n Beispiel

Danke! Mit ein BEispiel wirds für mich sicherlich etwas verständlicher.

Kann ich mit richedit1 auch direkt einen string auswählen und nicht einen bestimmten bereich eingeben ? Zum Beispiel hab ich einen Text und möchte immer das wort "tiefkühlpizza" hervorheben ohne zu kennen, wo es ist.


ZeitGeist87 - Mi 21.03.07 18:57

:)

Genau das Problem mit dem irgendwo im Text hat ich heut in der Arbeit, habs aber nicht gelöst, hab Feierabend gemacht :)

Aber da ich jetzt daheim bin, werd ich mir dran machen, etwas zu entwickeln!

Dazu kann ich glaub ich gut die FUnktion PosEx() gebrauchen und eine Rekursion...

LG
Stefan


GTA-Place - Mi 21.03.07 18:58


Delphi-Quelltext
1:
2:
RichEdit1.SelStart := Pos('Tiefkühlpizza', RichEdit1.Text) - 1;
RichEdit1.SelLength := Length('Tiefkühlpizza');


Geht dann aber nur beim 1. Vorkommen von Tieflkühlpizza.


ZeitGeist87 - Mi 21.03.07 19:01

Tja Fabian :)

Die Idee hat ich heut auch schon, allerdings wird da nur das erste Vorkommen "bearbeitet" :)


GTA-Place - Mi 21.03.07 19:04

Er hat ja auch nicht gesagt, dass es häufiger vorkommt. Außerdem: Siehe Edit.


ZeitGeist87 - Mi 21.03.07 19:08

Zitat:
immer das wort "tiefkühlpizza" hervorheben ohne zu kennen, wo es ist.


Ist für mich mehr als einmal :)

Und ok..ich schau aufs Edit :)


ZeitGeist87 - Mi 21.03.07 19:23

Beispiel wie versprochen im Anhang!

Allerdings wird nur das erste Vorkommen markiert.

Ich entwickel schnell noch die Funktion über den gesamten Text und update dann.

LG
Stefan


SweeT_C - Mi 21.03.07 19:41

user profile iconZeitGeist87 hat folgendes geschrieben:
Beispiel wie versprochen im Anhang!

Allerdings wird nur das erste Vorkommen markiert.

Ich entwickel schnell noch die Funktion über den gesamten Text und update dann.

LG
Stefan

Danke für das Programm. Ich verstehe, was du gemacht hast und Farbauswahl usw sind praktische Ideen *thumsup*

Ich hätt vielleicht ne Idee, wie man das "nur einmal" PRoblem lösen könnte, weiß aber nicht, wie ich es umsetzen kann. Was ist mit einer "while" schleife ? von der ersten Zeile des memofeldes bis zur letzen durchlaufen lassen ?


ZeitGeist87 - Mi 21.03.07 19:42

Die Idee ist nicht schlecht..nur dann brauchst du 3 schleifen :) und das dauert ewigkeiten!

Ich hab schon herausgefunden wie es funktionieren muss :)

PosEx ist die Lösung...

LG
Stefan


SweeT_C - Mi 21.03.07 20:04

hmm, ich weiß nicht genau, wie ich das mit PosEx machen soll. Hab heute erst mit strings angefangen ;) In dem Tut, das ich benutze wird das zweite vorkommen eines zeichens gefunden indem das erste plus 1 gerechnet wird. wenn ich das hier genauso machen wollte, müsste ich doch auch die Anzahl des vorkommens kennen ?

Über einen Denkanstoß wäre ich dankbar ;]


Blackheart666 - Mi 21.03.07 20:29

Vieleicht kannst Du mit dem hier was anfangen.
http://www.delphi-forum.de/viewtopic.php?t=67521&highlight=


ZeitGeist87 - Mi 21.03.07 21:04

Hab grad ne Lösung für mein eigenes Syntaxhighlighting-Problem entwickelt!

Funktioniert sogar wunderbar :)

Hier die neue Unit:


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:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
unit hauptprogramm;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, ComCtrls, Spin, StrUtils;

type RSyntax = record
      Begriff: String;
      Farbe: TColor;
      Style: TFontStyles;
end;

type
  TForm1 = class(TForm)
    databox: TRichEdit;
    Label1: TLabel;
    such_text: TEdit;
    GroupBox1: TGroupBox;
    schrift_farbe: TColorBox;
    Label2: TLabel;
    Label3: TLabel;
    schrift_size: TSpinEdit;
    check_fett: TCheckBox;
    check_kursiv: TCheckBox;
    check_unterstrichen: TCheckBox;
    Button1: TButton;
    Button2: TButton;
    function durchsuche(Suchbegriff: String; Textbaustein: TRichEdit; Offset: integer): integer;
    function doSyntax(Syntax: array of RSyntax; RichEdit: TRichEdit): Boolean;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private-Deklarationen }
    tempoffset: integer;
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;
  mySyntax: array of RSyntax;

implementation

{$R *.dfm}

function TForm1.doSyntax(Syntax: array of RSyntax; RichEdit: TRichEdit): Boolean;
{
  Funktion geht Syntax-Record durch und weist allen Funden die definierten Werte zu
}

var position: integer;
    i: integer;
begin;

 for i:= low(Syntax) to high(Syntax) do
 begin
  REPEAT
   position:= durchsuche(Syntax[i].Begriff, richedit, tempoffset);
   if position > 0  then
   begin
    RichEdit.SelStart:= position-1;
    RichEdit.SelLength:= length(Syntax[i].Begriff);
    RichEdit.SelAttributes.Color:= Syntax[i].Farbe;
    RichEdit.SelAttributes.Style:= Syntax[i].Style;
   end;
  UNTIL (position = 0);
 end;
 
end;

function TForm1.durchsuche(suchbegriff: string; Textbaustein: TRichEdit; Offset: Integer): Integer;
{
  Funktion durchsucht übergeben Text (Richedit) nach Vorkommen des Suchbegriffs
}

begin;
 tempoffset:= PosEx(suchbegriff, Textbaustein.text, offset+1);
 durchsuche:= tempoffset;
end;

procedure TForm1.Button1Click(Sender: TObject);
var posmerker: integer;
    Stil: TFontStyles; //Schritstyles zusammenfassen
begin
 //INIT
 posmerker:= 0;

 //Keine Schriftstyles
 Stil:= [];

 //Text suchen

 posmerker:= pos(such_text.Text, databox.text);
 if posmerker > 0 then
 begin
  //Textanfang setzen
  databox.SelStart:= posmerker-1;

  //Länge setzen (im Prinzip entspricht das dem Markieren);
  databox.SelLength:= length(such_text.text);

  //Und die Attribute darauf anwenden;

  //Schriftfarbe
  databox.SelAttributes.Color:= schrift_farbe.Selected;

  //Schriftgröße
  databox.SelAttributes.Size:= schrift_size.Value;

  //fett, kursiv und unterstrichen
  if check_fett.checked = true then
   Stil:= Stil + [fsbold];

  if check_kursiv.Checked = true then
   Stil:= Stil + [fsitalic];

  if check_unterstrichen.checked = true then
   Stil:= Stil + [fsunderline];

  //Schriftstyle zuweisen
  databox.SelAttributes.Style:= Stil;

  //Und Cursorpos hinter Text setzen
  databox.SelStart:= databox.SelStart + databox.SelLength;
 end
 else
  messagebox(application.handle, 'Textpassage wurde nicht gefunden''Kein Treffer', MB_IconWARNING);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
 setlength(mySyntax, 2);

 mySyntax[0].Begriff:= 'Demo';
 mySyntax[0].Farbe:= clred;
 mySyntax[0].Style:= [fsbold];

 mySyntax[1].Begriff:= 'die';
 mySyntax[1].Farbe:= clgreen;
 mySyntax[1].Style:= [fsitalic];

 //Syntaxhighlighting aufrufen
 doSyntax(mySyntax, databox);
end;

end.


Sucht noch Case-Sensitive

LG
Stefan


ZeitGeist87 - Do 22.03.07 14:50

Ist für Highlighting On-the-Fly allerdings nicht zu gebrauchen :)

Noch nicht! :mrgreen:

Denk ich stell heute abend die neue Version online.

Allerdings:

Hat vielleicht schon mal einer von euch sowas ähnliches gemacht?
Hinweise auf SynEdit bitte ersparen :)

Mich interessieren nur eure eigenen Entwicklungen/Ideen.

Danke!

LG
Stefan


Blackheart666 - Do 22.03.07 15:17

Vieleicht ist das ganz Interessant, hab die Seite nicht mehr gefunden deswegen als Anhang zip(PDF)


SweeT_C - Sa 24.03.07 21:45

Ich hab mich mal selbst auf die Suche einer Lösung gemacht und, glaube ich, eine gefunden. Allerdings funzt die Umsetzung nicht *ratlos guck*
Mein Gedanke war, den string zum einfärben zu suchenm und position und länge in einem dynamischen array zu speichern. Das ganze in einer Schleife solange bis der STring nciht mehr auftaucht. Darauf soll eine zweite SChleife aufgerufen werden, die die Daten aus dem Array ausliest, die Strings an den entsprechenden stellen wieder wieder einfügt und dann einfärbt.

Allerdings scheiterts bei mir schon daran, dass sich mein Programm nciht mehr reagiert, wenn ich die prozedur aufrufe. Ich denk mal, die Schleife wird nciht beendet.
Hier der Text, den ich nehme:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
<Nasse>
ich schreib dich in den nächsten tagen mal an und frag ich über physik aus
<Nasse>
hab aber kjetz keine lust mehr
<SweeT_C>
-.-
<Nasse>
*JOKINGLY*
<Nasse>
wäste mal früher gekommen
<SweeT_C>
dann ?


und die PRozedur


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:
procedure TForm1.Button8Click(Sender: TObject);
var s, name1, name2:string;
var pp, ll, i, o:integer;
var hallo:array of integer;
begin
  name1:='<'+edit3.text+'>';
  name2:='<'+edit4.text+'>';
  s:=richedit2.text;
  i:=0;
  Setlength(hallo, 0);
begin
  while Pos(name1, s)<>0 do
    Setlength(hallo,i+2);
    o:=i+1;
    hallo[i]:=Pos(name1, s);
    hallo[o]:=Length(name1);
    Delete(s, pp, ll);
    i:=i+2;
end;
  showmessage('completed');




end;


ZeitGeist87 - Sa 24.03.07 22:04

user profile iconSweeT_C hat folgendes geschrieben:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
procedure TForm1.Button8Click(Sender: TObject);
var s, name1, name2:string//einmal var reicht, auch für 20 Zeilen
{var} pp, ll, i, o:integer;
{var} hallo:array of integer;
begin
 name1:='<'+edit3.text+'>';
 name2:='<'+edit4.text+'>';
 s:=richedit2.text;
 i:=0;
 Setlength(hallo, 0);
 while Pos(name1, s)<>0 do
 begin
   Setlength(hallo,i+2);
   o:=i+1;
   hallo[i]:=Pos(name1, s);
   hallo[o]:=Length(name1);
   Delete(s, pp, ll);
   i:=i+2;
 end;
 showmessage('completed');
end;


LG
Stefan


SweeT_C - So 25.03.07 00:05

Habs korriegiert, aber das Programm hängt sich immernoch auf :?


GTA-Place - So 25.03.07 00:10

pp ist undefiniert. Es wird demnach nichts/falsches gelöscht.


SweeT_C - So 25.03.07 18:42

user profile iconGTA-Place hat folgendes geschrieben:
pp ist undefiniert. Es wird demnach nichts/falsches gelöscht.

:autsch: Hätt man auch selbst drauf kommen können. Danke!