Laden...

MouseMove über Childcontrols

Erstellt von Andreas@Tricept vor 15 Jahren Letzter Beitrag vor 15 Jahren 3.383 Views
A
Andreas@Tricept Themenstarter:in
289 Beiträge seit 2006
vor 15 Jahren
MouseMove über Childcontrols

Hallo,
ich habe eine Controlklasse, diese dient als spezieller Container für diverse Grafiken.
Was ich nun machen will ist wenn man in ein bestimmtes Feld mit der Maus geht (Beispiel 20x20 Feld unten links in der Ecke), soll ein kleines Popup Fenster geöffnet werden.

Ich würde im Basiscontainer Element dafür das MouseMove Event regestrieren und halt auf den Bereich hin abfragen und dann das Fenster anzeigen. Jedoch da es ja ein Container ist, können sich andere Controls darauf befinden und diesen Bereich überdecken, sodass der Event nicht mehr greift -_-.

  1. Ich habe dazu zwei Fragen. Ist der MosueMove Event der richtige Ansatz? Ich meine gehört zu haben das man soetwas anders abfragt. Vielleicht WinProc??

  2. Wie kann ich diesen Event über die Childcontrols setzten, sodass dieser gefeuert wird auch wenn ich über die Childcontrols gehe?

X
2.051 Beiträge seit 2004
vor 15 Jahren

zu 2.

foreach(Control ctrl in this.Controls)
  ctrl.MouseMove += new ..
A
Andreas@Tricept Themenstarter:in
289 Beiträge seit 2006
vor 15 Jahren

Der Ansatz würde funktionieren wenn ich Events weitergeben könnte. Dann so:


        ContainerKlasse()
        {

            this.MouseMove += new MouseEventHandler(Container_MouseMove);
            this.ControlAdded += new ControlEventHandler(control_ControlAdded);
        }

        void control_ControlAdded(object sender, ControlEventArgs e)
        {
            Control con = (Control)sender;
            Control added = con.Controls[con.Controls.Count-1];
            added.MouseMove += new MouseEventHandler(added_MouseMove);
            added.ControlAdded += new ControlEventHandler(control_ControlAdded);
        }

        void added_MouseMove(object sender, MouseEventArgs e)
        {
            ((Control)sender).Parent.OnMouseMove(e);
        }


Aber so einfach geht das ja nicht oder sehe ich was falsch?

915 Beiträge seit 2006
vor 15 Jahren



        void control_ControlAdded(object sender, ControlEventArgs e)
        {
            Control con = (Control)sender;
            Control added = con.Controls[con.Controls.Count-1];
            added.MouseMove += new MouseEventHandler(added_MouseMove);
            //added.ControlAdded += new ControlEventHandler(control_ControlAdded);
        }

Das würde gehen, aber bedenke, die Koordinaten werden vom 0 Punkt des Childs aus jeweils berechnet! Wenn also Parent e.X - Child e.X machst wirst immer = 0 erhalten da Parent e.X = 0 und Child e.X = 0 ist. 🙂

Klingt zwar einfachc oder logisch, aber wenn so etwas berechnen möchtest denk dran, über Parent.Location und Child.Location (kannst auch .ClientRect wenn auch den Rand ausschließen möchtest). Über den sender identifizierst ja die Controls.

Wie vernichtet stand Andreas unter den flammenden Augen seiner Kunden.
Ihm war's, als stünde des Schicksals dunkle Wetterwolke über seinem Haupte X(

A
Andreas@Tricept Themenstarter:in
289 Beiträge seit 2006
vor 15 Jahren

Das geht doch nicht weil dieser Teil nicht funktioniert, weil OnMouseMove Protected ist:


      void added_MouseMove(object sender, MouseEventArgs e)
        {
            ((Control)sender).Parent.OnMouseMove(e);
        }

Das heisst meine Basisklasse kriegt nie mit wann ein Mousemove auf seine Childs gemacht wird, weil die es nicht übergeben können an die Parents...

915 Beiträge seit 2006
vor 15 Jahren

Muh, hab mich verlesen, hatte es so verstanden vom Child zum Parent. Du willst aber die Parent MouseMove zum Client 😉

