mouseover/mouseout funktion (label) - workaround?!
-
Leider empfängt das Panel als Owner des Labels die Nachrichten.
Nur zur Klarstellung: Owner von Controls ist immer die Form. Das Panel kann hier maximal Parent sein.
Caption = "Owner: " + Label1->Owner->Name + ", Parent: " + Label1->Parent->Name;
-
@Jansen
Klar, stimmt. Hatte ich vergessen.F98, das glaube ich dir nicht!
-
wieso benutzt man nicht einfach das MouseMove Ereignis des Formulares? da bekommt man genau die x und y Position der Maus raus und man muss einfach nurnoch eine kleine Kollisionsabfrage machen also vonwegen
bool sichtbar = false; if(x < feld->Left && x > feld-> Left + left->Width && y < feld -> Top && y > Feld -> Top + feld -> Height) { sichtbar = false; } else sichtbar = true
ka ob das geht, sollte aber
-
Nein, das geht nicht!
-
da bin ich ja beruhigt dass ich mit meinem problem nicht alleine bin.
also die einzige lösung, welche ich bisher 'gefunden' habe ist die (von WebFritzi) das mousemove ereignis des umliegenden feldes (groupbox) abzufragen...
-
diese Logikrechungen bringen mich nochma um
das hat mich jetzt genervt deshalb habichs gemacht
, so gehts:
bool sichtbar = false; int get_mousex(void) { TPoint mousepos; GetCursorPos(&mousepos); return mousepos.x; } int get_mousey(void) { TPoint mousepos; GetCursorPos(&mousepos); return mousepos.y; } void TForm1::check(void) { int X = get_mousex()-Left; int Y = get_mousey()-Top; if(X < feld->Left || X > feld-> Left + feld->Width || Y < feld -> Top || Y > feld -> Top + feld -> Height) { sichtbar = false; } else sichtbar = true; anzeige -> Caption = (AnsiString)(int)sichtbar + " " + (AnsiString)X + " " + (AnsiString)Y + " " + feld->Left + " " + feld->Top; } void __fastcall TForm1::FormMouseMove(TObject *Sender, TShiftState Shift, int X, int Y) { check(); } //--------------------------------------------------------------------------- void __fastcall TForm1::feldMouseMove(TObject *Sender, TShiftState Shift, int X, int Y) { check(); } //---------------------------------------------------------------------------
sobald FormMouseMove auftritt kannst du auch die Variable auch gleich zurücksetzen aber vieleicht wilsu da ja auchnoch was machen
das gleiche gilt für feldMouseMove und setzen aber dann kannst du das bitmap nicht genau an Curserposition erscheinen lassen
-
Was willst du mit TForm::OnMouseMove, wenn dieses Ereignis bei dem Problem, das wir hier besprechen, garnicht auftritt. Das, was du da machst, ist schlichtweg brotlose Kunst. Und auch, wenn es funktionieren würde, wäre es zu umständlich. Wozu das check()? Wenn OnMouseMove des Labels (bei dir wohl "feld") ausgeführt wird, dann ist es ja wohl klar, dass sich der Cursor über dem Label befindet (und OnMouseMove der Form wird dann NICHT ausgelöst). Und wozu rufst du zweimal GetCursorPos() auf? Einmal hätte es auch getan. Aber jetzt will ich mal nicht so viel auf dir rumhacken. Es ist schön, dass du dich für andere bemühst. Das macht nicht jeder.
-
Soooo, für alle die es nicht glauben. Hier ist das Projekt mit raYne's Beispiel:
-
Original erstellt von <devil>:
**ich hab ein label und würde gerne als hint ein image anzeigen... - also ein image mit einem bild visible machen sobald man über das element fährt. leider gibt es kein mouseoverevent beim lable... aber das mousemove tut es da eigentlich auch.das problem ist das mouseout event, denn das gibts auch nicht... wie weiss ich also, wann ich das image wieder verstecken muss!?
hat einer ne idee?
danke**
Label haben durchaus ein MouseOver WebFritzi, das stand in seinem Post auch drin
ich weiss das das nicht die Optimallösung ist aber es funktioniert.. nur muss jede Komponente check im MouseOver haben(und so ziemlich jede sichtbare Komponente hat ein MouseOver ist glaubich sogar in TComponent drin)
und ich mach 2 mal GetCursorPos weil ich mir die beiden Funktionen fest wo reingeschreiben hab und verwende ^^ sooo viel Zeit hatte ich auchnicht das ich jetzt alles feinschleife quasi
also im Grunde wollt ich keine Optimallösung schaffen, weil die eh schon lange hier drinsteht sondern quasi nur "beweisen" das es auch anders geht
[ Dieser Beitrag wurde am 01.07.2002 um 09:26 Uhr von dreaddy editiert. ]
-
@F98 : naja, nachdem ich das bpr file etwas editiert habe gings (nich jeder hat deine zusatzkomponenten :))
aber hättest du dir die 'mühe' gemacht und ein panel auf deine form geklatscht und dann darauf das label hättest du gesehen dass es eben nicht geht!
wenn es normal auf der form ist - kein problem, nur sobald es (das label) nicht direk auf der form ist (groupbox, panel etc.) geht das beispiel (jedenfalls SO) nicht mehr!
-
meins geht da mal
man muss nur entweder bei jeder Mausbotschaft die an Application gesendet wird check()aufrufen oder es in jedes MouseMove von jeder halbwegs in der Nähe befindlichen Komponente reinmachen
-
@Devil:
Das mit den Komponenten hatte ich nicht berücksichtigt. Ja ich habe MySQLDAC V1.97 gekauft
Aber es geht ja auch hauptsächlich um die *.h, *.cpp und die *.exe.
Das Problem mit dem Panel kann man ansatzweise wie folgt lösen, es ist aber sicherlich nicht der Weisheit letzter Schluß:
void __fastcall TForm1::OnMouseOver(TMessage & Msg) { if( ((TLabel *)Msg.LParam) == Panel1) // :D { Label1->Caption = "Mouse Over"; } }
Warum bei den VCL-Messages nicht der Name des Labels zurückgeliefert wird würde mich mal interessieren.
Meiner Meinung nach ist es egal worauf das Label abgelegt ist, es muß doch eine Möglichkeit geben an den Namen des Labels unter dem Mauspfeil ranzukommen...
Leider bin ich hier nicht der C++ Held
-
hier mal eine Panel Version
ich habe auch mal ein beispiel project hochgeladen:
http://www.byte-island.com/bcb/mouseover.zipvoid __fastcall TForm1::OnMouseOver(TMessage & Msg) { if(((TLabel *)Msg.LParam) == Label2) ((TLabel *)Msg.LParam)->Color = clRed; else if( ((TPanel *)Msg.LParam) == Panel1 ) { TPoint pos; GetCursorPos(&pos); TControl *control = ((TPanel *)Msg.LParam)->ControlAtPos(((TPanel *)Msg.LParam)->ScreenToClient (pos),false,true); if(control != NULL) if(control->ClassType() == Label1->ClassType()) ((TPanel *)control)->Color = clRed ; } } void __fastcall TForm1::OnMouseOut(TMessage & Msg) { if( ((TLabel *)Msg.LParam) == Label2) ((TLabel *)Msg.LParam)->Color = clYellow; else if( ((TPanel *)Msg.LParam) == Panel1 ) { TPoint pos; GetCursorPos(&pos); TControl *control = ((TPanel *)Msg.LParam)->ControlAtPos(((TPanel *)Msg.LParam)->ScreenToClient (pos),false,true); if(control == NULL) Label1->Color = clYellow ; } }
[ Dieser Beitrag wurde am 01.07.2002 um 14:04 Uhr von raYne editiert. ]
-
möcht ja jetzt echt nich meckern oder so... aber nun setze ich auf das panel noch ne groubox (is bei mir wirklich so) und mach dann dort mein label rein und dann geht es ja wieder nicht....
gibt es da echt keine einheitliche lösung für... muss man da wirklich jede eventualität einzeln berücksichtigen... d.h. wenn ich noch ein panel oder sonstwas hinzufüge, dann kann ich wieder meine ganze funktion umschreiben....!?
-
So, jetzt reichts! <devil>, warum gehst du nicht meinem Vorschlag nach? Auf OnMouseMove der GroupBox reagieren! Scheinbar haben die Leute hier nicht durchgelesen, wo sich das Label von Devil befindet. Hier nochmal für alle:
Das Label befindet sich in einer GroupBox, die auf einem Panel sitzt, das sich auf der Form befindet!
Alles klar? Das heißt: Man kommt mit Message_Handlern nicht weiter. Und man frage sich außerdem, welche BCB-Standard-Events ausgelöst werden, wenn der Cursor das Label verlässt. Die Antwort ist: OnMouseMove der GroupBox, und sonst NICHTS! Das heißt:Er MUSS entweder auf das OnMouseMove der GroupBox reagieren oder für sein Panel ne neue WindowProc machen.
Zu der ersten Variante habe ich ihm schon geraten. Das scheint er aber aus irgendeinem Grund nicht zu wollen. Daher erkläre ich jetzt, wie man für das Label eine neue WindowProc macht, damit sich dieser Thread langsam mal seinem Ende zuneigt:
// HEADER private: Controls::TWndMethod OldLabelProc; void __fastcall NewLabelProc(TMessage& Msg); // CPP-Datei __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { OldLabelProc = Label1->WindowProc; Label1->WindowProc = NewLabelProc; } //------------------------------------------------------------------------------ void __fastcall TForm1::NewLabelProc(TMessage &Msg) { if(Msg.Msg==CM_MOUSEENTER) { // Hier der Code für OnMouseOver } if(Msg.Msg==CM_MOUSELEAVE) { // Hier der Code für OnMouseOut } OldLabelProc(Msg); }
-
@WebFritzi: Warum machst du das immer mit:
OldLabelProc = Label1->WindowProc;
Label1->WindowProc = NewLabelProc;Ich dachte man kann die WindowProc (virtuelle Methode?) überschreiben.
-
*push*
-
*noch ein letztes mal* :p
-
Original erstellt von <blat>:
Ich dachte man kann die WindowProc (virtuelle Methode?) überschreiben.Hi,
ich bin zwar nicht WebFritzi aber ich tu mal so.
Sicherlich gibt es die von Steuerelementen. Ist aber keine virtuelle Methode sondern ein Methodenpointer auf den Typ TWndMethod. Was WebFritzi da macht, ist den Pointer der Komponente zwischenzuspeichern und eine neue eigene Methode hinzufügen.
Am Ende, wenn das Objekt zerstört werden soll, muss der zwischengespeicherte Pointer wieder hergestellt werden. Begründung: Eventuell werden in der Proc noch weitere Routinen aufgerufen, die für die Zerstörung von untergeordneten Objekten zuständig sind.
[ Dieser Beitrag wurde am 26.02.2003 um 19:49 Uhr von AndreasW editiert. ]
-
Neee, das Wichtige am Speichern der OldWndProc ist, dass sie in der neuen WindowProc wieder aufgerufen werden muss (meist am Ende derer). Das verhält sich wie beim Subclassing von Windows-Controls.