ScrollBox automatisch scrollen
-
Die API-Zeile ist auch unspezifisch. Sowas ist gut, um zB. im RichEdit FindText ind den Sichtbereich zu bringen oder eben die ScrollBox schnell zu bewegen.
Mit Increment hab ich noch gat nicht expirimentiert. Könnte besser sein als Position+=8, auschecken. Range? Hmmm... mit größerem Range könnte der Ablauf eleganter werden.
Das wichtigste war sicher erst mal ein Stop-Faktor. OnMouseMove wirkt ja bei solchen Operationen quasi wie eine schleife. Das muß unterbrechbar sein, sonst bekommt man dieses Durchlaufverhalten...
Uff... ich seh nix mehr. Ist schon Nacht? Ich sollte weitermachen, wenn's draußen wieder hell ist. :p
-
Hi Omega-X
Du solltest mit Lob warten bis es optimal geht!
Und diese Uebertreibung!!!
(Waeren statt Cäsarnicht Bill Gates und Gott auch genug :p )Bei Dir fetzt das durch wie'n Puma???
(Da kommt wahrscheinlich MouseMove zu schnell in rekursion?)
Da hilft nur eins:
Das Ganze NICHT in MouseMove packen, sondern in eine NORMALE public- Funktion z.B. TimeScroll(...)
Da drin:
-- Mausposition abfragen
-- UMRECHNEN auf ScrollBox- Koordinaten!!!
-- Test aehnlich wie gepostet machen und Scrollen!!!Damit kannste auch auf Maus- Positionen reagieren, die AUSSERHALB der Box liegen
Die Funktion kann von 'nem ein/aus- schaltbaren Timer der Form gerufen werden.
(Kannst auch 'n Timer in die Klasse einbauen; ist aber Verschwendung, wenn Du das in mehreren Kompos machst)Ich mach in Form ein Timer, kleines Intervall (10..100 ms)
-- Timer- Event ruft fuer alle zu steuernden Kompos die dort eingebauten
-- Routinen TimeXXX() auf.-- in den Routinen wird dann mit Teiler (Als Property steuerbar?) zum Speibiel
-- nur jeder Zehnte Aufruf wirksam!-- Ich geb' den Routinen noch das Timerintrvall als Parameter mit, dann kann
-- sich jede Kompo individuell auf beliebiges (steuerbares) Vielfache des
-- Timerintervalls synchronisieren. :p(So in etwa mach ich das fuer eine Thumbnail- Anzeige. Die rauscht sonst auch durch!)
Ich hoffe, das hilft weiter!
-
Klar, Lob erst nach getaner Arbeit. Aber wann wird das sein? Bis dahin ist die Kehle längst ausgetrocknet. :p
Deine Ideen helfen auf jeden Fall. Timer? Die Maus soll doch selbst "Timer" spielen. Ansonsten würden sich beide wohl ins Handwerk pfuschen?. Nur jeder 10. Aufruf, das geht auch in einer Schleife. Muß ich auschecken, da die Maus zum Scrollen ja hin- und herfährt.
Variablen setzen, um später Properties draus machen zu können, stößt erst mal an Grenzen:
int Dfmod = fmod(DXR,VFac);
ScrollBox->HorzScrollBar->Position+=Dfmod;Eigentlich sollte jetzt bei jeder Mausbewegung bis zum nächsten Bildpixelraster durchgescrollt werden. Es erfolgt aber gar keine Reaktion. Der Modulo besteht aber, sonst würde es auch mit der if-Bedingung nicht klappen. Es sieht so aus, als würde Position nur einen Wert aber keine Variable akzeptieren. Das macht mir einen dicken Strich durch eine ansich vielleicht gute Rechnung. Das Verhalten irritiert mich.
Mit der Umrechnung von X auf ScrollBox-Maße hab ich Probs. X=0 ist außerhalb der ScrollBox-Position, wenn schon gescrollt wurde. Ich bräuchte einen Bezug für die Umrechnung. Vielleicht sind Screen-Koordinaten die Lösung? Damit werd ich mich mal auseinandersetzen...
-
Hi
ich glaub' jetzt haben wir uns mistverstanden!
Ich geh' davon aus, dass mit OnMouseMove das Teil zu schnell scrollt. (Scrollen loest wieder OnMouseMove aus-> Scrollen > OnMouseMove..... ==Rekursion ohne Ende!!!)
Deshalb 'Timing' vorgeben (wenn Maus am Rand der Scrollbox ist!)
-- eigene 'Timer'- Funktion
-- darin Mouse->CursorPos abfragen (Punkt in Screenkoordinaten!)
-- mit Umrechnen war nicht Skalieren gemeint! Sondern Abstand DeltaX und DeltaY
-- zu ScrollBox- Umgrenzung - Alle 4 Seiten kontrollieren
-- Dazu ev. MousePosition in ClientKoordinaten DER FORM umrechnen und mit
-- Left/Top/Right/Bottom der ScrollBox in Bezug bringen!!!-- Wenn Maus an einer Kante der ScrollBox ist, dann Scrollen um ScreenPixel!
?? Scrollweite Skalieren auf Anzeige- Bild- Pixel nur bei Vergroesserter
?? Darstellun sinnvoll!?? Skalierung mit fmod == RESTWERTDIV ??? (Ich denk 'ne normale Division
?? ist besser ???*****************************************************************************
DAS GILT ALLES NUR BEI EIGENER FUNKTION, NICHT BEI ONMOUSEMOVE DER SCROLLBOX!
*****************************************************************************
-
Hi Omega-X (Die Zweite)
Bau 'mal folgendes in eine Timerroutine Deiner Form ein und kuck Dir an was passiert, wenn die Maus aussen in die Naehe Deiner ScrollBox (hier IPSBox) kommt! :p
void __fastcall TForm1::Timer1Timer(TObject *Sender) { int DXl,DXr,DYo,DYu; int Rand=16; TRect ARect,IRect; TPoint Pt; ARect.Left=IPSBox->Left-Rand; ARect.Top=IPSBox->Top-Rand; ARect.Right=ARect.Left+IPSBox->Width +2*Rand; ARect.Bottom=ARect.Top+IPSBox->Height +2*Rand; IRect.Left=IPSBox->Left; IRect.Top=IPSBox->Top; IRect.Right=IRect.Left+IPSBox->Width; IRect.Bottom=IRect.Top+IPSBox->Height; Pt=ScreenToClient(Mouse->CursorPos); if ((Pt.x>ARect.Left)&&(Pt.x<ARect.Right)&&(Pt.y>ARect.Top)&&(Pt.y<ARect.Bottom)) { if ((Pt.x>IRect.Left)&&(Pt.x<IRect.Right)&&(Pt.y>IRect.Top)&&(Pt.y<IRect.Bottom)) { Form1->Color=clBtnFace; } else { //Maus im Randbereich (Ausserhalb)!!! DXl=IRect.Left-Pt.x; DXr=Pt.x-IRect.Right; DYo=IRect.Top-Pt.y; DYu=Pt.y-IRect.Bottom; if (DXl>0) Form1->Color=DXl*16; if (DXr>0) Form1->Color=DXr*16; if (DYo>0) Form1->Color=DYo*16; if (DYu>0) Form1->Color=DYu*16; } } else { Form1->Color=clBtnFace; } } //---------------------------------------------------------------------------
Hilft das weiter?
-
*Meuter*! Was bringen mir Screen-Koordinaten?
TPoint MPt = ClientToScreen(MovePt);
ShowMessage(IntToStr(MPt.x));Image->Left ist mindestens 200 vom Bildschirmrand entfernt. Ich geh auf ein Randpixel im Image nahe Image->Left, die Message sagt "3". Ist das nicht herrlich?
TPoint ScrollBScr = ScrollBox->ClientToScreen(ScrollBScr);
So sollte es nach der Hilfe gehen, die ScrollBox mit Bildschirmkoordinaten zu berechnen. Aber was hab ich jetzt definiert? Womit kann ich was berechnen? *Oh_ich_liebe_mein_Hirn_denn_es_ist_so_erfrischend_leer* :o
Wer kann einen gepeinigten Omega-X retten? Ich brauch ein gemeinsames Bezugssystem für die Scrollbox und das darin enthaltene TImage.
Beispiel: Wenn ScrollBox->Left=52; ist, soll die Message "53" ausgeben, wenn die Maus im ersten sichtbaren Image-Pixel ist. - Ansonsten vergleich ich Elefanten mit Mäusen.
-
Sorry, war so konzentriert, hab deinen beitrag erst jetzt gesehen. Ich check das mal. Auf den ersten Blick scheint es darum zu gehen, optisch darzustellen, wann Aktionen stattfinden würden. Recht aufwändig aber primstens testgeeignet. Und wieder ab in die Werkstatt. :p
-
Hmmm... nachdem nichts geschah, hab ich Color im if-Zweig auf clRed gesetzt, im else-Zweig auf clBlue. Egal, wohin ich mit der Maus geh, else ist immer true.
Konnte den Code nicht linear übernehmen.
// läuft bei mir nicht
Pt=ScreenToClient(Mouse->CursorPos);// So geht es
TPoint CursorPos;
Pt=ScreenToClient(CursorPos);Ob das den Unterschied macht?...
-
Hi
Komisch, das muesste geh'n.
Einfache Funktion:
1.ARect festlegen = Umriss der ScrollBox um Rand groesser
2.IRect festlegen = Umriss der ScrollBox
3.Pt=ScreenToClient(Mouse->CursorPos);
--MouseKoordinaten holen (= ScreenKoordinaten)
--Umrechnen in Form- Koordinaten.
??Falls das nicht geht nimm: Form1->ScreenToClient(...)??
4.Test, ob Maus im AUSSENRECHTECK (ScrollBox + Rand!!!)
-- Wenn ja, Test ob Maus im INNENRECHTECK (ScrollBox)
---- Wenn ja, Normale Farbe
---- sonst Farbe = Abstand der Maus von Kontur
-- sonst Normale FarbeD.h.:
Wenn Maus zu weit von Scroller weg ist oder innerhalb -> normale Farbe
Wenn Maus dicht an der Box (aussen) Farbe abhaengig von Abstand!Ist nur 'n Demo: Soll nur zeigen, wie Randberuehrung zeitgesteuert moeglich ist!
Bei mir wechselt die Farbe von dunkel bis Hellrot, wenn Maus im Randbereich ist.
Je weiter weg desto Heller Rot!(bis ARect verlassen wird) :pDie Breite des Randes ist einstellbar. Ob der sensitive Bereich ausserhalb an der Box oder innerhalb liegt, haengt von Berechnung AREct / IRect ab. Mich wuerde die Mausreaktion innen stoeren. Mir ist's lieber, wenn Reaktion nur in kleinem Bereich ausserhalb erfolgt - ist aber ANSICHTSSACHE!
-
Alles hängt daran, daß ich den die Mausposition nicht in Screenkoordinaten umwandeln kann. Damit wär ich nämlich aus dem Schneider. Hab es nach deinem Beispiel auch noch mal mit der Form als Basis versucht, bringt auch kein anderes Ergebnis.
MovePt = Form1->ClientToScreen(MovePt);
Bei der erst verwendeten Methode hab ich gemerxt, daß sich der Punkt des Scrollbeginns immer weiter ims Image hinein zurückverlagert, je größer Position ist. Das war bei dem Ansatz das Haupthandicap.
Karamba, wenn die Mausposition als Screen-Kordinaten ermittelbar wäre, könnte man exakt vergleichen, ohne die Rechtecke benutzen zu müssen. Und dann die Position der ScrollBar nur über den Timer verschieben. Das wär 'ne klare Sache.
Also, ich brauch die Mausposition als Screenkoordinaten! Was mach ich falsch? Es muß gehen, wenn es in der Klasse so vorgesehen ist.
Zum letzten Absatz: Mich würde auch stören, wenn die Mausreaktion innen ist. Die muß außen liegen, dann ist alles paletti. Als Bedingung setz ich auch, daß Drawing oder Dragging true sein muß. Sonst würde jede Mausbewegung im Bildschirm was bewegen.
-
Original erstellt von <Omega-X>:
Alles hängt daran, daß ich den die Mausposition nicht in Screenkoordinaten umwandeln kann. Damit wär ich nämlich aus dem Schneider.Wenn es dir weiterhilft:
POINT pt; GetCursorPos(&pt);
-
Hi
Das versteh' ich jetzt nicht!(???)
mit
Pt=Form1->ScreenToClient(Mouse->CursorPos)
muesste doch exakt die Positin der Maus IN FORM kommen:
-- Mouse->CursorPos enthaelt doch die ScreenKoordinaten der Maus!!! (BCB 4.0)
-- Form1->ScreenToClient macht daraus FORM- bezogene Koordinaten!Wo holst Du Dir die Mauskoordinaten; Was enthalten die genau?
Das hat eigentlich mit dem Stand der Rollbalken nichts zu tun???
Wo ist dein Timer? Sollte in der Form liegen, nicht in Klasse der ScrollBox!
PS: Liegt Deine ScrollBox in der Form oder auf einem Pane / Registe?
Wenn die NICHT in der Form direkt liegt, stimmt die ganze Rechnung nicht!
(ARect / IRect). Dann musste ScreenToClient von Panel nehmen![ Dieser Beitrag wurde am 14.03.2003 um 12:12 Uhr von DerAltenburger editiert. ]
-
@WebFritzi, *Volltreffer*!!!
Damit gehören dir meine letzten 30 Kamele und die antike Ölquelle, wie auf Seite 1 angekündigt.
Will sagen, super Dank, genau das war's.
Ole, jetzt wieder ab in die Werkstatt. @DerAltenburger, jetzt kann ich die Sachen nachvollziehen. - Ich hab übrigens das Image auf dem Panel liegen. Hat sich aus praktischen Gründen bewährt. Das über das Image hinausgeschobene Paste-Image wird nun nur noch soweit angezeigt, wie es über dem Image liegt. So soll es sein, da der Rest ja abgeschnitten wird.
-
Ohne Timer glatte Scrollbewegung, Geschwindigheit steuerbar.
Nachteil: Invalidate() ist unwirksam. Kleine Kostprobe - muß noch den Rest fertig machen:
void __fastcall TPixi::ScrollBoxMouseMove(TObject *Sender, TShiftState Shift, int X, int Y) { POINT pt; GetCursorPos(&pt); //falls Maus am rechten Rand if (pt.x > ScrollBox1->Left+ScrollBox1->Width) { ScrollBox->HorzScrollBar->Position+=1; // Invalidate() nicht wirksam Invalidate(); Sleep(1); } // im gleichen Stil noch die übrigen 3 Seiten ... }
@DerAltenburger, Mit dem Timer konnte ich nix gutes hinbekommen. Zwar war die Bewegung auch glatt, aber noch zu schnell. Hab alle Varianten mit Enabled durchprobiert, immer das gleiche. Die einmal angeregte Bewegung wird vom OnMouseMove immer wieder ausgelöst. Auch Stillstand ist MouseMove.
Ob sich irgendwie doch ein Invalidate(), Refresh()... erreichen läßT? Die Idee wär mir noch mal 30 Kamele wert, doch ich hab ja keine mehr. :p
-
Hi
Wenn Du das mit dem Timer probierst, DARF DAS SCROLLEN NICHT PARALLEL IN MouseMove AUSGELOEST WERDEN!
Timer ODER OnMouseMove! (Kannst das ja zum Test mal auskommentieren)
Das Tempo wird vom Timer und Deiner Berechnung gesteuert.
Der Timer loest alle INTERVALL msec ein Scrollen aus, Deine Berechnung sagt, wieviel Pixel jedesmal.
Pixel/sec = (1000 / Timer->Inervall) * Scrittweite !
Wenn OnMouseMove ebenfalls Scrollen ausfuehrt, rekursiert der wieder!
PS: Neh'm auch 8 Dromedare und 3 Haremsdamen :p
-
Und das war's dann erst mal. math.h ist mein Zeuge, daß ich von Mathe keine Ahnung hab. :p Das meint, eine steilere Kurve wär für höhere Zomfaktoren sicher noch besser. Immerhin kann das Refresh()-Geruckel in (vertretbaren) Grenzen gehalten werden. Feinheiten kann man aber jederzeit noch rausarbeiten. Wer eine Idee hat...
Hier mal die Fuction (ich hoff ja, dem Fragesteller wird halbwegs verziehen, wenn er Komplettlösungen postet?
):
void __fastcall TPixi::ScrollBoxMouseMove(TObject *Sender, TShiftState Shift, int X, int Y) { // float ZFac; // ZoomFaktor, im Header privat declariert POINT pt; GetCursorPos(&pt); // Mit Screenkoordinaten arbeiten if (pt.x > ScrollBox1->Left+ScrollBox1->Width && Tag == 0) { // rechter Rand // Scrollweg festlegen, Zoomfaktor mit einbeziehen ScrollBox->HorzScrollBar->Position+=cosh(2+ZFac/2); Tag = 1; // Scrollen und Refresh() im Wechsel } if (pt.x < ScrollBox1->Left && Tag == 0) { // linker Rand ScrollBox->HorzScrollBar->Position-=cosh(2+ZFac/2); Tag = 1; } if (pt.y > ScrollBox1->Top+ScrollBox1->Height && Tag == 0) { // unterer Rand ScrollBox->VertScrollBar->Position+=cosh(2+ZFac/2); Tag = 1; } if (pt.y < ScrollBox1->Top+ToolBar->Height && Tag == 0) { // oberer Rand ScrollBox->VertScrollBar->Position-=cosh(2+ZFac/2); Tag = 1; } if (Tag == 1) { Image->Refresh(); // Spuren der Arbeit beseitigen Tag = 0; // Auf Scrollen zurückschalten } }
-
Wie kann ich den Timer dann auslösen, wenn er gebraucht wird, sonst nicht? Zumindest muß ich ihn an der richtigen Codestelle enablen. Aber der Part ist überholt, es geht ja ohne.
- War eigentlich vorab schon klar, ich brauchte nur die Screenkoordinaten. Hoffentlich hat @webFritzi viel Freude an der Antiken Ölquelle - wenngleich sie natürlich schon lang nicht mehr fördert.
Dein PS ist viel wichtiger. Sei's um die Dromedare, sie sind dir gegönnt. Aber unter 5 Haremsdamen, das kann ich nicht entstehen lassen... bevor ich deutlich über 90 bin. Du siehst, ich bin bescheiden und... arm.
-
Den Timer lass ich dauernd laufen! Der steuert bei mir mehrere Komponenten. Jede Komponente, die ich takten will, hat ja 'ne eigene Funktion abbekommen, die das ausfuehrt. Die Ausfuehrung kann abhaenig von 'ner private "Status"- Variablen in jeder Kompo freigegeben / blockiert werden. Oder je nach Zustand (Anzeigen, Malen, ...) verschiedene Funktionen ausfuehren. :p
VORTEIL mit Timer: das laeuft auf jedem Rechner gleich schnell!!! (ausser der PC ist zu lahm, damm humpelts halt
PS: Grosser Dank fuer die Dromrdare. Hoffe, die kommen unbeschadet an.
Und Du hast wirklich nicht mal 37 Haremsdamen? Du bist arm dran - aber besser als Arm ab!
Dir sei verziehen!
-
Also ich bekomm ja ein richtig schlechtes Gewissen. Baust du Spiele? Da braucht man Systemunabhängige Abläufe. Man arbeitet zB. mit Ticks = 1/16 sec. Aber bei einer Anwendung wolte ich die Abläufe so schnell wie möglich haben. Bei kleineren Bildern läuft es glat, bei größeren ist (leider) die Refreshrate der Begrenzungsfaktor.
Als Nachteil bei dem Timer find ich vor allem, daß er bei jeder Zoomstufe gleich schnell arbeitet. Bei 100% wird das dann einfach zu schnell, wenn man es für höhere Vergrößerungen auslegt. Mit der Mathematik kann man da besser ausgleichen. Vielleicht findet jemand einen noch eleganteren Rechenalgor?
Kannst die Funktion ja mal probelaufen lassen. Ich hab die OnMouseMove-Routinen für die ScrollBox und das TImage zusammengelegt. Aber du hast ja ohnehin eine gemeinsame Klasse, da sollte es auf jeden Fal klappen.
37 Haremsdamen... Träum... das haben ja hier nicht mal die Stadträte. Kommst du aus 'ner Wohlstandsgegend? :p
-
Hi
Mit Spielen hat das nichts zu tun! Da kann man kaum direkt TImage nehmen - Du hast ja auch schon Flackereffekte u.ä.
Ich bastel nur 'n bissl mit Graphik, Sound und Video- Anzeigen 'rum.
Batel 'ne Suchmaschine, die Laufwerke und Netzwerkordner nach MultiMedia- Dateien durchforstet (Grafikfiles, Audio, Video und HTM(L)- Dateien), die Daten geeignet anzeigt (in 'ner Zoom- Scroll- Box / im WinMediaplayer / im MS- IE) - im Fenster oder Vollbild. Hintergrundmusik spielen braucht's auch. Grafiken (Thumbnails davon) als Uebersicht darstellen - in 'ner MultiImageScrollBox.
Beim 'AutoScroll' stoert mich, wenn das von Mausbewegung abhaengt und das Tempo vom System. Ist alles Ansichtssache!!!
Hab auch eine Thumbnail- Uebersicht am Bildschirmrand (wie IView) und dazu Autoscroll. Das fetzt durch wie Speedy Gonzales - dafuer nehm' ich den Timer - 3 - 5 Thumbnail / sec.
Was Du als Nachteil siehst bei Timer - "bei jeder Zoomstufe gleich schnell " - kann doch die Timer- Funktion mit 'einrechnen'???
!!! Deshalb sag ich: Spezielle Funktion in der Klasse (hat Zugriff auf alle
!!! Variablen) und Aufruf durch Timer von aussen.Meine Thumbnailliste roolt pro sec festgelegte Anzahl Bilder, EGAL wie gross die sind. Wenn die Maus zu weit weg ist tut sich nichts.(siehe letzter Tip mit der Farbe)
PS: Wozu habt Ihr Stadtraete, die kosten doch nur sinnlos TEUROS!
D#rum habt Ihr kein Geld fuern ordentlichen Harem :p