我的贴子“怎么知道鼠标在控件上面刚停下?”里问了一个问题,可是觉得大家的处理不太理想,我好好查了一下Control的用法,终于得到了一个较好的处理方法。原贴地址:
http://community.csdn.net/Expert/topic/5193/5193513.xml?temp=.569195我的处理是这样的:
重写控件的MouseHover及MouseMove两个基类的方法,如下:protected override void OnMouseHover(EventArgs e)
{
System.Console.WriteLine(DateTime.Now);
base.OnMouseHover(e);
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
base.ResetMouseEventArgs();
}
注释:
把上面的代码放入到自己的代码里(如果是窗体里则直接放,如果继承的控件,就放到控件的代码里)编译程序及运行后,大家就会看到每当鼠标停下来的时候都会引发一次MouseHover事件而会在输出窗口里输出当前时间的字符串,真在太高兴了。
因为这也是个技术问题,只不过自己解决了,特来感谢原贴参与者并放分一次。
------------
好希望能把这个加入FAQ!
http://community.csdn.net/Expert/topic/5193/5193513.xml?temp=.569195我的处理是这样的:
重写控件的MouseHover及MouseMove两个基类的方法,如下:protected override void OnMouseHover(EventArgs e)
{
System.Console.WriteLine(DateTime.Now);
base.OnMouseHover(e);
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
base.ResetMouseEventArgs();
}
注释:
把上面的代码放入到自己的代码里(如果是窗体里则直接放,如果继承的控件,就放到控件的代码里)编译程序及运行后,大家就会看到每当鼠标停下来的时候都会引发一次MouseHover事件而会在输出窗口里输出当前时间的字符串,真在太高兴了。
因为这也是个技术问题,只不过自己解决了,特来感谢原贴参与者并放分一次。
------------
好希望能把这个加入FAQ!
也就是说dwFlags = TME_HOVER + TME_LEAVE
应该是把悬停和离开的事件都重置了,我的建议是自己调用_TrackMouseEvent方法只重置TME_HOVER,稍后给出源码。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;namespace WindowsApplication1
{
public partial class Form1 : Form
{
bool flag = false;
public Form1()
{
InitializeComponent();
} private bool MyTrackMouseEvent(IntPtr handle)
{
TRACKMOUSEEVENT tme = new TRACKMOUSEEVENT();
tme.dwFlags = 1; //注意这里,这里只重置了TME_HOVER
tme.hwndTrack = handle;
return _TrackMouseEvent(tme);
}
[DllImport("comctl32.dll", ExactSpelling = true)]
private static extern bool _TrackMouseEvent(TRACKMOUSEEVENT tme); private void button1_MouseMove(object sender, MouseEventArgs e)
{
if (flag)
{
MyTrackMouseEvent((sender as Control).Handle);
flag = !flag;
}
} private void button1_MouseHover(object sender, EventArgs e)
{
textBox1.AppendText(DateTime.Now.ToString()+"\n");
flag = true;
}
}
[StructLayout(LayoutKind.Sequential)]
public class TRACKMOUSEEVENT
{
public int cbSize;
public int dwFlags;
public IntPtr hwndTrack;
public int dwHoverTime;
public TRACKMOUSEEVENT() {
this.cbSize = Marshal.SizeOf(typeof(TRACKMOUSEEVENT));
this.dwHoverTime = 400;
}
}
}
其它有人试也是这样吗?
怎么我这里不是?TO flyforlove(为情飞) ( ) 信誉:100 Blog
不想调用API来做。
不明白你的意思,
我不是已经调用到了吗?
to hbxtlhx(平民百姓) 因为调用了 ResetMouseEventArgs,猜测是这样,等我试试
---------不会的,你看了源代码就知道了它只发送windows不能发送的wm_buttonhover和wm_buttonleave
加一个Timer,间隔设在你想要的时间(就是鼠标停在控件上多久引发“停下”事件)
在 MouseMove 事件里 Enable 这个 Timer,同时保存当前鼠标的XY坐标
在 Timer_Tick 事件里检查当前鼠标的XY坐标是否与保存下来的一样,如果一样则说明鼠标停止移动了,这时 Disable 这个 Timer 同时手动触发你想要的事件(可以自己写一个或者直接调用你想调用的代码)
我個人認為
1.要么在move事件中預測鼠标在停止前很短時間運行趨勢,也就是判斷坐標變化趨勢來判斷是否要停止了。不是狠准確,前一帖偶說過了。
2.使用timer等,在mousemove也不觸發時也能比較坐標,從而判斷出鼠标停止了。
3.要么改寫鼠标事件觸發機制。不知道怎么作
{
try
{
......
}
finally
{
base.OnMouseMove(e);
base.ResetMouseEventArgs();
}
}protected override void OnMouseHover(EventArgs e)
{
base.OnMouseHover(e); //将断点设在此,居然没反应
}
Server Error in '/' Application.
--------------------------------------------------------------------------------Invalid postback or callback argument. Event validation is enabled using <pages enableEventValidation="true"/> in configuration or <%@ Page EnableEventValidation="true" %> in a page. For security purposes, this feature verifies that arguments to postback or callback events originate from the server control that originally rendered them. If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation method in order to register the postback or callback data for validation.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. Exception Details: System.ArgumentException: Invalid postback or callback argument. Event validation is enabled using <pages enableEventValidation="true"/> in configuration or <%@ Page EnableEventValidation="true" %> in a page. For security purposes, this feature verifies that arguments to postback or callback events originate from the server control that originally rendered them. If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation method in order to register the postback or callback data for validation.Source Error: An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below. Stack Trace:
[ArgumentException: Invalid postback or callback argument. Event validation is enabled using <pages enableEventValidation="true"/> in configuration or <%@ Page EnableEventValidation="true" %> in a page. For security purposes, this feature verifies that arguments to postback or callback events originate from the server control that originally rendered them. If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation method in order to register the postback or callback data for validation.]
System.Web.UI.ClientScriptManager.ValidateEvent(String uniqueId, String argument) +2082537
System.Web.UI.Control.ValidateEvent(String uniqueID, String eventArgument) +106
System.Web.UI.WebControls.TextBox.LoadPostData(String postDataKey, NameValueCollection postCollection) +31
System.Web.UI.WebControls.TextBox.System.Web.UI.IPostBackDataHandler.LoadPostData(String postDataKey, NameValueCollection postCollection) +11
System.Web.UI.Page.ProcessPostData(NameValueCollection postData, Boolean fBeforeLoad) +408
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +3776
--------------------------------------------------------------------------------
Version Information: Microsoft .NET Framework Version:2.0.50727.42; ASP.NET Version:2.0.50727.210
所以可以看出为什么进入控件后,只触发一次这样的事件。
假设说可以多次触发的话,那么触发一次后,下一次从什么时候开始计算?比如说鼠标一直在4X4的范围内运动,那么是不是超过400毫秒后,一直都要触发这个事件呢?所以严格来按照mousehover的定义,必须在每次触发mousehover事件后,再次寻找开始点。严格来说,楼主给出的代码有缺陷,
一个是,只要鼠标运动,就会重新注册时间(也就是说发送TrackMouseEvent)
再就是,只要鼠标不停,即时是在给定的范围内运动,都不会触发mousehover事件,这个不符合定义。
我上面给的一个例子,用了一个flag变量,就是为了寻找下一次的开始点,我用的是触发一次mousehover后,再开始计算。
改为
另外,mousehover事件并不是鼠标停止以后发生的,它有个时间和范围,
一个是,只要鼠标运动,就会重新注册时间(也就是说发送TrackMouseEvent)
改为
一个是,只要鼠标运动,就会重新注册事件(也就是说发送TrackMouseEvent)
-------------------
你使用API根本不在我們討論范圍!
不過我是上層軟件編程,能不用API就不用.
偵測滑鼠Leave及Hover事件
C++ void Class::OnMouseMove(UINT nFlags, CPoint point)
{
TRACKMOUSEEVENT trackmouseevent;
trackmouseevent.cbSize = sizeof(trackmouseevent);
trackmouseevent.dwFlags = TME_HOVER | TME_LEAVE;
trackmouseevent.hwndTrack = GetSafeHwnd();
trackmouseevent.dwHoverTime = 0x00000001;
_TrackMouseEvent(&trackmouseevent);
Class::OnMouseMove(nFlags, point);
}
我在北京,税前9K
-------------------------------
佩服樓主,象你學習!
多半是主管了!經理之類吧,純粹程序員恐怕拿不了!
private void dataGrid1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
Thread.Sleep(500);//这句是废话,跟断点加的
base.ResetMouseEventArgs();
}//这样就成,谢楼长 终于明白怎么重置这家伙了;
{
base.OnMouseHover(e);
this.ResetMouseEventArgs();
}这个效果更好.
不知道是不是LZ想要的效果呢