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



BeitragVerfasst: Do 09.03.17 16:31 
Das Thema synchronisiertes Scrollen in Richedit ist ja an verschiedenen Stellen publiziert. Ich nutze dies per Scrollbar mit nachstehenden Anweisungen - was auch funktioniert (ohne es wirklich zu verstehen). Dabei sieht man jeweils die synchron gleichen Textzeilen (z.B. 400 = 400) im Fenster.
Meine Anwendung vergleicht 2 Dateien und stellt die Cursor zum nächsten Unterschied. D.h. in Richedit1 z.B. Zeile 400, in Richedit2 auf Zeile 500. Nun will ich (ab Aktivierung vSyncron:=true) mit diesen Delta 100 Zeilen syncron scrollen.
Ich finde nicht die Stelle im Code an der +Delta (+/-100) stehen müsste. wParam liefert riesige Zahlen, ich vermute Pixel. Wer hat eine Idee/Lösung wo und wie Zeilen benutzt werden können?

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:
  private
    { Private-Deklarationen }
    PRichEdWndProc, POldWndProc: Pointer;
    procedure RichEdWndProc(var Msg: TMessage);

var vSyncron:boolean;
    Delta : integer; // Differenz der Zeilen

procedure TForm1.FormCreate(Sender: TObject);
begin
  vSynchron   := false;
  PRichEdWndProc := MakeObjectInstance(RichEdWndProc);
  POldWndProc    := Pointer(SetWindowLong(RichEdit1.Handle, GWL_WNDPROC,
                    Integer(PRichEdWndProc)));
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  if Assigned(PRichEdWndProc) then
  begin
    SetWindowLong(RichEdit1.Handle, GWL_WNDPROC, Integer(POldWndProc));
    FreeObjectInstance(PRichEdWndProc);
  end;
end;

procedure TForm1.RichEdWndProc(var Msg: TMessage);
begin
  Msg.Result := CallWindowProc(POldWndProc, RichEdit1.Handle, Msg.Msg,
    Msg.wParam, Msg.lParam);

 if vSynchron=false then exit;
  if (Msg.Msg = WM_VSCROLL) and (LOWORD(Msg.wParam) = SB_THUMBTRACK) then
  begin   {Anzeige vertikal sychron verschieben}
//    Label1.Caption := 'Pos is ' + IntToStr(HIWORD(Msg.wParam));
    RichEdit2.Perform(Msg.Msg, Msg.wParam, Msg.lParam);
    SetScrollPos(RichEdit2.Handle, SB_VERT, HIWORD(Msg.wParam), True);
  end;

  {prüft ob Scroll über Schieberegler, bzw Pfeil li,re}
  if (Msg.Msg = WM_HSCROLL) and (LOWORD(Msg.wParam) = SB_THUMBTRACK){=5} then
   begin   {Anzeige horizontal sychron verschieben}
    RichEdit2.Perform(Msg.Msg, Msg.wParam, Msg.lParam);
    SetScrollPos(RichEdit2.Handle, SB_HORZ, HIWORD(Msg.lParam), True);
   end;                           {SB_VERT            .wParam}
end;
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Do 09.03.17 21:18 
- Nachträglich durch die Entwickler-Ecke gelöscht -
hRb Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 267
Erhaltene Danke: 12



BeitragVerfasst: Fr 10.03.17 16:59 
Die konkrete Aufgabe besteht darin, dass ich jeweils am Jahresende alphabetisch sortierte Adressenlisten des Sportclubs (aufbereitet als einzelne Textzeile pro Person) auf Unterschiede vergleiche, d.h. es liegen zwei Textdateien vor: alt, neu in Richedit1, Richedit2. Meine Anwendung vergleicht und färbt jeweils die erste erkannte unterschiedliche Textzeile(n) zeichenweise ein. Der Vergleichsvorgang startet bei jedem Klick jeweils an der Zeile, an der der Cursor gerade steht!

Beispiel: Durch Neuzugang einer Familie kommen in Richedit2 z.B. 4 Personen hinzu, d.h der Zeilen-Zeiger von Richedit1 steht auf x der von Richedit 2 danach auf x+4. Das Delta wäre in diesem Fall=4. Delta kann sich beim nächsten Suchvorgang weiter erhöhen oder wieder erniedrigen - je nach Zugang/Abgang. Will ich nun beide Listen scrollen (per Buttom aktivieren/deaktivieren), dann liefern die oben erwähnten Proceduren synchrones Zeilen-Scrollen, während ich synchron, aber mit genanntem Delta-Versatz scrollen möchte. Denn nach vielen Änderungen ist der Unterschied so groß, dass die beiden RichEditfelder nicht gemeinsamens mehr anzeigen.

