Autor Beitrag
hRb
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 292
Erhaltene Danke: 12



BeitragVerfasst: 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.

ausblenden 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);

{HINWEIS: die Befehle unter Form1.Create und Form1.Close wurden hier weggelassen, sind aber zwingend im Programm erforderlich. Bei Bedarf suche unter ...synchronize two RichEdit by scrolling? Author: Bruno }

  procedure TForm1.RichEdWndProc(var Msg: TMessage);
  begin  {REdit synchron nur horizontal} 
    Msg.Result := CallWindowProc(POldWndProc, RichEdit1.Handle, Msg.Msg,
      Msg.wParam, Msg.LParam);
    if (Msg.Msg = WM_HSCROLL) {and (LOWORD(Msg.wParam) = SB_THUMBTRACK)} 
    then  begin     {VSCROLL} 
   {   Label1.Caption := 'Pos is ' + IntToStr(HIWORD(Msg.wParam));}
    RichEdit2.Perform(Msg.Msg, Msg.wParam, Msg.LParam);
    SetScrollPos(RichEdit2.Handle, SB_HORZ, HIWORD(Msg.LParam), True);
    end;      {wenn vertika Scroll SB_VERT             wParam }
  end;


Moderiert von user profile iconMartok: Delphi-Tags hinzugefügt
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19326
Erhaltene Danke: 1749

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: 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:
ausblenden 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 292
Erhaltene Danke: 12



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 632
Erhaltene Danke: 121

Win 7 32-bit
Delphi 2006/XE
BeitragVerfasst: Mi 29.05.13 04:21 
user profile iconhRb hat folgendes geschrieben Zum zitierten Posting springen:
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:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
//  http://msdn.microsoft.com/en-us/library/windows/desktop/bb774192(v=vs.85).aspx
//  uses RichEdit für EM_ExLineFromChar
procedure TForm1.Button1Click(Sender: TObject);
var
  Zeile   : integer;
  Zeichen : integer;
  Spalte  : integer;
  Bereich : TPoint;
begin
  Bereich := Point(33);  // Der Rand ist 1 Pixel groß
  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.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
// const EM_GetScrollPos = WM_User + 221;
// const EM_SetScrollPos = WM_User + 222;
// uses Types;
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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19326
Erhaltene Danke: 1749

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mi 29.05.13 08:01 
user profile iconGerd Kayser hat folgendes geschrieben Zum zitierten Posting springen:
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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 292
Erhaltene Danke: 12



BeitragVerfasst: 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
ausblenden 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 user profile iconMartok: Delphi-Tags hinzugefügt
hRb Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 292
Erhaltene Danke: 12



BeitragVerfasst: 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.
ausblenden Delphi-Quelltext
1:
2:
3:
    SendMessage(Richedit1.Handle, EM_GetScrollPos, 0, lParam(@Koordinaten));
    Koordinaten.Y:=0;  {Zeile immer auf Null halten, damit kein Vertikal-Scroll im Lineal}
    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 user profile iconMartok: Delphi-Tags hinzugefügt