Eine Lösung dafür wäre ein lowlevel hook auf den eigenen Prozess und das Handle des Parents , praktischerweise ist dieser ja dme Child bekannt.

Unter folgenden Link findest du einen global hookLink, shcmeiß das LoadLibrary weg, stell das SetWindowHook um.


SetWindowsHookEx(WH_MOUSE, MouseHookProcedure, <ParentHandle>, AppDomain.GetCurrentThreadId());

Kannst auch nen ThreadHook schreiben, und das <ParentHandle> weglassen, da es logisch ist das die Maus nur koordinaten des äussersten Containers versenden kann auf dem aktuellen GUI Thread. Ergo hast imemr das Parent.

Sieht so aus:


SetWindowsHookEx(WH_MOUSE, MouseHookProcedure, (IntPtr)0, AppDomain.GetCurrentThreadId());

Gibt aber auch andere sehr schöne hooks hier im Forum sogar in C++ 🙂

Wie vernichtet stand Andreas unter den flammenden Augen seiner Kunden.
Ihm war's, als stünde des Schicksals dunkle Wetterwolke über seinem Haupte X(

A
Andreas@Tricept Themenstarter:in
289 Beiträge seit 2006
vor 15 Jahren

Wow das sieht etwas zu hoch für mich aus. Muss erstmal verstehen was du meinst. Aber vielen Dank dafür, jetzt hab ich ja was woran ich mich setzten kann. Bestimmt melde ich mich nochmal zu dem Thema 😉

915 Beiträge seit 2006
vor 15 Jahren

Hrm, es geht auch etws einfacher. Du kannst ja auf deinen Controls eine Schnittstelle implementieren welche das event MouseEventHandler OnParentMouseMove; beinhaltet und beim Adden der controls so wie oben das event auf jene Controls mit dem passenden interface binden. Dann überschreibst beim Parent Control die OnMouseMove Methode und feuerst das Event ab. Und schon kannsta uf deinen childcontrols auf das Event reagieren.

Also es gibt viele Möglichkeiten das zu realisieren 🙂

Wie vernichtet stand Andreas unter den flammenden Augen seiner Kunden.
Ihm war's, als stünde des Schicksals dunkle Wetterwolke über seinem Haupte X(

A
Andreas@Tricept Themenstarter:in
289 Beiträge seit 2006
vor 15 Jahren

Das Problem dabei ist nur das ich alle Controls die ich einfüge erstmal anpassen müsste (Also das Interface implementieren). Das heisst die Klasse wäre ja dann nicht mehr allgemeingültig.

3.511 Beiträge seit 2005
vor 15 Jahren

Schau mal hier rein.

"Jedes Ding hat drei Seiten, eine positive, eine negative und eine komische." (Karl Valentin)

915 Beiträge seit 2006
vor 15 Jahren

Hrm, du kannst das auch über Win API abbilden was dir Khalid als Link reingestellt hat. Indem mit PostmEssage bei Protected override OnMouseMove beim Parentcotnrol ebenso durch alle Controls durchgehst und an WM_MOUSEMOVE über deren Handle die Nachricht weiterleitest, kannst als lParam ja das Parenthandle mit übergeben. Sollte deren eigener MouseMove dennoch interpretieren können. Wäre das selbe wie halt bei Khalid's beispiel nur nen fitzelchen weniger Code.

Wie vernichtet stand Andreas unter den flammenden Augen seiner Kunden.
Ihm war's, als stünde des Schicksals dunkle Wetterwolke über seinem Haupte X(

X
2.051 Beiträge seit 2004
vor 15 Jahren

sein erster einsatz ist doch ganz ok.

die einzige änderung ist doch hier nötig:

void added_MouseMove(object sender, MouseEventArgs e)
{
            ((Control)sender).Parent.OnMouseMove(e);
}

hier sollte man einfach statt parents OnMouseMove aufzurufen, gleich die richtigen koordinaten berechnen.

es geht auch ganz einfach: also von den sender-control koordinaten in die screen koordinaten und dann in die client koordinaten des hauptcontainers (Controlklasse).