Ich benutze das Programm übrigens auch, um mal zwei ähnliche Pascal-Dateien (Unit) zu vergleichen. Da kommt mal eine ganze Procedure hinzu. Heute wechsle ich beim Scrollen immer von Richedit1 nach Richedit2 um "optischen Abgleich" zu haben. Auch dafür könnte "Delta-Scrollen" gut sein:
Ich hoffe, jetzt ist der Sinn und die Aufgabe klar. Da ich die Scroll-Funktion logisch nicht verstehe (habe auch keine Zugang zu Unterlagen über Msg.-Aufrufe bzw. Parameter) erhoffe ich mir jedoch, dass durch eine einzige Addition von Delta auf das Scrollergebniss die beiden Ansichten gleich schalten kann. (vertikale Richtung)
PS: Da die Zeilen im allgemeinen über Bildschirmbreite lang sind, gibt es natürlich auch horizontales Scrollen (Spalten). Aber diese Funktion wird durch obigen Code korrekt erfüllt.
haentschman
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 285
Erhaltene Danke: 33


DX10 Berlin Professional
BeitragVerfasst: Fr 10.03.17 17:08 
Hallöle... :P
Zitat:
Ich benutze das Programm übrigens auch, um mal zwei ähnliche Pascal-Dateien (Unit) zu vergleichen.

...dafür gibt es Werkzeuge wie BeyondCompare. Imho sollte es in jeder (neueren) Delphi Version dabei sein. :zwinker: Wenn du deine Delphi Version verrätst, können wir es gleich sagen.
Zitat:
...am Jahresende alphabetisch sortierte Adressenlisten des Sportclubs (aufbereitet als einzelne Textzeile pro Person) auf Unterschiede vergleiche...

..die Anforderung habe ich nicht verstanden, sorry. :nixweiss:
Mach einfach mal einen Screenshot wie die Inhalte der RichEdit aussehen und was wie verglichen wird. 8)
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Fr 10.03.17 17:54 
- Nachträglich durch die Entwickler-Ecke gelöscht -
hRb Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 267
Erhaltene Danke: 12



BeitragVerfasst: Fr 10.03.17 23:09 
Tut mir leid, wenn ich nicht klar genug formuliert habe. Ich versuche es noch einmal.
1. haentschmann: Ich habe Delphi7 und XE3. Arbeite derzeit mit XE3, um Unicode-Strings verarbeiten zu können. BeyondCompare.Imho sagt mit leider überhaupt nichts.

2. Frühlingsrolle: Es geht nicht um die Zeilenanzahl (Lines.Count), sondern um die Zeilendifferenz der jeweils aktuellen Cursorposition in den beiden Vorlagen.

3. Ich habe ein Word-Dokument angehängt, das mein Programm zeigt. Da ich keine Personennamen veröffentlichen darf, habe ich zwei Pascaldateien als Muster gewählt. Wie man sieht hat das Programm zwei unterschiedliche Zeilen erkannt und zeigt diese an. Allerdings steht der Cursor in Richedit1 auf Zeile 153, während in Richedit2 der Cursor auf Zeile 176 steht. Die Zeilendifferenz beträgt also 176-153=23 Zeilen.
Mit einem Button SynScroll aktivieren bzw deaktieren ich das "synchronisierte Scrollen" wie folgt.
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
procedure TForm1.SynScrollClick(Sender: TObject);
begin
 vSynchron:= not vSynchron;
 if vSynchron=false
     then SynScroll.NumGlyphs:=4 
     else SynScroll.NumGlyphs:=1;
end;

Nun nochmals zur eingangs genannten Befehlsfolge
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
 procedure TForm1.RichEdWndProc(var Msg: TMessage);
begin
  Msg.Result := CallWindowProc(POldWndProc, RichEdit1.Handle, Msg.Msg,
    Msg.wParam, Msg.lParam);

 if vSynchron=false then exit;
  if (Msg.Msg = WM_VSCROLL) and (LOWORD(Msg.wParam) = SB_THUMBTRACK) then
  begin
    RichEdit2.Perform(Msg.Msg, Msg.wParam, Msg.lParam);
    SetScrollPos(RichEdit2.Handle, SB_VERT, HIWORD(Msg.wParam), True);
  end;

Ist vSynchron=true und wird der vertikale Scrollbar bewegt, dann syncronisieren sich die Anzeigen in Redit1 und Redit2 derart, dass sich jeweils die identischen Zeilennummern gegenüber stehen (nicht die identischen Texte), also im Beispiel je die Zeilen 153 ff.
Ich verstehe die Anweisungen so, dass mit Zeile 3-4 in Msg.Result der Status in Richedit1 ermittelt, und in Zeile 9-10 das Ergebnis auf Richedit2 übertragen wird (allerdings kommt dort Msg.Result dort nicht vor).
Ich jedoch will, dass sich die Zeilen 153 und 176 gegenüber stehen bleiben und um die Differenz Delta=23 fortan synchron scrollen, dh. Zeile 200 in Redit1 steht 223 in Redit gegenüber).
Ich hatte die Vorstellung die Anweisung zu ergänzen
ausblenden Delphi-Quelltext
1:
  SetScrollPos(RichEdit2.Handl e, SB_VERT, HIWORD(Msg.wParam) + Delta, True);					

