Wheel Problem mit Frames



  • Hallo.

    Viel experimentiert und eine Lösung gefunden, ABER

    void __fastcall TForm1::FormMouseWheel(TObject *Sender, TShiftState Shift,
          int WheelDelta, TPoint &MousePos, bool &Handled)
    {
        if (WindowFromPoint(MousePos)==ScrollBox1->Handle)
        {
            long msg = (Shift.Contains(ssShift)) ? WM_HSCROLL : WM_VSCROLL;
            long code = (WheelDelta>0) ? SB_LINEUP : SB_LINEDOWN;
            for (int i=1;i<Mouse->WheelScrollLines;i++)
            {
                ScrollBox1->Perform(WM_VSCROLL, code, 0);
                ScrollBox1->Perform(WM_VSCROLL, SB_ENDSCROLL, 0);
            }
        }
    }
    

    wenn die Scrollbox in einem Frame liegt klappt das nicht mehr in

    void __fastcall TFrame2::FrameMouseWheel(TObject *Sender,
          TShiftState Shift, int WheelDelta, TPoint &MousePos, bool &Handled)
    

    ScrollBox macht keinen Muxer mehr *jammer*
    Ist das ein CBuilder5 Bug oder habe ich etwas nicht berücksichtigt?



  • Kennt wer vielleicht noch eine andere Methode?

    Zuerst hatte ich versucht in der ScrollBox selbst im Ereignis OnMouseWheel es hinzubekommen. Das hat aber auch nichtmal ansatzweise geklappt. Erst als ich über deren Elternkomponente (TForm) ging und dessen OnMouseWhell nutzte, klappte es.

    Kann da wer was zu sagen? Wäre echt toll, ich würd schon gern die ScrollBox mit dem Mausrad bedienen können.



  • Sorry das ich jetzt hier spamme, aber mir ist eben was sehr komisches aufgefallen.

    Ich habe in FrameMouseWheel() den Code stehen. Klappt nicht, aber wenn ich in eine Auswahlbox gehe und dort das Mausrad benutze dann geht er ja die ItemIndex durch. Wenn ich aber mit der Maus zu der Zeit über der ScrollBox bin (ComboBox hat den Focus) dann scrollt sowohl die ComboBox als auch die ScrollBox. 😮 😕



  • Hi,

    Hoffentlich hab ich dich nicht falsch verstanden......
    Wenn du folgendes ausprobieren willst mach bitte ein Test-Projekt mit dem nötigsten.

    Diese Funktion überschreiben in der Hauptfensterklasse (bei dir warhrscheinlich Form1)

    TWinControl::DoMouseWheel
    DYNAMIC bool __fastcall DoMouseWheel(Classes::TShiftState Shift, int WheelDelta, const Windows::TPoint &MousePos);
    

    Meine Idee:
    Wenn das Frame aktiviert wird, das onMousWheel des Frame, auf die obige überschriebene Methode umleiten.
    Sobald das Form1 wieder aktiviert wird, das onMousWheel des Form1, dahin umleiten.

    Grüsse

    Kann sein das es völliger Quatsch ist .... sorry



  • Ich denke es klappt nicht im TFrame, weil das TFrame nicht den Focus erhalten kann. Wenn der Code in der TForm steht, dann hat ja die Form den Focus und somit klappt es. Aber weder das TFrame noch die TScrollBox kann den Focus erhalten. Dann frag ich mich aber, wozu sie die Ereignisse haben, wenn es doch garnicht so geht? 😮

    Praktisch heisst das wohl, das man in Frames nicht scrollen kann. *igh*

    Auch das mit MouseMove ist unpraktisch gelöst. Wenn man etwas in die ScrollBox legt und dafür ist sie ja da, reagiert das MouseMove Ereignis nicht mehr von der ScrollBox.

    @steinsoft
    Danke für deine Hilfe, aber leider verstehe ich nicht ganz was genau in der Header eintragen soll und wie es in der CPP ausehen soll. Schliesslich muss da auch der Klassenname rein, sonst habe ich kein Zugriff auf die Komponente die ich Scrollen möchte.



  • Hi,

    ich hab überigens auch BCB5 (Professional). Es muss wohl wirklich ein bekanntes Problem sein.
    Bei deinem MouseWheel ist hinten das noch dabei --> bool &Handled).
    Kannst ja mal in der Hilfe F1 schauen was dieser neue Prameter soll, den kenne ich nicht.

    Vor langer Zeit hab ich mal ein Programm gebastelt, dass unbegrenzt viele dynamisch erzeugte MDI-Fenster angelegt hat.
    Damals hatte ich ungefähr das Gleich Problem wie du mit dem Fokus und MousWheel.
    Nach langem überlegen hab ich es so gelöst.
    Die Hauptempfänger MausWheel-Methode überschrieben und selber richtig verteilt.
    Ist eine längere Geschichte.
    Zuerst schau bitte mal Was der neue Übergabe-Kandidat für eine Rolle spielt.
    Würd mich interessieren.

    Grüsse



  • Handled gibt an, ob das Steuerelement als Ereignis behandelt wird. Wenn Sie Handled den Wert False zuweisen, wird das Ereignis vom übergeordneten Objekt des Steuerelements behandelt.

    Jetzt kommt einem natürlich die Idee das man Handled im TFrame auf false setzt und über die TForm das regelt. Problem dabei ist, das ich die TFrames ständig austausche und ~20 Frames habe. Jetzt abzufragen ist TFrame1 aktiv dann nutze dessen ScrollBox, ist TFrame2 aktiv dann nutze seine ScrollBox... naja ich teste mal es aus Prinzip mit einem TFrame.

    *TEST*

    Ne klappt nicht. Er sagt "Zugriffsverletzung" in TForm1 in der Zeile:

    if (WindowFromPoint(MousePos)==MyFrame1->ScrollBox1->Handle)
    

    (MyFrame1 war aktiv)

    Mit dem Wheel ist es echt ein Kreuz 🙄



  • Hi,

    legst du die Frames dynamisch an?
    Oder sind die schon fest im Projket von Anfang an.

    Ich kenn mich mit Frames nicht aus..... noch nie verwendet 🙂

    Grüsse



  • Ich lege die TFrames dynamisch mit new an. Im Menü wählt man jedesmal ein neues aus und das alte wird mit delete entfernt.



  • Hi,

    In solchen Fällen rate ich erlich gesgt immer --> bei dynamischen Sachen
    Blöde Frage 🙂
    Hast du in der Frame-Klasse irgendwo unit1.h includiert. (im Zweifelsfall in der Frame.h und Frame.cpp)

    Grüsse



  • Ich muss sie includieren, ansonsten könnte ich die Frames nicht über das MainMenu erstellen 😃
    Aber wie gesagt klappt das nicht, da Zugriffsverletzung im laufenden Programm kommt.



  • Hi,

    es geht mir um die eventuell vielen Frames im Speicher.

    Wie sollen die wissen wo das '''übergeordneten Objekt des Steuerelements''' ist,
    wenn '''Handled==false''' ist.
    Ich kann ja falsch liegen das Form1 nicht das '''übergeordente Objekt'''' des Frames ist.
    Deshalb bin ich der Ansicht, dass in die Frame-Klasse das stehen muss
    #include <unit1.h> <---- in die Frame.h rein

    Grüsse



  • Ohne zum eigentlichen Thema etwas beitragen zu können:

    Bei Frames steht die Wiederverwendbarkeit im Vordergrund. Insofern wäre es tückisch, dort einen Verweis auf irgendeine Form zu verwenden. Die Forms müssen wissen, welche Frames es gibt. Nicht aber umgekehrt.

    Includes sollten vorzugsweise in der CPP-Datei durchgeführt werden. Nur wenn es absolut unumgänglich ist, sollten includes in der Header-Datei verwendet werden.



  • Jetzt entfernen wir uns aber langsam weit vom Thema.

    Nochmal Kurz zusammengefasst:
    In der TForm ist die TFrame Klasse eingebunden und in der TFrame Klasse ist die TFrom eingebunden, da beide miteinander Daten austauschen müssen.
    Würde die eine die andere nicht kennen, würde der Compiler schon meckern das ihm die Klasse unbekannt ist.



  • Hi,

    was ist in der ScrollBox1 auf dem Frame drin??
    (Das könnte dir den Fokus von der Scrollbox weg schnappen... PaintBox macht das nicht)
    Baue mir das schnell nach....... sage dann bescheid.

    Grüsse



  • In der ScrollBox liegt ein TImage welches natürlich den gesammten Platz wegnimmt. In TForm hat es auch keine Probleme mit 😉



  • Hi,

    mein Plan hat nicht funktioniert... und wäre auch nicht sehr konfortabel gewesen....

    in unit1.h

    private:	// Anwender-Deklarationen
    TScrollBox *hallo;
    //zum überschreiben deklarieren .... diese muss immer am Schluss von allen privaten Deklerationen stehen
    DYNAMIC bool __fastcall DoMouseWheel(Classes::TShiftState Shift, int WheelDelta, const Windows::TPoint &MousePos);
    

    in unit1.cpp

    //Im Konstruktor hallo auf 0 setzen!!!!
    
    //Hauptmausradfunktion überschreiben
    bool __fastcall TForm1::DoMouseWheel(Classes::TShiftState Shift, int WheelDelta, const Windows::TPoint &MousePos)
    {
     if(hallo!=0)
      {
        if (WindowFromPoint(MousePos)==hallo->Handle)
        {
            long msg = (Shift.Contains(ssShift)) ? WM_HSCROLL : WM_VSCROLL;
            long code = (WheelDelta>0) ? SB_LINEUP : SB_LINEDOWN;
            for (int i=1;i<Mouse->WheelScrollLines;i++)
            {
                hallo->Perform(WM_VSCROLL, code, 0);
                hallo->Perform(WM_VSCROLL, SB_ENDSCROLL, 0);
            }
        }
    } }//---------------------------------------------------------------------------
    
    //wenn in die ScrollBox geklickt wird .... das Scrollen starten
    void __fastcall TForm1::ScrollBox1MouseUp(TObject *Sender,
          TMouseButton Button, TShiftState Shift, int X, int Y)
    {
     hallo = ScrollBox1;
    }
    //---------------------------------------------------------------------------
    

    Mein Plan war es nun... vom Frame aus Form1->hallo auf die dortige ScrollBox zu setzen.
    Dies Funktioniert nicht weil beim Compilieren oder Linken der Fehler kommt das nicht auf
    TForm1 zu geriffen werden kann.

    Sorry das es so lange gedauert hat musst mir erst noch eine ScrollMaus ausleihen.
    Vielleicht kann ja trotzdem irgend jemand daraus was lernen.

    Ich bin mir sicher das es ein Lösung gibt...... mir fällt nicht mehr ein

    Grüsse



  • Hi,

    Es geht doch!!! 🙂

    +++hallo++++ ist nicht public.

    Also die das MousWheel von den ScrollBoxen wird nicht mehr gebraucht.
    Sie werden auf die überschriebene DoMousWheel umgeleitet (wenn man das so sagen kann)

    Grüsse



  • Da hängt sich ja jemand richtig rein 😃

    Ohne das jetzt auszuprobieren, denke ich das du lediglich eine Umleitung gefahren bist. Unter TForm1 lief das scrollen ja auch bei mir. Das Problem bestand nur dann, wenn die ScrollBox in einem Frame liegt oder wenn man das Ereignis OnWheel direkt in der ScrollBox abfragen wollte.

    Dein Code fragt alles wieder auf TForm1 ab.

    Erstelle mal bitte über Menü->Datei->Neues Frame... pack dort eine ScrollBox rein mit einem grossen Image und lege jetzt über Komponentenpalette oben, bei Tab Standard das erste Icon TFrame in deine TForm1 rein.. es sollte eine Abfrage erscheinen welches Frame du einbinden willst. Da wählst dann dein Frame aus mit der ScrollBox .. so und dann probier nochmal die ScrollBox in dem Frame zu bewegen 🙄

    Ich habs mal hier ausprobiert, hatte leider nicht geklappt im Frame.



  • Hi Schnappi :-),

    Mir fällt nicht mehr dazu ein.
    Kann sein das es irgendwo eine richtig Umgangsweise beschrieben ist.

    Kannst ja versuchen, ob du es in einer Komponente besser lösen kannst.
    So wie ich das sehe, ist das Frame eine einfachere Art einer Komponente.
    Muss aber dazu sagen,
    dass ich noch nie eine ScrollBox in eine Komponente eingebaut hab.

    See you later Schnappi.

    Grüsse


Anmelden zum Antworten