How can I process mouse enter/leave at the form level
I have a form that consists of only a TableLayoutPanel (which fills the entire form) containing a vertical stack of buttons. The resulting app is used in conjunction with another app. What I would like is to have the vb app do something when the mouse enters the form. Unfortunately, all mouse enter/leave events are trapped by the panel or the buttons.
As a quick test I created a form with a tablelayoutpanel (docked to fill the form) containing one button. I added the following code:
Private Sub Form1_MouseEnter(sender As System.Object, e As System.EventArgs) Handles MyBase.MouseEnter
Debug.WriteLine("enter form")
End Sub
Private Sub Form1_MouseLeave(sender As System.Object, e As System.EventArgs) Handles MyBase.MouseLeave
Debug.WriteLine("leave form")
End Sub
Private Sub TableLayoutPanel1_MouseEnter(sender As System.Object, e As System.EventArgs) Handles TableLayoutPanel1.MouseEnter
Debug.WriteLine("enter panel")
End Sub
Private Sub TableLayoutPanel1_MouseLeave(sender As System.Object, e As System.EventArgs) Handles TableLayoutPanel1.MouseLeave
Debug.WriteLine("leave panel")
End Sub
Private Sub Button1_MouseEnter(sender As System.Object, e As System.EventArgs) Handles Button1.MouseEnter
Debug.WriteLine("enter button")
End Sub
Private Sub Button1_MouseLeave(sender As System.Object, e As System.EventArgs) Handles Button1.MouseLeave
Debug.WriteLine("leave button")
End Sub
There was no way of moving the mouse around that caused the form's mouse enter or leave events to fire. Is there anything (perhaps similar to KeyPreview) that lets me see the mouse enter/leave events at the form level? I could always add a common Mouse_Enter event to each button (all buttons are created at runtime) but this seems like a crude way to do it.
10 Months Ago
Last Updated
Reverend Jim
Carpe per diem
3,612 posts since Aug 2010
Reputation Points: 563
Solved Threads: 451
Skill Endorsements: 32
Hi Jim, I ran what you had set up in your test and tried TableLayoutPanel1.SendToBack and Me.BringToFront neither worked, Bummer.
Now for my question since you're getting the Panel MouseEnter event to fire isn't that the same as the Mouse entering the form or do you need the event Argument of the Form enter event. I’m just thinking out loud here.
kRod
Junior Poster in Training
71 posts since May 2012
Reputation Points: 18
Solved Threads: 24
Skill Endorsements: 0
I found this Click Here Might be a solution. I would just call the Forms mouse enter and leave subs from the Panels mouse enter and leave subs.
kRod
Junior Poster in Training
71 posts since May 2012
Reputation Points: 18
Solved Threads: 24
Skill Endorsements: 0
Hi Jim,
If I'm understanding your problem correctly, I think what you want is a message prefilter. These filters are added to the application and filter all application messages. By combining WM_MOUSEMOVE and WM_MOUSELEAVE with a hit test on the clientrectangle you can achieve this.
Public Class Form1
Implements IMessageFilter
Private Const WM_MOUSELEAVE As Int32 = &H2A3
Private Const WM_MOUSEMOVE As Int32 = &H200
Private MouseInForm As Boolean = False
'Add a dock-filled panel to the form to block the normal MouseLeave, MouseEnter Events
Private pnl As New Panel With {.Dock = DockStyle.Fill, .Parent = Me, .BorderStyle = BorderStyle.Fixed3D}
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Application.AddMessageFilter(Me)
End Sub
Public Function PreFilterMessage(ByRef m As System.Windows.Forms.Message) As Boolean Implements System.Windows.Forms.IMessageFilter.PreFilterMessage
If m.Msg = WM_MOUSELEAVE OrElse m.Msg = WM_MOUSEMOVE Then
'hit test the client rectangle
'since WM_MOUSELEAVE does not provide the mouse location, use MousePosition
Dim hit As Boolean = Me.ClientRectangle.Contains(Me.PointToClient(MousePosition))
If hit Then
If Not MouseInForm Then
OnMouseEnter(Nothing)
End If
MouseInForm = True
Else
If MouseInForm Then
OnMouseLeave(Nothing)
End If
MouseInForm = False
End If
End If
End Function
Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
Application.RemoveMessageFilter(Me)
End Sub
Private Sub Form1_MouseEnter(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.MouseEnter
Debug.WriteLine("mouse entered form")
End Sub
Private Sub Form1_MouseLeave(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.MouseLeave
Debug.WriteLine("mouse left form")
End Sub
End Class
TnTinMN
Practically a Master Poster
640 posts since Jun 2012
Reputation Points: 418
Solved Threads: 148
Skill Endorsements: 13
@Krod - Thanks for the suggestion but because the buttons completely fill the TableLayoutPanel, the panel never gets to trigger.
@TNTinMN - Also thanks. I think the prefilter is the way to go, however, I'll need to do a little research to figure out the finer points.
Reverend Jim
Carpe per diem
3,612 posts since Aug 2010
Reputation Points: 563
Solved Threads: 451
Skill Endorsements: 32
Looks like prefilter was the thing. As it turns out, I only really need to trap the mouse enter. Thanks again.
Reverend Jim
Carpe per diem
3,612 posts since Aug 2010
Reputation Points: 563
Solved Threads: 451
Skill Endorsements: 32
Question Answered as of 10 Months Ago by
kRod
and
TnTinMN