Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

VB .NET: using onMouseLeave on form

Posted on 2004-11-01
20
Medium Priority
?
278 Views
Last Modified: 2010-04-24
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!
0
Comment
Question by:majnun
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
20 Comments
 
LVL 4

Expert Comment

by:andrewharris
ID: 12469270
I would use the fors LostFocus Event instead.

Andrew
0
 

Author Comment

by:majnun
ID: 12469490
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.
0
 
LVL 8

Expert Comment

by:toddhd
ID: 12469667
   Protected Overrides Sub OnMouseMove(ByVal e As System.Windows.Forms.MouseEventArgs)
        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
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
LVL 8

Expert Comment

by:toddhd
ID: 12469669
Sorry, change the form values to whatever you want - but you get the idea
0
 

Author Comment

by:majnun
ID: 12469701
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.

0
 
LVL 8

Expert Comment

by:toddhd
ID: 12469724
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.
0
 

Author Comment

by:majnun
ID: 12469842
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.MousePosition).X
        My = Me.PointToClient(Me.MousePosition).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.
0
 

Author Comment

by:majnun
ID: 12469868
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?
0
 
LVL 1

Expert Comment

by:hagipmc
ID: 12470899
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.
"
0
 
LVL 8

Expert Comment

by:toddhd
ID: 12472379
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" :)
0
 
LVL 8

Expert Comment

by:toddhd
ID: 12472573
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.MousePosition)
            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
0
 

Author Comment

by:majnun
ID: 12484022
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?

0
 

Author Comment

by:majnun
ID: 12484131
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.MousePosition).X
        My = Me.PointToClient(Me.MousePosition).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.
0
 

Author Comment

by:majnun
ID: 12484144
Woops, don't need the  Xoffset, Yoffset dimmed in the above.
0
 

Author Comment

by:majnun
ID: 12484250
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!
0
 

Author Comment

by:majnun
ID: 12484306
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.
0
 

Author Comment

by:majnun
ID: 12484942
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.ElapsedEventArgs) _
                            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.MousePosition).X
        My = Me.PointToClient(Me.MousePosition).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(ByVal sender As Object, ByVal e As System.EventArgs) Handles lblPlaylist.MouseHover
        pop()
    End Sub

    Public Sub MediaPlayer_MouseLeave(ByVal 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!
0
 

Author Comment

by:majnun
ID: 12485072
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?
0
 

Accepted Solution

by:
modulo earned 0 total points
ID: 12799397
PAQed with points refunded (500)

modulo
Community Support Moderator
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction As chip makers focus on adding processor cores over increasing clock speed, developers need to utilize the features of modern CPUs.  One of the ways we can do this is by implementing parallel algorithms in our software.   One recent…
If you need to start windows update installation remotely or as a scheduled task you will find this very helpful.
Want to learn how to record your desktop screen without having to use an outside camera. Click on this video and learn how to use the cool google extension called "Screencastify"! Step 1: Open a new google tab Step 2: Go to the left hand upper corn…
We’ve all felt that sense of false security before—locking down external access to a database or component and feeling like we’ve done all we need to do to secure company data. But that feeling is fleeting. Attacks these days can happen in many w…

636 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question