| Autor |
Beitrag |
NewMori
      
Beiträge: 45
Erhaltene Danke: 1
|
Verfasst: 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
      
Beiträge: 632
Erhaltene Danke: 121
Win 7 32-bit
Delphi 2006/XE
|
Verfasst: Di 27.07.10 01:29
Warum nimmst Du nicht ein RichEdit? Das beherrscht u. a. Tabulatoren und farbige Schrift.
|
|
jaenicke
      
Beiträge: 19341
Erhaltene Danke: 1752
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Di 27.07.10 05:32
Gerd Kayser hat folgendes geschrieben : | | 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 
      
Beiträge: 45
Erhaltene Danke: 1
|
Verfasst: Di 27.07.10 09:04
jaenicke hat folgendes geschrieben : | | 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
      
Beiträge: 632
Erhaltene Danke: 121
Win 7 32-bit
Delphi 2006/XE
|
Verfasst: Di 27.07.10 17:53
jaenicke hat folgendes geschrieben : | 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:
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:
| 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';
FillChar(ChrFormat, SizeOf(TCharFormat2), 0); ChrFormat.cbSize := SizeOf(TCharFormat2); ChrFormat.dwMask := CFM_BackColor; 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]; RichEdit1.SelAttributes.Color := clRed; 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 
      
Beiträge: 45
Erhaltene Danke: 1
|
Verfasst: 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
      
Beiträge: 31
Erhaltene Danke: 1
Windows 7 64bit
Turbodelphi Explorer, Lazarus, Prism Commandline, C# (VS 2010, #Develop
|
Verfasst: 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 
      
Beiträge: 45
Erhaltene Danke: 1
|
Verfasst: 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
      
Beiträge: 19341
Erhaltene Danke: 1752
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Di 27.07.10 19:08
Gerd Kayser hat folgendes geschrieben : | 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 
      
Beiträge: 45
Erhaltene Danke: 1
|
Verfasst: Di 27.07.10 19:56
_________________ Es ist keine Kunst in ein Programm 20 Fehler zu schreiben. Die Kunst ist es das Programm dann noch zum laufen zu bekommen.
|
|
NewMori 
      
Beiträge: 45
Erhaltene Danke: 1
|
Verfasst: 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:
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
      
Beiträge: 632
Erhaltene Danke: 121
Win 7 32-bit
Delphi 2006/XE
|
Verfasst: Di 27.07.10 22:01
Versuchs mal damit:
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
      
Beiträge: 19341
Erhaltene Danke: 1752
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Di 27.07.10 22:30
Das geht ja nur bei einem TMemo. 
|
|
Gerd Kayser
      
Beiträge: 632
Erhaltene Danke: 121
Win 7 32-bit
Delphi 2006/XE
|
Verfasst: Di 27.07.10 23:03
|
|
jaenicke
      
Beiträge: 19341
Erhaltene Danke: 1752
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: 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 
      
Beiträge: 45
Erhaltene Danke: 1
|
Verfasst: Mi 28.07.10 09:30
jaenicke hat folgendes geschrieben : | | 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.
|
|