关于MouseMove触发频率的问题

唯心还是违心 2018-05-29 05:49:35
最近正在做的项目需要用鼠标绘制线条,在使用MouseMove事件的时候发现,MouseMove事件触发大概是0.1s一次,这就会导致在鼠标快速移动的时候获取到的点间隙很大,本来是条曲线,但是变成多段折线,尝试过很多办法,包括使用Bezier曲线,或者MouseHook,都无法达到理想的效果。查资料说是因为WM_MouseMove消息机制导致的。但是windows附件的绘图工具的曲线绘制显然是非常理想的状况,那么说明windows系统本身对于鼠标位置移动的反馈是足够快速的,但是在不知道在.net当中如何达到这种效果。
...全文
3088 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
xuzuning 2018-05-30
  • 打赏
  • 举报
回复
不会吧?用 System.Diagnostics.Stopwatch 测试了一下,MouseMove 触发间隔在 12ms 左右
        List<double> sp = new List<double>();
        System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
        void panel1_MouseDown(object sender, MouseEventArgs e)
        {
            sw.Start();
        }
        void panel1_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Left)
            {
                sw.Stop();
                sp.Add(sw.Elapsed.TotalMilliseconds);
                sw.Restart();
            }
            if(sp.Count>0) Text = string.Format("{0} {1}", sp.Count, sp.Average());
        }
唯心还是违心 2018-05-30
  • 打赏
  • 举报
回复
找到问题原因了,我自己的问题,我的写代码的机器是通过远程桌面访问,我把EXE文件放到本机之后速度就正常了,应该是远程桌面传输鼠标行为的消息有限制
大鱼> 2018-05-30
  • 打赏
  • 举报
回复
引用 7 楼 u012300857 的回复:
[quote=引用 5 楼 daixf_csdn 的回复:] 另外你这句代码也是可以优化的,改成异步 txtLog.Text +=
这只是我为了看一下执行频率记录的坐标,项目中使用的话肯定没有txtLog这个东西的[/quote] 你这段代码确实看不出来哪里有耗时的,是不是你鼠标还触发了其他事件,或者说有其他方法在占用UI线程
唯心还是违心 2018-05-30
  • 打赏
  • 举报
回复
引用 5 楼 daixf_csdn 的回复:
另外你这句代码也是可以优化的,改成异步 txtLog.Text +=
这只是我为了看一下执行频率记录的坐标,项目中使用的话肯定没有txtLog这个东西的
唯心还是违心 2018-05-30
  • 打赏
  • 举报
