Autor |
Beitrag |
hRb
      
Beiträge: 292
Erhaltene Danke: 12
|
Verfasst: Sa 18.05.13 00:11
Hallo,
Ich möchte über einem Textfeld (Richedit1) ein Liniel anzeigen (Richedit2) und habe im Forum Befehle gefunden, die etwas abgewandelt zwei übereinander stehende Richedit miteinander horizontal synchronisieren. Dies funktioniert wie gewünscht, wenn der Scrollbalken von Richedit1 mit der Maus verschoben wird. Die Procedure reagiert jedoch nicht auf automatisches Scrollen wenn ich im Textfeld schreibe oder mit den Cursor-Tasten Pos1 bzw. Ende navigiere. Wer kann helfen?
Vielleicht gibt es auch eine viel einfachere Methode als zwei Richedit, da das Liniel (Richedit2) nur eine Zeile enthält und neben fortlaufenden Zahlen nur noch gesetzte Tabulatormarken anzeigt. Wenn ich z.B. wüsste, welche Zeile/Spalte am linken oberen Eck von Richedit1 steht, könnte ich in einem Label-Objekt das Lineal darstellen. Nachstehend meine Befehlsfolge.
Ich danke im Voraus.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| private PRichEdWndProc, POldWndProc: Pointer; procedure RichEdWndProc(var Msg: TMessage);
procedure TForm1.RichEdWndProc(var Msg: TMessage); begin Msg.Result := CallWindowProc(POldWndProc, RichEdit1.Handle, Msg.Msg, Msg.wParam, Msg.LParam); if (Msg.Msg = WM_HSCROLL) then begin RichEdit2.Perform(Msg.Msg, Msg.wParam, Msg.LParam); SetScrollPos(RichEdit2.Handle, SB_HORZ, HIWORD(Msg.LParam), True); end; end; |
Moderiert von Martok: Delphi-Tags hinzugefügt
|
|
jaenicke
      
Beiträge: 19326
Erhaltene Danke: 1749
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Sa 18.05.13 08:20
Statt zwei RichEdits findest du in der Demo zu TRichEdit eine viel einfachere Variante, mit der du auch Tabs setzen kannst usw., indem ein Ruler benutzt wird. Die Demo findest du in deinen Beispielen unter Samples\Delphi\VCL\RichEdit. Also z.B. unter:
Quelltext 1:
| C:\Users\Public\Documents\RAD Studio\11.0\Samples\Delphi\VCL\RichEdit |
Dort wird beim Scrollen dieses Lineal aber auch nicht mitgescrollt, für dein eigentliches Problem hilft dir das also auch nicht...
|
|
hRb 
      
Beiträge: 292
Erhaltene Danke: 12
|
Verfasst: Mo 27.05.13 18:17
Tatsächlich geht es bei meiner Frage um mehr. Das mit dem Ruler kenne ich.
Wenn also jemand weiss wie man die Spalte/Zeile der linken oberen Ecke in Richedit abfragen bzw. positionieren kann, wäre dies super.
Alternativ auch Befehle, bei der Richedit2 mit-Scrollt beim Schreiben in Richedit1.
|
|
Gerd Kayser
      
Beiträge: 632
Erhaltene Danke: 121
Win 7 32-bit
Delphi 2006/XE
|
Verfasst: Mi 29.05.13 04:21
hRb hat folgendes geschrieben : | Wenn also jemand weiss wie man die Spalte/Zeile der linken oberen Ecke in Richedit abfragen bzw. positionieren kann, wäre dies super.
Alternativ auch Befehle, bei der Richedit2 mit-Scrollt beim Schreiben in Richedit1. |
Die Abfrage auf Zeilen und Spalten wird Dir nichts bringen, weil Zeilen abhängig vom verwendeten Font und der Fontgröße unterschiedlich hoch sein können. Spalten (wie auf einem karierten Blatt Papier) gibt es beim RichEdit nicht. Jedes Zeichen ist unterschiedlich breit (abhängig vom Font, der Fontgröße und dem Zeichen). Ein W ist nun einmal breiter als ein kleines L. Wenn die erste sichtbare Zeile eine Leerzeile (also nicht mit Leerzeichen aufgefüllt) ist, bekommst Du als Rückgabewert immer das 0. Zeichen zurück. Teste es mal aus:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| procedure TForm1.Button1Click(Sender: TObject); var Zeile : integer; Zeichen : integer; Spalte : integer; Bereich : TPoint; begin Bereich := Point(3, 3); Zeichen := SendMessage(RichEdit1.Handle, EM_CharFromPos, 0, lParam(@Bereich)); Zeile := SendMessage(RichEdit1.Handle, EM_ExLineFromChar, 0, Zeichen); Spalte := Zeichen - SendMessage(RichEdit1.Handle, EM_LineIndex, Zeile, 0); Label1.Caption := 'Zeile: ' + IntToStr(Zeile); Label2.Caption := 'Spalte: ' + IntToStr(Spalte); end; |
Es ist also besser, die Pixel-Koordinaten oben links in einem RichEdit abzufragen und diesen Wert im zweiten RichEdit zu setzen.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| procedure TForm1.Button2Click(Sender: TObject); var Koordinaten : TPoint; begin SendMessage(RichEdit1.Handle, EM_GetScrollPos, 0, lParam(@Koordinaten)); SendMessage(RichEdit2.Handle, EM_SetScrollPos, 0, lParam(@Koordinaten)); end; |
Du musst das lediglich in die entsprechenden Ereignisse bzw. Messages einbauen, dann sollte es wie gewünscht funktionieren.
Edit: Kleinen Flüchtigkeitsfehler berichtigt (wParam durch lParam ersetzt).
Zuletzt bearbeitet von Gerd Kayser am So 02.06.13 13:59, insgesamt 1-mal bearbeitet
|
|
jaenicke
      
