ScrollBox, Objekt auf Objekt plazieren



  • In der ScrollBox liegt ein TImage, das auf beliebige Position gescrollt ist.

    Nun möchte ich auf dem TImage ein 2. TImage so positionieren, daß es Top/Left innerhalb der ScrollBox liegt. Es soll also voll sichtbar sein, egal wie gescrollt ist. Die Versuche mißlingen jämmerlich. Hier mal der aktuelle nutzlose Code:

    TPoint ITL,STL,ITS,STS;
            ITL.x = Image->Left;
            ITL.y = Image->Top;
            STL.x = ScrollBox->Left;
            STL.y = ScrollBox->Top;
            ITS = ClientToScreen(ITL);
            STS = ClientToScreen(STL);
            MarkBase->Left = STS.x+ITS.x;
            MarkBase->Top = STS.y+ITS.y;
    

    Bin offenbar zu doof, ClientToScreen richtig einzusetzen. Wie muß ich richtig an die Sache drangehen?



  • Hi,

    die Koordinaten beziehen sich immer auf der Position Top/Left des Parent.
    Wenn du also ein Objekt in ein Objekt legen möchtest, so setze

    Image->Parent=ScrollBox;

    nun haben wir das Image auf die Scrollbox gelegt. Damit verschiebt sich auch der Bezugpunkt für das Image.
    Du beziehst hier das Image auf den Bildschierm . Das Image möchte aber eine Position relative zur Top/Left - Position des Parent. X=0 und Y=0 wäre hier die Linke Obere Ecke auf der ScrollBox.

    Also muss dann
    Image->Left=0;
    Image->Top=0;

    sein Die Coordinaten die du zusammenbaust kannst du auch wieder mit ScreenToClient zurückkonveriteren auf den Bezugspunkt des Parent.



  • Hab's jetzt so versucht:

    MarkBase->Parent = ScrollBox;
            MarkBase->Left = ScrollBox->Left;
            MarkBase->Top = ScrollBox->Top;
            MarkBase->Parent = Panel;
    

    Nun liegt das 2. Image (o,o) auf dem 1. Image. Es nimmt ja beim Parent-Wechsel seine Position mit, und die war (o,o).

    Der komplette Aufbau ist folgender: Form, ScrollBox1, ScrollBox, Panel, Image1, Image2. Beide Images haben als Parent das Panel. Nur für Image2 kann ich das Parent wechseln, sonst zerstör ich die Positionierungen im Gesamtaufbau. Aber ich gewinn nix, da Parent am schluß wieder das Panel sein muß.

    Ich denk, ich muß mit Screen-Koordinaten Arbeiten. Ich brauch ein gemeinsames Bezugssystem. Aber mein Code ist unwirksam. Ich bekomm auf die Art keine Screen-Koordinaten.



  • Hi Omega-X

    Was willst Du genau 'basteln' (Werd' nicht ganz schlau aus Deinen Angaben)

    Was meinst Du mit:

    Nun möchte ich auf dem TImage ein 2. TImage so positionieren, daß es Top/Left innerhalb der ScrollBox liegt.

    Soll das 2. Image bezogen auf das erste positioniert werden oder bezueglich der ScrollBox (sichtbarer Bereich?) ?
    😕
    Im ersten Fall musst Du dich nur auf Left/ Top des Ersten Image beziehen. Die beiden Werte sind aber von HorzScrollBar->Position und VertScrollBar->Position mit abhaengig!!!

    Im zweiten Fall beziehst Du Dich am besten nur auf ScrollBar- Positionen!

    Wichtig: Parent sollte dabei fuer beide Images dasselbe Objekt sein (ScrollBox)
    --- wie AndreasW sagt, kommt es auf den ParentBezug an!!!

    Wie liegen diesbezueglich Deine Komponenten:

    ??? Hast Du zwei ScrollBoxen nebeneinander oder ineinander, Was macht das Panel genau?

    PS: Hast Du neue Kamele bekommen 😉



  • "Aufbau" meint den Aufbau übereinander. Das Drumrum laß ich weg (wird zu unübersichtlich). Also:

    Form ist Parent von ScrollBox1.

    ScrollBox1 ist Parent von ScrollBox. (ScrollBox wird gescrollt, beide Boxes liegen Left/Top/Width genau übereinander, ScrollBox1 ist unten größer).

    ScrollBox1 ist Parent von Panel (Panel liegt zentriert und ist in der Größe Abhängig vom jeweiligen Bild und der Zoomstufe).

    Panel ist Parent von Image und MarkBase. (Image ist das ArbeitsImage, MarkBase ist das PasteImage und über dem Image frei bewegbar).

    MarkBase soll beim Aufruf so angezeigt werden, daß es (egal welche) Scrollposition oben links im sichtbaren Clientbereich der ScrollBox liegt (also nicht etwa Top/Left auf dem Image - das ja verdeckt sein kann).

    Zum PS: Kamele? Ist noch etwas zu kalt für Kamele. 😉 Dank Schwarz- und Nachtarbeit konnte ich eine Elefantenladung Hirse organisieren. 🙄



  • Uuuups!!!

    Da siehst Du noch durch? 😉

    Das sind ja verschachtelte Familienverhaeltnisse (Parent- maessig) 😕

    Ich denke, Du musst Dich dabei strikt an Koordinaten- Bezug vom Panel halten - das ist Parent beider Images.
    Alle Umrechnungen (ScreenToClient und ClientToScreen) mussen ueber Panel-> laufen - das ist der einzige gemeinsame (exakte) Bezug!

    Die Lage vom Panel haengt von BEIDEN SCROLLBOX- ScrollBar Positionen ab!

    Wozu liegt eine ScrollBox in einer Anderen??? 😕 Eine ScrollBox kann doch in x- und y- Richtung scrollen, das sollte doch genuegen? (Beide liegen doch Left/Top/Width exakt uebereinander)***gruebel***nichtversteh***

    PS: Gut Dass Du schon Futter fuer die neuen Kamele besorgst! (Oder fuetterst Du damit die Haremsdamen? 😃 )



  • Hab im aktuellen Code das Panel als Bezug. Das geht genausowenig.

    Dank @WebFritzis Hilfe kann ich jetzt ganz edel die Mausposition in Screenkordinaten umrechnen. Mit den Controls klappt es einfach nicht. Da finde ich keine Entsprechung. Die Syntax, die ich mir aus der Hilfe zusammengebastelt hab, muß falsch sein. 🙄

    Ja, die vielen Controls übereinander (ich blick noch durch) 😉 . Ich hab zwei Paletten-Panels mit alLeft und alRight. Setz ich jetzt das Statuspanel alBottom, nimmt es die Priorität und setzt sich über die volle Formbreite. Es soll aber nur unter der ScrollBox liegen (die dann mit alClient den restlichen Raum ausfüllt. Darein kann ich das Statuspanel nicht packen, da es sonst mitgescrollt wird. - Wenn ich einen einfacheren Weg finde, änder ich das, die untere ScrollBox fliegt raus. Da scheint aber nichts zu gehen, alBottom hat die Priorität (Mit einem Panel getestet).

    PS: Na klar. Bald ist die Erntezeit für Kamele; da muß man vorsorgen. Hirse anbieten kann man ja hierzulande niemandem. Haremsdamen stehen auch auf Handfest, nicht auf Hirse. 🙄



  • Die Koordinaten der Controls - ich nehm' an Du meinst die Image im Panel - das ist wirklich 'verzwickt'.

    Annahme: Image liegt mit Left bei +25 Pixel
    Panel liegt mit -10 gescrollt in der ScrollBox bei Left=0

    -> Linke Kante von Image muesste bei +15 Pixel Abstand zu ScrollBox- Rand liegen
    -> Du musst wahrscheinlich fuer Umrechnung Left UND ScrollBar->Position UND Left von Image 'verrechnen'!? (Aber wie???) 😕

    (Hatte 'mal 'n aehnliches Problem bei Zoom mit Scrollrad in gezoomten und gescrollten Bild in der ScrollBox unter Beibehaltung des Bilpunktes unter der Maus - Nur mit Verrechnung aller Offsetwerte gelungen! Die Formel geht aber hier nicht!

    Bei Dir noch schlimmer, da Image in Panel in ScrollBox in ScrollBox1 ...???

    PS: Deine armen Haremsdamen, mussen mit HAND- fest zufrieden sein. 😃 Hast Du so wenig Zeit?? :p



  • Ist vielleicht gar nicht so verzwickt. ScrollBox1 Top/Left hab ich. Die Bewegliche ist Panel Top/Left. Hierfür bräuchte ich die ScreenKoordinaten. Die Umrechnung sollte dann klar gehen.

    -Sagst gar nix zu TBitmap::HandleType . Da kannst du die Timer-Auszeiten verlängern. Kein Refresh() oder Invalidate() sondern konkret (bei mir) Image->Refresh(); . Läuft sehr glatt und sauber, die Geschichte - macht schon richtig Fun.

    PS: Nicht HAND- fest sondern handfest. Das meint, soviel Zeit muß jederzeit sein. Da müssen sogar die Knobelkuren zurückstehen. - Hab halt nur die 5, und das soll so bleiben. 😉 😃



  • Original erstellt von <Omega-X>:
    **Hab's jetzt so versucht:

    MarkBase->Parent = ScrollBox;
            MarkBase->Left = ScrollBox->Left;
            MarkBase->Top = ScrollBox->Top;
            MarkBase->Parent = Panel;
    

    **

    ähm, ich hab doch gesagt.
    /me muss sich mal eben selbst zitieren:

    Also muss dann
    Image->Left=0;
    Image->Top=0;

    also:

    MarkBase->Parent = ScrollBox;
            MarkBase->Left = 0;
            MarkBase->Top = 0;
            MarkBase->Height = MarkBase->Parent->ClientHeight;
            MarkBase->Width = MarkBase->Parent->ClientWidth; 
            Sleep(5000); // zum überprüfen des erfolgreichen Parentwechsels 
            MarkBase->Parent = Panel;
            MarkBase->Height = MarkBase->Parent->ClientHeight;
            MarkBase->Width = MarkBase->Parent->ClientWidth;
    


  • waaa..., hast nicht aufgegeben, @AndreasW, dank dir. 🕶

    Den Parent->Wechsel hatte ich probiert. Hab jetzt auch noch mal deinen Coder versucht. Kann alles nicht gehen - sofern ich nicht ganz falsch lieg. Wenn MarkBase (10,10) auf der ScrollBox lag, kommt es auch (10,10) auf das Panel. Beim Wechsel nimmt es seine Koordinaten mit.

    Ich kapier nur nicht, wieso keine Screenkoordinaten gelingen. Die Klasse ist doch nicht als Attrappe eingerichtet. Ein API sollte auch dahinterstehen. Ich geb also die Hoffnung nicht auf. genau wie beim Mitscrollen im OnMouseMove solte das hier eine elegante Lösung ermöglichen.

    -Zur unteren ScrollBox: Überreden hat geholfen. 🙂 Sie mußte einem Panel weichen. War ja Verschwendung und nur wengen eines Versuches + späterer Faulheit einfach dort geblieben.



  • Hi Omega

    Vielleicht hilft das?:

    ScrollBox->Parent->ClientToScreen(Point(ScrollBox->left,ScrollBox->Top))
    -> liefert die Screen- Position der linken/oberen Ecke der ScrollBox!
    -> unabhaengig von ScrollBar- Positionen
    
    ScrollBox->Parent->ClientToScreen(Point(ScrollBox->left-
                                            ScrollBox->HorzScrollBar->Position,
                                            ScrollBox->Top-
                                            ScrollBox->VertScrollBar->Position))
    -> liefert die Screen- Position der linken/oberen Ecke des ScrollBox- Inhaltes!
    -> abhaengig von ScrollBar- Positionen
    ?? bei ScrollBar- Positionen=0 mueste das identisch sein zum Vorherigen??
    
    MarkBase->ClientToScreen(Point(0,0))
    -> liefert die Screen- Position der linken/oberen Ecke der MarkBase!
    -> ob dies in ScrollBox sichtbar ist oder nicht!!! Abhaengig von Scrollstand
    

    Hoffe, das ich nichts verwechselt hab' 😃



  • ...und dabei sah alles so vielversprechend aus. 😉

    Die Idee ist zumindest mal klasse, @Der Altenburger. Jetzt lassen sich immerhin schonmal Control-Punkte in Screenkoordinaten berechnen. 🙂 Aber positionieren läßt sich damit noch nichts. 🙄

    Dieses Mistvieh von MarkBase bleibt an der Position, an der es erstellt wurde. Zumindest wenn ich alles auf Screenkoordinaten umlege.

    Arbeite ich mit ->Left und ->Top, geht es dynamisch. Bisher leider nur mit Abweichungen, die sich mit der Scrollposition multiplizieren oder dividieren. Artillerietechnisch einschießen gelang bisher nicht.

    Ole, hier mal ein glatter Screenkoordinatencode, der glatt und sauber nichts bringt. Die beiden auskommentierten Zeilen bringen ein Ergebnis, allerdings versagt es bei größereen Scrollpositionen. Dann geht man auf die Suche. *ZFac wird zu viel, /ZFac wird zu wenig.

    Wahrscheinlich müßte man im höheren Scrollbereich Range mit berücksichtigen. Ab wann und wie. Mal seh'n, ob sich da ein Bezug finden läßt. Die Beschreibung ist je recht gut.

    POINT img = Image->Parent->ClientToScreen(Point(0,0));
            POINT scrb = ScrollBox->Parent->ClientToScreen(Point(0,0));
            if (img.x < scrb.x && img.y < scrb.y)
                MarkBase->Parent->ClientToScreen(Point(0,0)) = scrb;
            if (img.y < scrb.x && img.y >= scrb.y)
                MarkBase->Parent->ClientToScreen(Point(0,0)) = Point(scrb.x,img.y);
            if (img.x >= scrb.x && img.y < scrb.y)
                MarkBase->Parent->ClientToScreen(Point(0,0)) = Point(img.x,scrb.y);
            if (img.y >= scrb.y && img.y >= scrb.y)
                MarkBase->Parent->ClientToScreen(Point(0,0)) = img;
            //MarkBase->Left = ScrollBox->BoundsRect.Left+
                    ScrollBox->HorzScrollBar->Position;
            //MarkBase->Top = ScrollBox->BoundsRect.Top+
                    ScrollBox->VertScrollBar->Position;
    


  • Hi Omega-X

    Mit Deinem Code
    [cpp]
    **

    if (img.x < scrb.x && img.y < scrb.y)
    MarkBase->Parent->ClientToScreen(Point(0,0)) = scrb;
    if (img.y < scrb.x && img.y >= scrb.y)
    MarkBase->Parent->ClientToScreen(Point(0,0)) = Point(scrb.x,img.y);

    **[/cpp]
    muessten doch Fehlermeldungen kommen!(???)
    ??? Damit wird der Funktion ....->ClientToScreen(...) ein Punkt zugewiesen!
    Das duerfte der BCB nicht dulden?

    Mit:

    //MarkBase->Left = ScrollBox->BoundsRect.Left+
                    ScrollBox->HorzScrollBar->Position;
    

    sagst Du, geht's 'n bissl? Nur ScrollBar- Position stoert?

    Da fehlt glaub' ich Dein Panel in der Formel!(MarkBase liegt doch in Panel, Panel legt in ScrollBox, richtig?)
    So plazierst Du ein MarkBase in ScrollBox, Du musst aber doch MarkBase in Panel, und dieses in der ScrollBox platzieren!(???Aber wie???)



  • Nö, keine Fehlermeldung, keine Warnung. Was ich mach, nützt einfach nur nichts. Im Grunde tu ich wohl nicht mal was. Hab es dann nicht weiter untersucht.

    Nun zum Gag des heutigen Tages: Der "Zweizeiler" wollte noch nicht richtig. Dann war IDE aus, RuntimeError (wie immer) bestätigen, Maschine aus, Omega regenerieren, Maschine an, IDE starten, Projekt laufen lassen angesagt.

    Ole, exakt! ZB. ein Bild 2000x1695, 1000% Zoom, Position ganz am Ende. Er pastet exakt ins sichtbare (0,0) der ScrollBox! Verstehen tu ich das nicht, versuch es auch gar nicht. Denn es gibt viel mehr zwischen Hardware und BCB, als sich unsere... 😃

    Wichtig ist, daß es jetzt exakt läuft, *giganfreu* 🕶 ! Die Aufgabe ist gelöst, Ring frei zu weiteren Abenteuern. :p

    void __fastcall TPixi::PasteClick(TObject *Sender)
    {
        // Bitte nur Bilder, MarkBase ist ein TImage
        if(Clipboard()->HasFormat(CF_PICTURE))
        {
            // ab jetzt keine Zeichenoperationen mehr durchführen
            MarkBtn->Down = true;
            // an Bildgröße anpassbereit machen
            MarkBase->AutoSize = true;
            MarkBase->Stretch = false;
            // Position auf die Situation der ScrollBox abstimmen
            MarkBase->Left = ScrollBox->BoundsRect.Left+
                    ScrollBox->HorzScrollBar->Position;
            MarkBase->Top = ScrollBox->BoundsRect.Top+
                    ScrollBox->VertScrollBar->Position;
            // also, hol dein Bild ab und zeig dich
            MarkBase->Picture->Assign(Clipboard());
            MarkBase->Show();
            // Bereit machen für die Anpassung an den Zoomfaktor
            MarkBase->AutoSize = false;
            MarkBase->Stretch = true; 
            // int, dient zur Berechnung
            // der relativen Größe bei Zoomfaktorwechsel
            mbOldWidth = MarkBase->Width;
            mbOldHeight = MarkBase->Height;
            // Größe an den Zoomfaktor anpassen,
            // nun bereit, verschoben zu werden
            MarkBase->Width = MarkBase->Width*ZFac;
            MarkBase->Height = MarkBase->Height*ZFac;
        }
        // MarkierungsRect wieder aufräumen
        ARect = Rect(0,0,0,0);
    }
    


  • Glueckwunsch!!! (tatatataaaaa) 😉

    PS: Die Zeilen, die nichts tun wuerd ich aber trotzdem entfernen(machen ja eh' nix). Nicht das der die Funktionsadressen ueberschreibt!!! (Wehe wenn die Funktion 'mal gerufen wird!) 😉



  • Ha ja, das sind so die kleinen Frischlingsfreuden. Wenn ich dagegen richtigen Code seh... :p Aber das kommt mit der Zeit. Beispiele und Übung.

    Oh ja hab ich die nutzlosen Zeilen entfernt. Auskommentiert wird ja sowieso immer alles, was nicht aktuell laufen soll (Tests usw.). Was ich gepostet hab, ist die bereinigte Funktion. Copy und paste werden ja praktisch immer zentral gebraucht. Die sollen stimmen. - Normal kommentier ich solche glatt lesbaren Standards nicht. Aber falls doch mal jemand sowas braucht...

    Dank noch mal allen Beleidigten für die Hile. Der nächste Knoten kommt bestimmt. :p


Anmelden zum Antworten