Eine Addition von +Delta auf HIWORD(Msg.wParam) bringt aber nicht das gewünschte Ergebnis.
Einloggen, um Attachments anzusehen!
haentschman
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 285
Erhaltene Danke: 33


DX10 Berlin Professional
BeitragVerfasst: Sa 11.03.17 07:25 
Moin... :P
..seit XE dabei.
C:\Program Files (x86)\Embarcadero\RADStudio\11.0\bin\BCompareLite.exe :?:
oder in der IDE unter
Bearbeiten->Compare

Ich hatte nicht verstanden was die Personendateien damit zu tun haben. :gruebel: Jetzt denke ich daß du einen Comparer programmiert hast. Auch wenn schon viel Zeit investiert hast...schau dir mal den BeyondCompare an. Da stecken Mannjahre Erfahrung drin. Als Werkzeug... :zustimm:

Sorry.
Einloggen, um Attachments anzusehen!
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Sa 11.03.17 13:01 
- Nachträglich durch die Entwickler-Ecke gelöscht -
hRb Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 267
Erhaltene Danke: 12



BeitragVerfasst: Sa 11.03.17 17:30 
1. Hiword weglassen: nutzt nichts. Habe sogar nur Null eingetragen: ändert ebenfalls nichts. Es scheint so zu sein, als würde der Parameter HIWORD(Msg.wParam) in Zeile 10 ohne Bedeutung sein. Habe auch an mehreren anderen Stellen im Code Festwerte eingesetzt bzw. Konstanten hinzu addiert. Ergebnis: entweder keine Auswirkung oder Scroll-Funktion geht überhaupt nicht.

2. Der Vermerk "keine Personendaten .. daher Pascal" war überflüssig. Begründung war, dass meine Hauptanwendung der Vergleich von Personendaten ist und von diesen Daten wollte ich keine Screenkopie anfertigen.
ABER: Der Hinweis auf Beyond-Compare war super! Vielen Dank! Dieses Programm erfüllt auf den ersten Blick vieles von dem was ich selbst habe bzw. brauche - vermutlich mehr. Gibt es hierfür Quellcode?, denn ein-zwei Kleinigkeiten hätte ich noch gerne.
Im Hinblick auf das Scrollen benutzt dieses Programm wohl einen Trick, in dem fehlende Zeilen(blöcke) durch "optischen Füllstoff" ausgeglichen werden. So läuft die Anzeihe in den beiden Vorlagen zeilensynchron, aber genau mit dem von mir gewünschten Versatz. Wäre interessant, wie man so etwas realisiert.

3. Sollte jemand doch noch eine Lösung auf meine Frage haben, dann gerne - auch wenn ich meinerseits das Thema zunächst mal schließe.
Nicht vergessen will ich aber den Dank für so viel ehrenamtliche Hilfe und Engagement. Ihr seid eine großartige Gruppe. Habt ihr nicht ein Spendenkonto? - wenigsten für ein ganz, ganz kleines Helles?
hRb
haentschman
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 285
Erhaltene Danke: 33


DX10 Berlin Professional
BeitragVerfasst: Sa 11.03.17 18:14 
:P
Zitat:
Habt ihr nicht ein Spendenkonto? - wenigsten für ein ganz, ganz kleines Helles?

...dann kommst du den Forentagen dieses Jahr...da findest du uns. 8) Ich habe immer Durscht... :zwinker:
Zitat:
Der Vermerk "keine Personendaten .. daher Pascal" war überflüssig

...ich habe alles und runter gelesen..."daher Pascal" habe ich nicht gefunden? :gruebel: Wie meintest du das?
Zitat:
Gibt es hierfür Quellcode?

Das ist ein kommerzielles Programm. Dem Delphi liegt aktuell die kostenlose Lite Version bei. Ob die Vollversion die Features hat, die du möchtest, mußt herausfinden. :zwinker:
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Mo 13.03.17 01:39 
- Nachträglich durch die Entwickler-Ecke gelöscht -
hRb Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 267
Erhaltene Danke: 12



