majnun
asked on
VB .NET: using onMouseLeave on form
I'm creating a form that expands, and when the user moves the mouse off the expanded form, I want to trigger the resize to normal. It also seems that if the mouse enters a control on the form it triggers the form's onMouseleave event.
I am setting the size by: me.height = 100
But the onMouseleave event seems to fire when the mouse moves onto a control, or moves past the OLD size of the form.
How can I get the onMouseleave event not to fire if i move into a control it owns, and to use the form's new size when calculating if the user has moved the mouse out of it?
Is this a good approach: when the form's onMouseLeave event is triggered determine if the mouse is in the border of the form? How would I do that?
Thanks!
I am setting the size by: me.height = 100
But the onMouseleave event seems to fire when the mouse moves onto a control, or moves past the OLD size of the form.
How can I get the onMouseleave event not to fire if i move into a control it owns, and to use the form's new size when calculating if the user has moved the mouse out of it?
Is this a good approach: when the form's onMouseLeave event is triggered determine if the mouse is in the border of the form? How would I do that?
Thanks!
ASKER
Yeah, but the expanded form might be covering up the other windows, so it's better to use a modified "mouseOut" functionality so that the user can actually click the other forms to change the focus.
I'm working on figuring out how to check the mouse position against the actual boundaries of the form.
I'm working on figuring out how to check the mouse position against the actual boundaries of the form.
Protected Overrides Sub OnMouseMove(ByVal e As System.Windows.Forms.Mouse EventArgs)
If (e.X > 0 And e.X < Me.Width) And (e.Y > 0 And e.Y < Me.Height) Then
Me.Width = 400
Me.Height = 400
Else
Me.Width = 300
Me.Height = 300
End If
End Sub
If (e.X > 0 And e.X < Me.Width) And (e.Y > 0 And e.Y < Me.Height) Then
Me.Width = 400
Me.Height = 400
Else
Me.Width = 300
Me.Height = 300
End If
End Sub
Sorry, change the form values to whatever you want - but you get the idea
ASKER
toddhd:
on the right track, but the problem is that it only shrinks when i move the mouse out slowly to the left... if i move out quickly or exit the form rectangle in any other direction it stays at the bigger dimensions.
on the right track, but the problem is that it only shrinks when i move the mouse out slowly to the left... if i move out quickly or exit the form rectangle in any other direction it stays at the bigger dimensions.
I'll keep thinking - in the meantime, if it's not a high-perf app, you can add a loop or timer somewhere to call OnMouseMove on a given interval - say, every one second. That might help. Better yet, skip the event altogether and just track the mouse in a loop (I'm old an school game programmer - that's how I'd do it anyway).
Just FYI - I'm not having that problem on my machine - even fast, it's working.
Just FYI - I'm not having that problem on my machine - even fast, it's working.
ASKER
Ok here's what i did and it works (add to the forms onMouseLeave event):
Dim X, Y, Xoffset, Yoffset, Mx, My As Integer
Dim off As Boolean = False
Xoffset = 5 'border pixels
Yoffset = 35 'titlebar & border pixels
X = Me.Width - Xoffset
Y = Me.Height - Yoffset
Mx = Me.PointToClient(Me.MouseP osition).X
My = Me.PointToClient(Me.MouseP osition).Y
If Mx >= X Or Mx < 1 Then off = True
If My >= Y Or My < 1 Then off = True
If off then 'shrink window
Can someone help me refine this so that it automatically takes the title bar and form border into consideration, so that i can use the same function for different form types (with and without title bars, dialogs, etc. etc.) and at different screen resolutions (becase as it stands i think the offsets will need to change based on the screen resolution, no?)
If anyone has a better way of doing this please let me know.
Dim X, Y, Xoffset, Yoffset, Mx, My As Integer
Dim off As Boolean = False
Xoffset = 5 'border pixels
Yoffset = 35 'titlebar & border pixels
X = Me.Width - Xoffset
Y = Me.Height - Yoffset
Mx = Me.PointToClient(Me.MouseP
My = Me.PointToClient(Me.MouseP
If Mx >= X Or Mx < 1 Then off = True
If My >= Y Or My < 1 Then off = True
If off then 'shrink window
Can someone help me refine this so that it automatically takes the title bar and form border into consideration, so that i can use the same function for different form types (with and without title bars, dialogs, etc. etc.) and at different screen resolutions (becase as it stands i think the offsets will need to change based on the screen resolution, no?)
If anyone has a better way of doing this please let me know.
ASKER
I like toddhd solution of overriding the onMouseMove sub better than mine, seems more efficient... i wonder why i cant get it to work properly... any thoughts?
majnun ,
check out bounds property!
from msdn:
"
.NET Framework Class Library
Control.Bounds Property
Gets or sets the size and location of the control including its nonclient elements.
[Visual Basic]
Public Property Bounds As Rectangle
[C#]
public Rectangle Bounds {get; set;}
[C++]
public: __property Rectangle get_Bounds();
public: __property void set_Bounds(Rectangle);
[JScript]
public function get Bounds() : Rectangle;
public function set Bounds(Rectangle);
Property Value
A Rectangle that represents the size and location of the control including its nonclient elements.
Remarks
The bounds of the control includes the nonclient elements such as scroll bars, borders, title bars, and menus. The SetBoundsCore method is called to set the Bounds property. The Bounds property is not always changed through its set method so you should override the SetBoundsCore method to ensure that your code is executed when the Bounds property is set.
"
check out bounds property!
from msdn:
"
.NET Framework Class Library
Control.Bounds Property
Gets or sets the size and location of the control including its nonclient elements.
[Visual Basic]
Public Property Bounds As Rectangle
[C#]
public Rectangle Bounds {get; set;}
[C++]
public: __property Rectangle get_Bounds();
public: __property void set_Bounds(Rectangle);
[JScript]
public function get Bounds() : Rectangle;
public function set Bounds(Rectangle);
Property Value
A Rectangle that represents the size and location of the control including its nonclient elements.
Remarks
The bounds of the control includes the nonclient elements such as scroll bars, borders, title bars, and menus. The SetBoundsCore method is called to set the Bounds property. The Bounds property is not always changed through its set method so you should override the SetBoundsCore method to ensure that your code is executed when the Bounds property is set.
"
Majnun,
FYI again, I think I just "lucked out" last night - I tried it again this morning, and it's not working so well - I'm still working on it when I can... just wanted to let you know "it's not you" :)
FYI again, I think I just "lucked out" last night - I tried it again this morning, and it's not working so well - I'm still working on it when I can... just wanted to let you know "it's not you" :)
Ok, try this:
Protected Overrides Sub OnMouseEnter(ByVal e As System.EventArgs)
Me.Width = 400
Me.Height = 400
End Sub
Protected Overrides Sub OnMouseLeave(ByVal e As System.EventArgs)
Dim Flag As Boolean = False
Dim c As Control
For Each c In Me.Controls
Dim p As Point
p = Me.PointToClient(Me.MouseP osition)
If p.X >= c.Left And p.X <= c.Left + c.Width Then
If p.Y >= c.Top And p.Y <= c.Top + c.Height Then
Flag = True
End If
End If
Next
If Not Flag Then
Me.Width = 300
Me.Height = 300
End If
End Sub
Protected Overrides Sub OnMouseEnter(ByVal e As System.EventArgs)
Me.Width = 400
Me.Height = 400
End Sub
Protected Overrides Sub OnMouseLeave(ByVal e As System.EventArgs)
Dim Flag As Boolean = False
Dim c As Control
For Each c In Me.Controls
Dim p As Point
p = Me.PointToClient(Me.MouseP
If p.X >= c.Left And p.X <= c.Left + c.Width Then
If p.Y >= c.Top And p.Y <= c.Top + c.Height Then
Flag = True
End If
End If
Next
If Not Flag Then
Me.Width = 300
Me.Height = 300
End If
End Sub
ASKER
hagipmc:
Interesting, might be very helpful, but two problems I am having with it though:
1) It doesn't seem to do the trick because:
MsgBox(Me.Bounds.Height & " | " & Me.Height)
Me.Bounds.Height returns the same int as Me.Height
2) If I can get the Bounds to represent the form plus titlebar, borders, etc. when does the onMouseLeave fire? When the mouse moves out of the bounds or out of the area of the form inside the bounds?
Interesting, might be very helpful, but two problems I am having with it though:
1) It doesn't seem to do the trick because:
MsgBox(Me.Bounds.Height & " | " & Me.Height)
Me.Bounds.Height returns the same int as Me.Height
2) If I can get the Bounds to represent the form plus titlebar, borders, etc. when does the onMouseLeave fire? When the mouse moves out of the bounds or out of the area of the form inside the bounds?
ASKER
Ok this works almost perfectly (in the form's onMouseLeave):
Dim X, Y, Xoffset, Yoffset, Mx, My As Integer
Dim off As Boolean = False
X = Me.ClientSize.Width
Y = Me.ClientSize.Height
Mx = Me.PointToClient(Me.MouseP osition).X
My = Me.PointToClient(Me.MouseP osition).Y
If Mx >= X Or Mx < 1 Then off = True
If My >= Y Or My < 1 Then off = True
If off Then popBack() 'resize
I say it works almost perfectly, because if I move the mouse out really fast it doesn't seem to trigger the onMouseLeave event... i'm assuming because the mouse position "jumps" over the boundary of the client area of the form and so never triggers the onMouseLeave event.
Dim X, Y, Xoffset, Yoffset, Mx, My As Integer
Dim off As Boolean = False
X = Me.ClientSize.Width
Y = Me.ClientSize.Height
Mx = Me.PointToClient(Me.MouseP
My = Me.PointToClient(Me.MouseP
If Mx >= X Or Mx < 1 Then off = True
If My >= Y Or My < 1 Then off = True
If off Then popBack() 'resize
I say it works almost perfectly, because if I move the mouse out really fast it doesn't seem to trigger the onMouseLeave event... i'm assuming because the mouse position "jumps" over the boundary of the client area of the form and so never triggers the onMouseLeave event.
ASKER
Woops, don't need the Xoffset, Yoffset dimmed in the above.
ASKER
ok, last thing to do i think is trigger the onMouseLeave event for the form on the onMouseEnter sub of the owning form... anyone know how I can trigger one form's events from another form?
Thanks!
Thanks!
ASKER
ok, on second thought, incase i want to use this for non-owned forms, maybe i'll start a timer when the form is expanded and poll the mouse position every few seconds incase i moved off to fast, then destroy the timer when the form shrinks.
ASKER
Ok, i've figured out a solution which works for me, and in case others find the particular execution useful here's the entirety:
In plain english:
The form (mediaPlayer) has a bunch of controls, one of the controls is a panel (pnlPlaylist) which is "hidden" below the forms border (i size the control so that the panel is not visible, but sits hidden "below" everything else). This panel is revealed when the form pops (expands and reveals the hidden panel). Based on the position of the form in relation to its parent form, it either pops up or pops down. If the form pops down the size increases and reveals the panel, if the form pops up the size increases, the panel jumps to the top of the form, and the other controls are repositioned to the bottom appropriately. I create an arraylist which holds control names which need to be repositioned to the bottom of the form when the form pops down (note i exclude the panel since it is positioned explicity). When the mouse moves out of the form its checks to make sure the mouse position is actually outside the form and then pops back to the smaller position. Just incase the user moves the mouse out to fast, a timer is created and started when the form pops bigger and poles the mouse position every two seconds and closes it if the mouse is off the form (the timer is also disposed whenever the form shrinks),
In code:
Dim popHeight As Integer = 200
Dim poppedDown As Boolean = False
Dim poppedUp As Boolean = False
Dim alControls As New ArrayList()
Dim intPnlPlaylistTop As Integer
Dim WithEvents tmrPop As System.Timers.Timer
Sub tmrPop_Elapsed(ByVal sender As Object, _
ByVal e As System.Timers.ElapsedEvent Args) _
Handles tmrPop.Elapsed
' Respond to event
popBack()
End Sub
Sub pop()
If Me.Height < popHeight Then
tmrPop = New System.Timers.Timer()
tmrPop.Interval = 2000
tmrPop.Start()
If Me.Top < (Me.ParentForm.Size.Height / 2) Then
popDown()
Else
popUp()
End If
End If
End Sub
Sub popDown()
Me.Height = Me.Height + popHeight
poppedDown = True
End Sub
Sub popUp()
Dim ctr As Control
Me.Height = Me.Height + popHeight
For Each ctr In alControls
ctr.Top = ctr.Top + popHeight
Next
intPnlPlaylistTop = pnlPlaylist.Top
pnlPlaylist.Top = 10 'can't be at 0 because i need to pass over the form on the way out to trigger the onMouseLeave event
Me.Top = Me.Top - popHeight
poppedUp = True
End Sub
Sub popBack()
Dim X, Y, Mx, My As Integer
Dim off As Boolean = False
X = Me.ClientSize.Width
Y = Me.ClientSize.Height
Mx = Me.PointToClient(Me.MouseP osition).X
My = Me.PointToClient(Me.MouseP osition).Y
If Mx >= X Or Mx < 1 Then off = True
If My >= Y Or My < 1 Then off = True
If off Then
If poppedUp Or poppedDown Then
tmrPop.Dispose()
End If
If poppedDown = True Then
Me.Height = Me.Height - popHeight
poppedDown = False
End If
If poppedUp = True Then
Dim ctr As Control
Me.Height = Me.Height - popHeight
For Each ctr In alControls
ctr.Top = ctr.Top - popHeight
Next
pnlPlaylist.Top = intPnlPlaylistTop
Me.Top = Me.Top + popHeight
poppedUp = False
End If
End If
End Sub
Private Sub MediaPlayer_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'add all the controls to the alControls arraylist
'use a case to check for control names not to add to arraylist
Dim ctr As Control
For Each ctr In Me.Controls
Select Case ctr.Name
Case "pnlPlaylist" 'controlName, controlName, etc. for controls not to add to the alControls arraylist
Case Else
alControls.Add(ctr)
End Select
Next
End Sub
Private Sub lblPlaylist_MouseHover(ByV al sender As Object, ByVal e As System.EventArgs) Handles lblPlaylist.MouseHover
pop()
End Sub
Public Sub MediaPlayer_MouseLeave(ByV al sender As Object, ByVal e As System.EventArgs) Handles MyBase.MouseLeave
popBack()
End Sub
I will leave this thread open for awhile to see if anyone has come up with a more elegant solution, or has suggestions regarding this implementation.
Thanks!
In plain english:
The form (mediaPlayer) has a bunch of controls, one of the controls is a panel (pnlPlaylist) which is "hidden" below the forms border (i size the control so that the panel is not visible, but sits hidden "below" everything else). This panel is revealed when the form pops (expands and reveals the hidden panel). Based on the position of the form in relation to its parent form, it either pops up or pops down. If the form pops down the size increases and reveals the panel, if the form pops up the size increases, the panel jumps to the top of the form, and the other controls are repositioned to the bottom appropriately. I create an arraylist which holds control names which need to be repositioned to the bottom of the form when the form pops down (note i exclude the panel since it is positioned explicity). When the mouse moves out of the form its checks to make sure the mouse position is actually outside the form and then pops back to the smaller position. Just incase the user moves the mouse out to fast, a timer is created and started when the form pops bigger and poles the mouse position every two seconds and closes it if the mouse is off the form (the timer is also disposed whenever the form shrinks),
In code:
Dim popHeight As Integer = 200
Dim poppedDown As Boolean = False
Dim poppedUp As Boolean = False
Dim alControls As New ArrayList()
Dim intPnlPlaylistTop As Integer
Dim WithEvents tmrPop As System.Timers.Timer
Sub tmrPop_Elapsed(ByVal sender As Object, _
ByVal e As System.Timers.ElapsedEvent
Handles tmrPop.Elapsed
' Respond to event
popBack()
End Sub
Sub pop()
If Me.Height < popHeight Then
tmrPop = New System.Timers.Timer()
tmrPop.Interval = 2000
tmrPop.Start()
If Me.Top < (Me.ParentForm.Size.Height
popDown()
Else
popUp()
End If
End If
End Sub
Sub popDown()
Me.Height = Me.Height + popHeight
poppedDown = True
End Sub
Sub popUp()
Dim ctr As Control
Me.Height = Me.Height + popHeight
For Each ctr In alControls
ctr.Top = ctr.Top + popHeight
Next
intPnlPlaylistTop = pnlPlaylist.Top
pnlPlaylist.Top = 10 'can't be at 0 because i need to pass over the form on the way out to trigger the onMouseLeave event
Me.Top = Me.Top - popHeight
poppedUp = True
End Sub
Sub popBack()
Dim X, Y, Mx, My As Integer
Dim off As Boolean = False
X = Me.ClientSize.Width
Y = Me.ClientSize.Height
Mx = Me.PointToClient(Me.MouseP
My = Me.PointToClient(Me.MouseP
If Mx >= X Or Mx < 1 Then off = True
If My >= Y Or My < 1 Then off = True
If off Then
If poppedUp Or poppedDown Then
tmrPop.Dispose()
End If
If poppedDown = True Then
Me.Height = Me.Height - popHeight
poppedDown = False
End If
If poppedUp = True Then
Dim ctr As Control
Me.Height = Me.Height - popHeight
For Each ctr In alControls
ctr.Top = ctr.Top - popHeight
Next
pnlPlaylist.Top = intPnlPlaylistTop
Me.Top = Me.Top + popHeight
poppedUp = False
End If
End If
End Sub
Private Sub MediaPlayer_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'add all the controls to the alControls arraylist
'use a case to check for control names not to add to arraylist
Dim ctr As Control
For Each ctr In Me.Controls
Select Case ctr.Name
Case "pnlPlaylist" 'controlName, controlName, etc. for controls not to add to the alControls arraylist
Case Else
alControls.Add(ctr)
End Select
Next
End Sub
Private Sub lblPlaylist_MouseHover(ByV
pop()
End Sub
Public Sub MediaPlayer_MouseLeave(ByV
popBack()
End Sub
I will leave this thread open for awhile to see if anyone has come up with a more elegant solution, or has suggestions regarding this implementation.
Thanks!
ASKER
MODERATOR:
Is it possible to change the title of the question to:
"Expanding/Contracting forms: onMouseOut problem"
Since i've included the whole solution in case someone is wondering how to do it?
Is it possible to change the title of the question to:
"Expanding/Contracting forms: onMouseOut problem"
Since i've included the whole solution in case someone is wondering how to do it?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Andrew