Autor Beitrag
NewMori
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 45
Erhaltene Danke: 1



BeitragVerfasst: Mo 26.07.10 11:08 
Hi,
ich schreibe gerade ein Memo mit Syntax Highlighting. Und habe dort Tabs zugelassen, beim zeichnen arbeite ich mit Canvas.TextWidth um die Breite des Textes zu ermitteln. Leider funktioniert dies bei einem Tab nicht, sodass der Schreibmarker zwar richtig springt, aber der Tab nur wie ein Leerzeichen gezeichnet wird, was dann zur folge hat, das der Marker an der falschen Stelle ist. Hat jemand eine Lösung wie ich die richtige Breite eines Tabs herrausbekomme, oder ist es eine feste Breite etc. Ich wäre für Hilfe sehr dankbar.

_________________
Es ist keine Kunst in ein Programm 20 Fehler zu schreiben. Die Kunst ist es das Programm dann noch zum laufen zu bekommen.
Gerd Kayser
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 632
Erhaltene Danke: 121

Win 7 32-bit
Delphi 2006/XE
BeitragVerfasst: Di 27.07.10 01:29 
Warum nimmst Du nicht ein RichEdit? Das beherrscht u. a. Tabulatoren und farbige Schrift.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19341
Erhaltene Danke: 1752

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Di 27.07.10 05:32 
user profile iconGerd Kayser hat folgendes geschrieben Zum zitierten Posting springen:
Warum nimmst Du nicht ein RichEdit? Das beherrscht u. a. Tabulatoren und farbige Schrift.
Hast du es mal versucht eine fertige Komponente für Syntaxhighlighting zu verwenden? Ich vermute nein...
Du kommst da nicht an alles heran, so dass das nicht gut funktioniert.

Die Breite eines Tabs ist ja z.B. kontextabhängig, je nach Implementierung. TextWidth kann ja nicht wissen wo in einer Zeile z.B. man sich befindet. Außerdem kann man die Breite eines Tabs in der Regel auch selbst definieren.

Das sinnvollste ist wohl einfach (wie Delphi selbst) für einen Tab eine feste Anzahl Leerzeichen zu verwenden, die man am besten auch einstellen kann.
NewMori Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 45
Erhaltene Danke: 1



BeitragVerfasst: Di 27.07.10 09:04 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Das sinnvollste ist wohl einfach (wie Delphi selbst) für einen Tab eine feste Anzahl Leerzeichen zu verwenden, die man am besten auch einstellen kann.

Ich werde mir das RichEdit nochmal anschauen. Mein Problem besteht nicht darin, dass ich nicht in der Lage wäre ein Tab 5 Leerzeichen lang zu machen oder alle vollen 100 Pixel erst den nächsten Text zu zeichnen. Das Problem liegt in dem Marker, ich weis nicht wie ich ihn manipulieren kann, sodass er bei "meinen Tabs" richtig springt.
(Kann mir vielleicht auch jemand sagen wo ich die Zeichenfunktion für makierte Texte findet, in dieser Zeile greift mein WM_PAINT komischerweise nicht, oder soll ich dafür besser nen neues Thema aufmachen?)

_________________
Es ist keine Kunst in ein Programm 20 Fehler zu schreiben. Die Kunst ist es das Programm dann noch zum laufen zu bekommen.
Gerd Kayser
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 632
Erhaltene Danke: 121

Win 7 32-bit
Delphi 2006/XE
BeitragVerfasst: Di 27.07.10 17:53 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Hast du es mal versucht eine fertige Komponente für Syntaxhighlighting zu verwenden? Ich vermute nein...
Du kommst da nicht an alles heran, so dass das nicht gut funktioniert.

Doch, ich habs heute Nachmittag probiert. :)

Kleines Beispiel:
ausblenden volle Höhe 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:
// uses RichEdit, StrUtils;

procedure TForm1.Button1Click(Sender: TObject);
begin
  RichEdit1.Clear;
  RichEdit1.Lines.Add('Satz: Ein kleiner Text.');
  RichEdit1.Lines.Add('Ein weiterer Satz.');
  RichEdit1.Lines.Add('Dieser Satz ist auch sehr kurz.')
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  Stelle    : integer;
  Suchwort  : string;
  ChrFormat : TCharFormat2;
  Position  : integer;
  Abbrechen : boolean;