Beiträge: 19326
Erhaltene Danke: 1749
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mi 29.05.13 08:01
Gerd Kayser hat folgendes geschrieben : | Du musst das lediglich in die entsprechenden Ereignisse bzw. Messages einbauen, dann sollte es wie gewünscht funktionieren. |
Leider scheint es da keine Message speziell dafür zu geben, aber mit WM_HSCROLL, WM_VSCROLL, WM_MOUSEWHEEL und WM_SETCURSOR zusammen scheint es relativ gut zu funktionieren.
Ansonsten bleiben nur die Zeichenbefehle, denn WM_PAINT wird bei Änderungen schon immer ausgelöst, hat aber ja eigentlich einen anderen Sinn.
|
|
hRb 
      
Beiträge: 292
Erhaltene Danke: 12
|
Verfasst: Do 06.06.13 15:46
Sorry, war familiär bedingt eine Tage out.
G.Kayser, herzlichen Dank. Problem gelöst. Danach suchte ich schon seit Monaten.
Ich habe zwar nicht das Problem mit unterschiedlicher Zeichenbreite, da mein Programm in spezieller Editor ist, der u.a. Rechteck-Bereiche kopieren, ausschneiden, einfügen kann. So verwende ich eine nicht-proportionale Schriftart.
Aber die zwei Anweisungen Delphi-Quelltext 1: 2:
| SendMessage(RichEdit1.Handle, EM_GetScrollPos, 0, lParam(@Koordinaten)); SendMessage(RichEdit2.Handle, EM_SetScrollPos, 0, lParam(@Koordinaten)); |
erfüllen in Verbindung mit meinen oberen Befehlen genau das, was ich brauche.
Anmerkung: die oben von mir erwähnte Procedure RichEdWndProc stammt von einem Autor Namens "Bruno". Zu finden unter swissdelphicenter.ch/de/showcode.php?id=2227 (Ehre wem Ehre gebührt!)
Moderiert von Martok: Delphi-Tags hinzugefügt
|
|
hRb 
      
Beiträge: 292
Erhaltene Danke: 12
|
Verfasst: Fr 06.12.13 20:39
Bedanke mich für alle guten Tipps. Inzwischen funktioniert mein "Lineal" super. Musste viel probieren, da mir das Message-Konzept bisher nicht so bekannt war. Für alle die ähnliche Probleme haben, hier die Lösung zum Realisieren eines Lineals
1. Man nehme die Procedur TForm1.RichEdWndProc zum Srollen zweier Richeditfelder wie oben beschrieben (ausführlich siehe www.swissdelphicente...h/de/oberflaeche.php
Einschränkung hierbei: diese Procedure reagiert nur auf Änderungen am Scrollbar.
2. Damit die Felder auch synchron sind wenn über den Rand hinaus geschrieben wird, muss die Keydown-Procedur (die bei jedem Tastendruck anspricht) angepasst werden, wie von Gerd Kyser vorgeschlagen. Delphi-Quelltext 1: 2: 3:
| SendMessage(Richedit1.Handle, EM_GetScrollPos, 0, lParam(@Koordinaten)); Koordinaten.Y:=0; SendMessage(RicheditLineal.Handle, EM_SetScrollPos, 0, lParam(@Koordinaten)); |
Den Befehl Koordinaten.Y:=0 habe ich eingefügt. Da RicheditLineal nur aus einer einzigen Zeile, dem Lineal besteht, darf dies Vorlage nicht vertikal scrollen. Sonst ist das Lineal nicht immer sichtbar. Y:=0 simuliert, als wäre die erste Zeile in Richedit1 sichtbar. Viel Glück für alle Nachahmer und nochmals Danke. Gutes Team!
Moderiert von Martok: Delphi-Tags hinzugefügt
|
|
|