I made a custom button with some panels and pictureboxes. With the MouseEnter and MouseLeave I set the appropriate hover images like normal buttons.
The problem is that if I move the mouse too fast over the control it sometimes doesn't trigger the MouseLeave event. This way the button is "locked" in hover state.
screenshot problem: http://www.jesconsultancy.nl/images/screens/screen_prblm.png
the button at the right is locked in "hover" state.
How can 开发者_运维技巧i solve this?
Thanks.
Holy... That's a mess!
Firstly, UserControl
s are very buggy. I suggest you make your control inherit from Control
instead and draw the image and text yourself.
Secondly, why are you using reflection?
Thirdly, why are there so many controls?
This misses the event because it takes too much to update!
Here is some code for the simples control possible, that will NEVER miss an event:
using System;
using System.Drawing;
using System.Windows.Forms;
namespace lol
{
public class BlackWhiteControl : Control
{
protected override void OnMouseEnter(EventArgs e)
{
base.OnMouseEnter(e);
this.BackColor = Color.Black;
}
protected override void OnMouseLeave(EventArgs e)
{
base.OnMouseLeave(e);
this.BackColor = Color.White;
}
}
}
You should receive the WM_MOUSELEAVE windows message automatically when the mouse leaves the client area and the base class processing of this message will then call the OnMouseLeave method. If this is really not happening you can certainly get around it. Just intercept the WM_MOUSEMOVE directly and then make a Win32 API call that requests you be notified when the mouse leaves your control.
Use the following simple WndProc override...
private bool _mouseOver = false;
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case PI.WM_MOUSEMOVE:
if (!_mouseOver)
{
PI.TRACKMOUSEEVENTS tme = new PI.TRACKMOUSEEVENTS();
tme.cbSize = (uint)Marshal.SizeOf(typeof(PI.TRACKMOUSEEVENTS));
tme.dwHoverTime = 100;
tme.dwFlags = (int)(PI.TME_LEAVE);
tme.hWnd = Handle;
PI.TrackMouseEvent(ref tme);
_mouseOver = true;
}
base.WndProc(ref m);
break;
case PI.WM_MOUSELEAVE:
_mouseOver = false;
base.WndProc(ref m);
break;
}
}
And the platform invoke information you need is...
internal const int WM_MOUSEMOVE = 0x0200;
internal const int WM_MOUSELEAVE = 0x02A3;
internal const int TME_LEAVE = 0x0002;
[StructLayout(LayoutKind.Sequential)]
internal struct TRACKMOUSEEVENTS
{
public uint cbSize;
public uint dwFlags;
public IntPtr hWnd;
public uint dwHoverTime;
}
Hope that helps.
精彩评论