begin
  Suchwort := 'Satz';

  // für Schrifthintergrundfarbe erforderlich
  FillChar(ChrFormat, SizeOf(TCharFormat2), 0);
  ChrFormat.cbSize := SizeOf(TCharFormat2);
  ChrFormat.dwMask := CFM_BackColor;                      // gelber Hintergrund
  ChrFormat.crBackColor := clYellow;

  Abbrechen := false;
  Stelle := 1;
  while not Abbrechen do
    begin
      Position := PosEx(SuchWort, RichEdit1.Text, Stelle);
      if Position > 0 then
        begin
          RichEdit1.SelStart := Position - 1;
          RichEdit1.SelLength := Length(Suchwort);
          RichEdit1.SelAttributes.Style := [fsUnderline];  // unterstrichen
          RichEdit1.SelAttributes.Color := clRed;          // rote Schriftfarbe
          // Schrift gelb hinterlegt
          SendMessage(RichEdit1.Handle, EM_SetCharFormat, SCF_Selection, LParam(@ChrFormat));
          Stelle := Position + Length(Suchwort);
        end
      else
        Abbrechen := true;
    end;
end;

Für diesen Beitrag haben gedankt: NewMori
NewMori Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 45
Erhaltene Danke: 1



BeitragVerfasst: Di 27.07.10 18:29 
@Gerd Kayser: Danke für die Mühe, ich habe es mal ausprobiert. Es gibt ein Problem, wenn ich Strings habe soll alles dazwischen gefärbt werden, dort habe ich dann kein Suchwort. Auch müsste ich den kompletten Text mit allen Wörten nach jeder Änderung durchlaufen. Das kann man zwar lösen aber etwas umständlicher. Ich würde sowieso das WM_PAINT Ereigniss überschreiben und den Text dann neu formatieren. Das Problem ist jetzt, dass ich das eigendlich schon hinbekommen habe, mir fehlt wie gesagt nur eine Funktion etc. wie ich herrausbekomme wo ich nach einem Tab weiter zeichnen muss, bzw ob ich den Cursor an die Stelle rücken kann wo ich weiter zeichnen will.

_________________
Es ist keine Kunst in ein Programm 20 Fehler zu schreiben. Die Kunst ist es das Programm dann noch zum laufen zu bekommen.
Chromic
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 31
Erhaltene Danke: 1

Windows 7 64bit
Turbodelphi Explorer, Lazarus, Prism Commandline, C# (VS 2010, #Develop
BeitragVerfasst: Di 27.07.10 18:35 
Hallo!

Hmm. TMemo + Syntaxhighlighting, TRichEdit + Syntaxhighlighting... Da fällt mir so auf die schnelle ne nette Komponente ein, die es schon gibt und sich in vielen Projekten (zB Lazarus) hervorragend bewährt: SynEdit.

mfg Chromic

_________________
Desktop-Anwendungen: Delphi
Web-Anwendungen: XHTML, CSS, PHP, SQLite, jQuery
NewMori Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 45
Erhaltene Danke: 1



BeitragVerfasst: Di 27.07.10 18:53 
@Chromic: Das habe ich auch schon gefunden. Ich würde das allerdings gerne selber schreiben, bzw nicht noch eine externe Klasse brauchen, denn falls Fehler auftreten wird es schwierig Hilfe zu bekommen.

_________________
Es ist keine Kunst in ein Programm 20 Fehler zu schreiben. Die Kunst ist es das Programm dann noch zum laufen zu bekommen.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19341
Erhaltene Danke: 1752

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Di 27.07.10 19:08 
user profile iconGerd Kayser hat folgendes geschrieben Zum zitierten Posting springen:
Doch, ich habs heute Nachmittag probiert. :)
Soweit ist das auch kein Problem, aber es geht vor allem um sehr performante Anpassungen bei Änderungen im Quelltext usw., und da kommt man mit den Standardkomponenten nicht weit.

Es hat schon einen Grund weshalb diese Komponenten alle nicht auf TMemo oder TRichEdit basieren. Sowas wie SynEdit selbst zu schreiben ist aber illusorisch, da würde man Jahre dran sitzen.

Es geht ja hier um eine sehr einfach gestrickte Komponente, die nicht so viele Funktionen hat.

Und was das Problem angeht:
Wie gesagt: Ein Tab hat keine systemweit feste Breite. Es ist deine Definition in deiner Komponente wie breit der sein soll. ;-)
NewMori Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 45
Erhaltene Danke: 1



BeitragVerfasst: Di 27.07.10 19:56 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Und was das Problem angeht:
Wie gesagt: Ein Tab hat keine systemweit feste Breite. Es ist deine Definition in deiner Komponente wie breit der sein soll. ;-)