回复
引用 4 楼 daixf_csdn 的回复:
[quote=引用 3 楼 u012300857 的回复:] [quote=引用 1 楼 sp1234 的回复:] 说明你的程序卡死了。你看看有没有什么定时器、子线程、Task 之类的东西,卡住了。另外不要在mousemove中直接进行复杂的曲线插值计算,用非常简单的圆弧来大致拟合就可以,然后当用户松开鼠标按键时,才最后进行一次耗时的曲线插值计算。
private void pictureBox1_MouseMove(object sender, MouseEventArgs e) { if (e.Button == System.Windows.Forms.MouseButtons.Left) { //mousePath.AddLine(m_oldX, m_oldY, e.X, e.Y); txtLog.Text += m_oldX.ToString() + "," + m_oldY.ToString() + "," + e.X.ToString() + "," + e.Y.ToString() + "\r\n"; m_oldX = e.X; m_oldY = e.Y; //pictureBox1.Invalidate(); } } 我mousemove部分的代码,已经很简单了,还是110ms执行一次[/quote] 你屏蔽掉的代码才是关键啊。我不信未屏蔽的这部分代码,会这么慢。[/quote] 实际结果是目前这段代码100-110ms执行一次,放开注释之后110-120ms执行一次
圣殿骑士18 2018-05-30
  • 打赏
  • 举报
回复
另外你这句代码也是可以优化的,改成异步 txtLog.Text +=
圣殿骑士18 2018-05-30
  • 打赏
  • 举报
回复
引用 3 楼 u012300857 的回复:
[quote=引用 1 楼 sp1234 的回复:] 说明你的程序卡死了。你看看有没有什么定时器、子线程、Task 之类的东西,卡住了。另外不要在mousemove中直接进行复杂的曲线插值计算,用非常简单的圆弧来大致拟合就可以,然后当用户松开鼠标按键时,才最后进行一次耗时的曲线插值计算。
private void pictureBox1_MouseMove(object sender, MouseEventArgs e) { if (e.Button == System.Windows.Forms.MouseButtons.Left) { //mousePath.AddLine(m_oldX, m_oldY, e.X, e.Y); txtLog.Text += m_oldX.ToString() + "," + m_oldY.ToString() + "," + e.X.ToString() + "," + e.Y.ToString() + "\r\n"; m_oldX = e.X; m_oldY = e.Y; //pictureBox1.Invalidate(); } } 我mousemove部分的代码,已经很简单了,还是110ms执行一次[/quote] 你屏蔽掉的代码才是关键啊。我不信未屏蔽的这部分代码,会这么慢。
唯心还是违心 2018-05-30
  • 打赏
  • 举报
回复
引用 1 楼 sp1234 的回复:
说明你的程序卡死了。你看看有没有什么定时器、子线程、Task 之类的东西,卡住了。另外不要在mousemove中直接进行复杂的曲线插值计算,用非常简单的圆弧来大致拟合就可以,然后当用户松开鼠标按键时,才最后进行一次耗时的曲线插值计算。
private void pictureBox1_MouseMove(object sender, MouseEventArgs e) { if (e.Button == System.Windows.Forms.MouseButtons.Left) { //mousePath.AddLine(m_oldX, m_oldY, e.X, e.Y); txtLog.Text += m_oldX.ToString() + "," + m_oldY.ToString() + "," + e.X.ToString() + "," + e.Y.ToString() + "\r\n"; m_oldX = e.X; m_oldY = e.Y; //pictureBox1.Invalidate(); } } 我mousemove部分的代码,已经很简单了,还是110ms执行一次
  • 打赏
  • 举报
回复
我测试了一下,一秒钟起码能触发100次mousemove 事件。 可见是你的程序卡死了。
  • 打赏
  • 举报
回复
说明你的程序卡死了。你看看有没有什么定时器、子线程、Task 之类的东西,卡住了。另外不要在mousemove中直接进行复杂的曲线插值计算,用非常简单的圆弧来大致拟合就可以,然后当用户松开鼠标按键时,才最后进行一次耗时的曲线插值计算。
源码链接: https://pan.quark.cn/s/eb15aeae54ba 在JavaScript编程中,有时我们需要跟踪用户的鼠标移动,例如在创建交互式绘图工具或游戏时。 这个场景中,开发者遇到了两个核心问题:1. **Question①:优化mousemove事件的数据采集** 当用户移动鼠标时,`mousemove`事件会频繁触发,导致存储了大量的坐标数据(left和top)。 为了解决这个问题,开发者可以考虑以下策略: - **采样率**:不是记录每一个移动,而是每隔一定距离或时间记录一次坐标。 - **平滑处理**:对连续的坐标进行平均,减少不必要的数据点。 - **阈值检查**:如果移动的距离小于某个阈值,不记录这次移动。 2. **Question②:回放过程中的速度调节** 在回放时,由于for循环执行得非常快,使得动画效果瞬间完成,无法观察到中间过程。 为了解决这个问题,开发者尝试使用了一个延迟函数`sleep`,但这种方法并不理想,因为`while`循环会导致主线程阻塞,影响页面其他功能的正常运行。 为了实现平滑的回放效果,开发者最终采用了定时器`setInterval`来逐帧更新小方块的位置。 通过递增一个全局数组下标`iNum`,每次定时器触发时,更新小方块的位置,直到数组遍历完为止。 这种方法允许代码以预设的频率执行,不会阻塞主线程,从而实现了平滑的动画效果。 以下是关键代码片段的说明:```javascript// 延迟方法(未采用,会导致阻塞)// sleep: function(n) {// var start = new Date().getTime();// while (true) {// if (new Date().getT...

111,125

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Creator Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