DevExpress WaitForm和PreFilterMessage - 意外的MouseMove消息

时间:2015-10-02 11:41:36

标签: c# .net devexpress

我需要在我的软件中使用应用程序空闲时间。出于这个原因,我创建了一个帮助类ApplicationIdleHelper,它实现了IMessageFilter接口。

这很好用,如果我的应用程序闲置一段时间,我会使用以下代码行显示DevExpress WaitForm

SplashScreenManager.ShowForm(typeof(WaitForm));

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

SplashScreenManager.CloseForm();

以下是步骤中解释的问题:

  1. 鼠标光标位于表单上。
  2. 用户暂时不做任何事情 - >空闲时间 - >所以我展示了WaitForm
  3. 现在我的MouseMove message方法中出现PreFilterMessage了吗?但为什么?老鼠没动。没有按键?因为我的应用程序认为MouseMove message,用户会做一些输入并自动关闭WaitForm
  4. 如果我关闭WaitForm,行为相同。

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

    DevExpress文档说:

      

    等待表单和启动画面由启动画面管理器显示   在另一个线程中。

    也许这与这种行为有关?

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

    提前谢谢。

1 个答案:

答案 0 :(得分:2)

最可能的原因是鼠标对环境噪音很敏感。鼠标完全有可能经历一点点抖动,导致它报告非常小的运动,最终导致零位变化。或者,这未经验证,系统上的Windows或其他软件可能会生成额外的鼠标移动消息,以确保每个人都与当前鼠标位置保持同步。

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

  1. 在您入睡时捕捉鼠标位置。
  2. 每次收到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)

  3. 每当您处理硬件时,您需要准备好向它发送您不期望的更新。例如,按下按钮可能导致物理接触反弹,从而导致电气水平的多个按压/断开信号。大多数情况下,硬件设计用于过滤噪声,但有时会渗透。