Der Text fängt nach einem Tab, aber immer nach einem festen Muster wieder an, zB. nach den nächsten vollen 100 Pixeln etc. leider weis ich nicht wie ich den Textanfang errechnen kann. Wenn ich das nicht herrausfinde wäre es vielleicht möglich den Textcursor umzusetzen, ich habe bis jetzt aber noch nicht das Event,die Funktion etc. gefunden um selber die Position des Cursors in Pixeln setzen zu können.

_________________
Es ist keine Kunst in ein Programm 20 Fehler zu schreiben. Die Kunst ist es das Programm dann noch zum laufen zu bekommen.
NewMori Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 45
Erhaltene Danke: 1



BeitragVerfasst: Di 27.07.10 21:24 
Ich habe jetzt eine Zwischenlösung gefunden, bei Schrift Courier New und Schriftgröße 10 kann man X so berechnen:
ausblenden Delphi-Quelltext
1:
2:
Tab:=65;
X:=X-(X mod Tab)+Tab;


Ich suche jetzt nochmal nach einer Lösung für alle Schriftarten Größen etc. Solange benutze ich diesen Code.

_________________
Es ist keine Kunst in ein Programm 20 Fehler zu schreiben. Die Kunst ist es das Programm dann noch zum laufen zu bekommen.
Gerd Kayser
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 632
Erhaltene Danke: 121

Win 7 32-bit
Delphi 2006/XE
BeitragVerfasst: Di 27.07.10 22:01 
Versuchs mal damit:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
procedure TForm1.Button4Click(Sender: TObject);
var
  Position      : integer;
  PixelPosition : integer;
  Suchwort      : string;
begin
  Suchwort := 'Satz';
  Position := Pos(Suchwort, Memo1.Text) - 1
  PixelPosition := SendMessage(Memo1.Handle, EM_PosFromChar, Position, 0);
  ShowMessage('Zeichenposition: ' + IntToStr(Position) + #13#10 +
              'Pixelposition-X: ' + IntToStr(LoWord(PixelPosition))+ #13#10 +
              'PixelPosition-Y: ' + IntToStr(HiWord(PixelPosition)));
end;
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19341
Erhaltene Danke: 1752

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Di 27.07.10 22:30 
Das geht ja nur bei einem TMemo. :gruebel:
Gerd Kayser
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 632
Erhaltene Danke: 121

Win 7 32-bit
Delphi 2006/XE
BeitragVerfasst: Di 27.07.10 23:03 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Das geht ja nur bei einem TMemo. :gruebel:

RichEdit wollte er ja nicht. Des Menschen Wille ist nun einmal sein Himmelreich.

So geht es mit RichEdit:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
procedure TForm1.Button3Click(Sender: TObject);
var
  Position      : integer;
  PixelPosition : TPoint;
  Suchwort      : string;
begin
  Suchwort := 'Satz';
  Position := Pos(Suchwort, RichEdit1.Text) - 1;
  SendMessage(RichEdit1.Handle, EM_PosFromChar, wParam(@PixelPosition), lParam(Position));
  ShowMessage('Zeichenposition: ' + IntToStr(Position) + #13#10 +
              'Pixelposition-X: ' + IntToStr(PixelPosition.X)+ #13#10 +
              'PixelPosition-Y: ' + IntToStr(PixelPosition.Y));
end;

Ich würde persönlich aber ein RichEdit bevorzugen. Mit ein wenig Nachdenken bekommt man auch bei größeren Texten eine performante Lösung hin. Der Rechner ist jedenfalls mit der Abarbeitung der Funktionen schneller, als ich jemals werde tippen können.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19341
Erhaltene Danke: 1752

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mi 28.07.10 06:14 
Also ich hatte das so verstanden, dass es eine eigene Komponente ohne TMemo ist. Das ist auch die sinnvollste Variante wie gesagt.
NewMori Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 45
Erhaltene Danke: 1



BeitragVerfasst: Mi 28.07.10 09:30 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Also ich hatte das so verstanden, dass es eine eigene Komponente ohne TMemo ist. Das ist auch die sinnvollste Variante wie gesagt.

Ich benutze ein TMemo, nur das ich das WM_PAINT Ereigniss überschreibe.

_________________
Es ist keine Kunst in ein Programm 20 Fehler zu schreiben. Die Kunst ist es das Programm dann noch zum laufen zu bekommen.