Autor |
Beitrag |
galagher
Beiträge: 2534
Erhaltene Danke: 44
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Mo 10.01.22 20:24
Hallo zusammen!
Ich möchte gerne einen (oder mehrere) TButtons in einem TJvRichEdit so "einfügen", dass er mitscrollt, dass er also seine Position im Text behält. Dabei soll der Button voll funktionsfähig bleiben, und es soll möglichst flüssig ablaufen. Gerne auch TSpeedButton oder TBitBtn!
Man kann ja Grafiken auf diese Weise einbinden, aber das kommt nicht in Frage, weil man nicht abfragen kann, welche Grafik gerade angeklickt wurde.
Ein TJvRichEdit als Parent einer Komponente geht - natürlich - ebenfalls nicht.
Kann man das mit Komponenten so überhaupt machen? Wenn ja, wie?
lg
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
Th69
Beiträge: 4791
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Di 11.01.22 11:29
Einen direkten (vom System vorgesehenen) Weg gibt es dafür nicht. Als einziger Weg bleibt wirklich nur den Button dem TJvRichEdit als "SubControl" hinzuzufügen und dann die Scroll-Messages ( WM_HSCROLL, WM_VSCROLL) abzufangen und die Position neu zu setzen (evtl. mußt du also das EditControl "subclass"en, also davon ableiten und die Messages dort behandeln).
Als Überblick kann ich dir nur den Petzold empfehlen: Building a Better Scroll (Code ist aber natürlich in C).
Für diesen Beitrag haben gedankt: galagher
|
|
galagher
Beiträge: 2534
Erhaltene Danke: 44
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Mi 12.01.22 14:39
Th69 hat folgendes geschrieben : | Einen direkten (vom System vorgesehenen) Weg gibt es dafür nicht. Als einziger Weg bleibt wirklich nur den Button dem TJvRichEdit als "SubControl" hinzuzufügen |
So wird das nichts, einen Button auf das JvRichEdit legen (in Wirklichkeit ja auf die TForm) und dann alles per Hand machen. Da verzichte ich lieber drauf!
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
Th69
Beiträge: 4791
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Mi 12.01.22 16:27
Auch wenn evtl. die Delphi-Komponenten das nicht direkt unterstützen, solltest du immer direkt per WinAPI-Funktion SetParent ein beliebiges Windows-Control als Parent des Buttons zuweisen können (und dieser wird dann auch vom Windows-System nur innerhalb des sichtbaren Bereichs des Parent-Controls angezeigt).
Und dann eben nur noch bei den Scroll-Messages (nachdem das eigentliche TJvRichEdit diese verarbeitet hat), die Position des Buttons neu anpassen (so viel Code sollte das dann nicht sein).
In einem kleinen WinForms-Testprojekt (mit C#) habe ich das ansatzweise ausprobiert und es hat funktioniert. Einzig, wenn du sehr viele Buttons hast, kann natürlich die Performance ein bißchen darunter leiden.
Für diesen Beitrag haben gedankt: galagher
|
|
galagher
Beiträge: 2534
Erhaltene Danke: 44
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Fr 14.01.22 11:34
Th69 hat folgendes geschrieben : | Und dann eben nur noch bei den Scroll-Messages (nachdem das eigentliche TJvRichEdit diese verarbeitet hat), die Position des Buttons neu anpassen (so viel Code sollte das dann nicht sein). |
So aus dem Stand habe ich keine Vorstellung davon, wie ich das anpasse. Ich sehe mir das aber an, vielleicht komme ich ja weiter.
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
galagher
Beiträge: 2534
Erhaltene Danke: 44
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Fr 14.01.22 18:27
SetParent ist mir klar, nicht aber der Rest.
Es gibt ein Ereignis OnVerticalScroll, das gilt aber für beide vertikale Richtungen. Das ist es aber nicht, was du mit Scroll-Messages meinst.
Ich brauche einen Tipp...
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
Th69
Beiträge: 4791
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Sa 15.01.22 09:00
Ich meine die allgemeine WndProc.
|
|
galagher
Beiträge: 2534
Erhaltene Danke: 44
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: So 16.01.22 19:29
Th69 hat folgendes geschrieben : | Ich meine die allgemeine WndProc. |
Ok:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| procedure TForm1.WndProc(var msg : TMessage); begin if msg.Msg = WM_VSCROLL then ;
inherited WndProc(msg); end; |
Die Prozedur wird ausgeführt, aber wie ermittle ich den Wert für Button2.Top?
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
Th69
Beiträge: 4791
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Mo 17.01.22 10:08
Indem du diese Position relativ zur aktuellen Scrollposition des TJvRichEdit berechnest (merke dir dafür die initiale Position des Buttons), s.a. How to get the scrollbar posit(i)on in a RichEdit control (das einfachste ist wohl unter "Solve 2" beschrieben).
Führ die Berechnung aber nach dem Bearbeiten der Message aus (also nach inherited WndProc(msg);).
|
|
galagher
Beiträge: 2534
Erhaltene Danke: 44
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Mo 17.01.22 16:47
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
Th69
Beiträge: 4791
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Mo 17.01.22 18:10
Ich meinte ja auch:
Delphi-Quelltext 1:
| Button2.Top := InitialPosY + GetVertScrollBarPosition; | (und InitialPosY initialisierst du bei der ersten Zuweisung von Button2.Top).
Alternativ berechnest du die Differenz der Scrollbewegung (also Werte vor und nach dem Scrollen vergleichen) und addierst diese zur Button-Position.
PS: Es sollte nur
Delphi-Quelltext 1:
| Result := GetScrollPos(Handle, SB_VERT); | heißen...
Für diesen Beitrag haben gedankt: galagher
|
|
galagher
Beiträge: 2534
Erhaltene Danke: 44
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Mo 17.01.22 19:31
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
Th69
Beiträge: 4791
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Di 18.01.22 07:43
So habe ich mir das vorgestellt.
Ja, hast Recht, hier muß subtrahiert werden, da GetScrollPos positive Werte liefert (in .NET hat die AutoScrollPosition immer negative Werte - daher hab ich mich hier vertan). Aber dafür bist du ja Entwickler...
Eigentlich sollte auch während des Bewegens der ScrollBar die WM_VSCROLL-Nachricht verschickt werden (mit SB_THUMBTRACK im wParam) (denn der Text scrollt ja auch währenddessen).
Und laut WinAPI-Doku zu GetScrollPos gibt es (dort) nicht SB_THUMBPOSITION als Parameter (der Kommentar ist also diesbzgl. falsch).
PS: Noch als Hinweis, falls du es noch nicht in der Doku gelesen hast: wenn deine ScrollBar mehr als 65535 (virtuelle) Pixel hat, dann mußt du stattdessen GetScrollInfo benutzen (32bit-Werte anstatt 16bit).
|
|
galagher
Beiträge: 2534
Erhaltene Danke: 44
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Di 18.01.22 15:50
Th69 hat folgendes geschrieben : | Eigentlich sollte auch während des Bewegens der ScrollBar die WM_VSCROLL-Nachricht verschickt werden (mit SB_THUMBTRACK im wParam) (denn der Text scrollt ja auch währenddessen).
Und laut WinAPI-Doku zu GetScrollPos gibt es (dort) nicht SB_THUMBPOSITION als Parameter (der Kommentar ist also diesbzgl. falsch). |
Ja, es funktioniert auch ohne SB_THUMBPOSITION, aber: Wenn man den Balken der Scrolleiste bewegt, wird der Button erst gesetzt, wenn man die linke Maustaste wieder loslässt.
Mit GetScrollInfo habe ich noch Schierigkeiten, ich bin aber dran.
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
Th69
Beiträge: 4791
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Di 18.01.22 18:03
In der Antwort von Delphi - Get and Set Scrollbar Position of a ListView steht, wie man GetScrollInfo aufruft.
Du mußt dann nur fMask mit SIF_TRACKPOS initialisieren und danach nTrackPos auslesen.
|
|
galagher
Beiträge: 2534
Erhaltene Danke: 44
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Mi 19.01.22 16:14
Das Ganze kann man aber auch einfach in der OnVerticalScroll-Prozedur unterbringen:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| procedure TForm1.JvRichEdit1VerticalScroll(Sender: TObject); var iYPos: Integer; SInfo: TScrollInfo; begin SInfo.cbSize := SizeOf(SInfo); SInfo.fMask := SIF_ALL; GetScrollInfo(JvRichEdit1.Handle, SB_VERT, SInfo); iYPos := SInfo.nPos;
Button2.Top := InitialPosY - iYPos; end; |
Mit SIF_TRACKPOS und nTrackPos funktioniert es nicht, SIF_ALL und nPos scheinen korrekt zu sein, denn damit klappt es.
Bleibt immer noch der Effekt, dass beim Verschieben des Scrollbalkens die Position erst nach dem Loslassen der Maustaste gesetzt wird, und bei OnMouseWheel passiert gar nichts. Ein Aufruf von JvRichEdit1VerticalScroll im OnMouseWheel setzt die Position nur ungefähr, aber nicht genau.
Aber das Prinzip funktioniert. Dank dir!
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
Th69
Beiträge: 4791
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Mi 19.01.22 16:29
galagher hat folgendes geschrieben : | Bleibt immer noch der Effekt, dass beim Verschieben des Scrollbalkens die Position erst nach dem Loslassen der Maustaste gesetzt wird |
Und genau dafür ist doch nTrackPos (im Unterschied zu nPos).
|
|
galagher
Beiträge: 2534
Erhaltene Danke: 44
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Mi 19.01.22 18:53
Th69 hat folgendes geschrieben : | Und genau dafür ist doch nTrackPos (im Unterschied zu nPos). |
SIF_ALL und nPos: a) Pfeile der Bildlaufleiste und in die Bildlaufleiste klicken klappt, ziehen am Balken klappt nicht.
SIF_TRACKPOS und nTrackPos: b) Ziehen am Balken klappt, Pfeile der Bildlaufleiste und in die Bildlaufleiste klicken klappt nicht.
SIF_TRACKPOS und nPos: c) Beides klappt nicht.
SIF_ALL und nTrackPos: Wie b).
Mal sehen, ob es da sonst noch etwas gibt.
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
galagher
Beiträge: 2534
Erhaltene Danke: 44
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Mi 19.01.22 19:17
Hier meine vorläufige Lösung, jetzt klappt alles:
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:
| procedure TForm1.JvRichEdit1VerticalScroll(Sender: TObject);
procedure VScroll(Sender: TControl); var iPos, iTrackPos: Integer; SInfo: TScrollInfo; begin SInfo.cbSize := SizeOf(SInfo); SInfo.fMask := SIF_ALL;
GetScrollInfo(JvRichEdit1.Handle, SB_VERT, SInfo); iPos := SInfo.nPos; iTrackPos := SInfo.nTrackPos;
if iTrackPos = 0 then TControl(Sender).Top := InitialY - iPos else TControl(Sender).Top := InitialY - iTrackPos; end;
begin VScroll(Button2); end; |
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|