我的软件需要应用程序空闲时间。因此,我创建了一个帮助类ApplicationIdleHelper来实现IMessageFilter接口。

这可以正常工作,并且如果我的应用程序处于空闲状态一段时间,则使用以下代码行显示DevExpress WaitForm

SplashScreenManager.ShowForm(typeof(WaitForm));


在此WaitForm中,我向用户显示了有关在后台执行的操作的一些信息。如果用户移动鼠标或按下某些键,我将关闭WaitForm,如下所示:

SplashScreenManager.CloseForm();


这是在步骤中说明的问题:


鼠标光标在窗体上。
用户在一段时间内不执行任何操作->空闲时间->因此我显示WaitForm
现在我在MouseMove message方法中得到一个PreFilterMessage吗?但为什么?鼠标没有动。没有按键?因为我得到了应用程序认为的MouseMove message,所以用户进行了一些输入并自动关闭了WaitForm


如果关闭WaitForm,则行为相同。

这是一个示例应用程序,因此您应该能够重现此行为:
https://drive.google.com/file/d/0BxabrokJG-OWV3FLV2hNNVk5NjQ/view?usp=sharing

DevExpress文档说:


  初始屏幕管理器显示等待表单和初始屏幕
  在单独的线程中。


也许这与该行为有关?

希望有人可以向我解释,为什么我在显示或关闭MouseMove message之后在PreFilterMessage函数中添加WaitForm

先感谢您。

最佳答案

造成这种情况的最可能原因是鼠标对环境噪声敏感。鼠标完全有可能会出现一点抖动,从而导致鼠标报告很小的运动,最终使位置变化为零。另外,未经验证,Windows或系统上的某些其他软件可能会生成额外的鼠标移动消息,以确保每个人都与当前鼠标位置保持同步。

无论哪种方式,最稳定的解决方案是确定您认为“真实”的运动量(请参见下面的threshold),然后:


睡觉时捕获鼠标位置。
每次收到WM_MOUSEMOVE消息(或MouseMove事件)时,都要计算该运动的量,如下所示:

Point cached; // from when you went to sleep
Point current; // determined from the window message/event
double move = Math.Sqrt(Math.Pow(cached.X - current.X, 2) +
                        Math.Pow(cached.Y - current.Y, 2))

if (move > threshold)
{
    // Wake up
}
else
{
    // Ignore and optionally update the cached position
    // in case the mouse is slowly drifting
}


(请注意,您不一定需要那样计算真实距离,您可以使用ΔX+ΔY)


无论何时使用硬件,都需要做好准备以将不需要的更新发送给您。例如,按下一个按钮可能会导致物理接触反弹,从而在电气水平上导致多次按下/断开信号。在大多数情况下,硬件是设计用来过滤噪声的,但有时会渗入。

关于c# - DevExpress WaitForm和PreFilterMessage-意外的MouseMove消息,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32906422/

10-12 17:32