BeitragVerfasst: Di 14.03.17 15:48 
Da steh ich nun, ich armer Tor, und bin so klug als wie zuvor.
Hallo Frühlingsrolle,
sieht alles prima aus, nur - mir fehlt vermutlich wieder das handwerkliche Rüstzeug.
Habe in meinem Hauptprogramm unter uses uRichEditEx hinzugenommen sowie uRichEditEx.pas ins Objekt eingebunden. Zuvor in uRichEditEx.pas "..Memo" gegen "..Richedit" ersetzt (notwendig bzw richtig?). Zuletzt im Hauptprogramm bei den Aktivierungs-Buttons fürs Scrollen die genannten Befehle eingefügt.
ausblenden Delphi-Quelltext
1:
2:
RichEditEx1.SynchronObject := RichEditEx2;
RichEditEx1.SynchronPosY := true;
Der Compiler streikt jedoch bei vorgenannten Anweisungen.
[dcc32 Fehler] Unit1.pas(40): E2003 Undeklarierter Bezeichner: 'SynchronObject'
[dcc32 Fehler] Unit1.pas(47): E2003 Undeklarierter Bezeichner: 'SynchronPosY'
Was fehlt da noch bzw. ist es zu viel verlangt ein lauffähiges Beispiel mit zwei Richedit-Feldern als zip anzuhängen? Wäre super!
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Di 14.03.17 16:07 
- Nachträglich durch die Entwickler-Ecke gelöscht -
hRb Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 267
Erhaltene Danke: 12



BeitragVerfasst: Mo 20.03.17 00:55 
Es hat einige Zeit gedauert. Nun melde mich nochmals.
Als Anlage das nochmals überarbeitete Beispiel von Frühlingsrolle, dem ich hiermit herzlich danke für seine super-Vorlage!!!
Missverständniss gab es wohl, wie Delta ermittelt wird. Nämlich nicht über Lines.Count, sondern über die aktuelle CursorPos der beiden Vorlagen. Die wird ermittelt über folgende Funktion:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
function GetFiRow (Fn : TCustomMemo{TCustomRichEdit}) : LongInt;
{liefert die ZeilenNR in der der Cursor steht 0..n}
begin
  Result := SendMessage(Fn.Handle, EM_LINEFROMCHAR, Fn.SelStart, 0);
  if Result<0 then Result:=0;
end;

So weit, so gut, mit Memo läuft das Beispiel. Erweitert werden kann es für horizontales scrollen.
Doch Frühlingsrolle hat es schon erwähnt:
Zitat:
TRichEditEx = class(TMemo) // TMemo durch TRichEdit ersetzen, aber
// TRichEdit zeigt/e ein sonderbares Scollverhalten auf,
// daher bin ich auf TMemo ausgewichen
sein Beispiel funktioniert nur mit Memos. Leider ist es auch mir nicht gelungen, dass das Beispiel auch mit Richedit voll-umfänglich funktioniert. In der Scroll-Case-Anweisung funktioniert:
- eine Zeile auf/ab (kleiner Pfeil am Scrollbar)
- eine Seite auf/ab (über Tastatur)
- Bewegung am Scrollbar funktioniert wie gesagt nicht mit Richedit (es gibt zwischen Himmel und Erde einfach Dinge, die logisch nicht zu verstehen sind). Oder gibt es doch eine Lösung? Habe sie nicht gefunden.

Ich habe noch eine wichtige Frage: Das Beispiel ist so, dass die Memos erst im FormCreate-Zweig zur Laufzeit erzeugt werden. Was muss verändert werden, wenn die zwei Memos bzw. Richedit schon mit dem Objektinspektor erstellt wurden?
der Grund: Ich werte in Richedit eine ganze Reihe weiterer Ereignisse aus (OnEdit, OnKeyUp, OnMouseUp). Diese Funktionen will ich nicht erst zur Laufzeit erstellen. Nun finde ich keine Lösung, wie ich die vorhandenen Objekte nachträglich durch TRichEditEx-Objekte überschrreiben kann. Habe viel gelesen, viel versucht - aber Verfahren nicht verstanden.
Einloggen, um Attachments anzusehen!
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Mo 20.03.17 03:02 
- Nachträglich durch die Entwickler-Ecke gelöscht -
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Di 21.03.17 19:01 
- Nachträglich durch die Entwickler-Ecke gelöscht -
hRb Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 267
Erhaltene Danke: 12



BeitragVerfasst: Fr 24.03.17 16:42 
Auch ich war noch einmal tätig und habe mit all den gewonnenen Erkenntnissen eine Lösung für zwei synchrone Richedit gefunden, die klassisch konstruiert werden.
Folgende Optionen sind beim Scrollen realisiert: Aus, Ein oder mit "synchroner Cursorposition" (Cursor-Differenz).
Das komplette Beispiel liegt als zip-Datei bei. Vielleicht hilft es auch anderen.
hRb
Einloggen, um Attachments anzusehen!
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Fr 24.03.17 17:03 
- Nachträglich durch die Entwickler-Ecke gelöscht -