c# - 鼠标事件发送者如何为空? (仅适用于 Windows 8.1+ TOUCH)

标签 c# winforms event-handling touch mouseevent

这只发生在 Windows 8.1+ 触控设备上。我有一些面板,用户可以在其中用手指滑动。我已经实现了 PreFilterMessage 这样我就可以在整个应用程序中捕捉到鼠标的全局移动,而不必担心子控件的干扰。

在触摸设备上单击表单时,我有时会收到一般错误:

IsCanceledMove() Object reference not set to an instance of an object.

我在没有工具栏或工具条的空白表单中进行测试。只有两个面板。一个有大标签,另一个有按钮和文本框。这是我的鼠标移动过滤器,我将引发事件的发送者传递给引发异常的函数。

private static void mouseFilter_MouseFilterMove(object sender, MouseFilterEventArgs e)
{
     IsCanceledMove(sender as Control);
}

public bool PreFilterMessage(ref Message m)
{
      Point mousePosition = Control.MousePosition;
      var args = new MouseFilterEventArgs(MouseButtons.Left, 0, mousePosition.X, mousePosition.Y, 0);

      switch (m.Msg)
      {
          case WM_MOUSEMOVE:
              if (MouseFilterMove != null)
                     MouseFilterMove(Control.FromHandle(m.HWnd), args);
              break;

            // more cases
      }

        // Always allow message to continue to the next filter control
        return args.Handled;
}

接下来,我将检查被移过的控件是否是一个文本框,以及它的文本是否被突出显示。我还检查了另一个公共(public)类的静态 bool 变量。如果其中任何一个为真,我将 LastTouchedPanel 设置为 null。 (属于 Panel 类型)

// On Mouse move check if text is behing high lighted
private static void IsCanceledMove(Control c)
{
     try
     {
          // If highlighting text, stop moving
          if (c.GetType() == typeof(TextBox))
              if ((c as TextBox).SelectionLength > 0)
                  LastTouchedPanel = null;

          // Checks a static boolean variable from another control class.
          if (UKSlider.IsSliding)
               LastTouchedPanel = null;
     }
     catch (Exception ex)
     {
          MessageBox.Show("IsCanceledMove() " + ex.Message);
     }
}

如果对象为空,对象如何发送事件?对于 ARM 设备如何处理?这适用于 Vista 到 Windows 10,但不适用于 Windows 10 ARM。

编辑:我注意到 Control.FromHandle(m.HWnd) 有时会在我的 PreMessageFilter 和 ARM 设备中返回 Null。放入空检查显然可以解决异常,但是会错过一些移动事件。

最佳答案

空鼠标事件发送者与使用 IMessageFilter 直接相关在触摸设备上。我在 Windows 8.1 触摸设备和 Windows 10 上看到过这种情况。

我在我的应用程序 PreFilterMessage 事件的开头开始。我想确保确实有一个由 Control.FromHandle 创建的空发件人。果然,我可以看到,有时只需触摸窗体上的空白区域就会返回空控件。据推测,无法转换为 .NET 控件类型的窗口句柄。

带有自定义控件的表单是空的。我确定只使用对 Control.FromHandle 安全的控件。

所以这让我想到了一个大问题 - 我如何才能在尝试转换这些控件时获得空引用?

因为我知道有问题的控件无法转换为 .NET 控件,所以我转向窗口句柄查找一些信息。我注意在 null 控件上引发的窗口句柄。

当我单击表单中的空白区域时,我可以看到我按预期获得了表单的窗口句柄。我注意到,当我获得空引用时,句柄并非来 self 的应用程序中的任何控件。

我认为实际上只有一个答案,手势 Controller 或类似的东西。这是我开始尝试一些手势的时候。就是这样,几个小时以来我第一次很高兴看到空引用异常。

事实证明,用一根手指移动会在表单的 PreMessageFilter 中获得鼠标移动。用两个 手指移动,您可以从手势 Controller 获取表单的mousemove AND 作为mousemove 消息。无法使用 Control.FromHandle 将手势 Controller 转换为控件。

这里发生的事情是我在测试期间变得懒惰,并在单击时将手掌放在触摸屏上。

对于我的场景,我知道我只想处理鼠标移动而不关心手势。我可以忽略空句柄。如果您想同时处理这两者,我认为您应该在 PreMessageFilter 中忽略它,并使用手势消息正确处理手势。

关于c# - 鼠标事件发送者如何为空? (仅适用于 Windows 8.1+ TOUCH),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51760083/

相关文章:

C# .NET Web 服务并返回具有子对象列表的对象列表

C# winform 删除然后将更多项目添加到面板控件

c# - ListView问题: it does not Jump to the selected item

reactjs - react-sortable-hoc : Handling of click event on list item

java - 为什么此代码有 "one off error"?

c# - 用户控制事件

c# - 在任务计划程序 2.0 中获取错误代码 -2147216615

c# - 传递页面的查询字符串时未触发 AjaxFileUpload1_UploadComplete 事件

C# - 为什么::-operator 与全局关键字而不是点运算符相关联?

c# - 为什么我的图像无法打印到 PrintDocument?