【问题标题】:WPF Send click through controlWPF 发送点击通过控件
【发布时间】:2015-06-13 14:53:18
【问题描述】:

我想向控件后面的应用程序发送鼠标点击。我有一个最顶层的透明窗口和一些控件。我希望能够通过其中一些控件发送点击。

我已经尝试将属性 IsHitTestVisible="False" 设置为控件,但它不起作用。例如,它不会通过控件将点击发送到桌面。

我也试过这个问题中提出的解决方案:How to create a semi transparent window in WPF that allows mouse events to pass through

它可以工作,但我想让一些控件透明,而不是窗口。

如何将该问题的解决方案应用于单个控件,例如椭圆?

解决办法:

public static class WindowsServices
{
  const int WS_EX_TRANSPARENT = 0x00000020;
  const int GWL_EXSTYLE = (-20);

  [DllImport("user32.dll")]
  static extern int GetWindowLong(IntPtr hwnd, int index);

  [DllImport("user32.dll")]
  static extern int SetWindowLong(IntPtr hwnd, int index, int newStyle);

  public static void SetWindowExTransparent(IntPtr hwnd)
  {
    var extendedStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
    SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle | WS_EX_TRANSPARENT);
  }
}

protected override void OnSourceInitialized(EventArgs e)
{
  base.OnSourceInitialized(e);
  var hwnd = new WindowInteropHelper(this).Handle;
  WindowsServices.SetWindowExTransparent(hwnd);
}

【问题讨论】:

  • 你应该做的是在窗口上正常捕获所有鼠标事件。获取屏幕上的窗口位置并将鼠标单击位置添加到该位置。当您在屏幕上获得鼠标点击的绝对位置后,您需要通过 P/Invoke 发送一个全局鼠标按下事件。
  • 我有一个椭圆,其行为类似于由 Leap Motion 控制器控制的光标。实际上我可以将点击发送到椭圆的左角(靠近边框,但在椭圆之外),但我想要的是将点击发送到椭圆的中心。当我这样做时,椭圆会接收点击,而不是椭圆后面的任何内容。例如,我不能使用椭圆单击文件夹,除非我将椭圆单击点放在椭圆边框附近,但在外面。要发送点击,我实际上是在使用 mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo)。
  • 我也尝试过使用 sendInput 和 postmessage,但它不起作用,因为椭圆是最顶层的,它总是接收鼠标事件。

标签: c# wpf click-through


【解决方案1】:

以这种方式使用路由事件。 在控件A中写入点击事件:

 #region - Routed events -
    /// <summary>
    /// Bubble event
    /// </summary>
    public static readonly RoutedEvent ClickEvent =
        EventManager.RegisterRoutedEvent("Click", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof([Class name]));
    public event RoutedEventHandler Click
    {
        add { AddHandler(ClickEvent, value); }
        remove { RemoveHandler(ClickEvent, value); }
    }

    /// <summary>
    /// Fired the click event
    /// </summary>
    /// <param name="sender">this control</param>
    /// <param name="e">routed args</param>
    private void usercontrol_Clicked(object sender, RoutedEventArgs e)
    {
        RoutedEventArgs args = new RoutedEventArgs(LastUnitCycleTime.ClickEvent);
        RaiseEvent(args);
    }
    #endregion - Routed events -

那么您可以在所有其他控件中使用它,只需使用以下方式:

在其他控件构造函数中插入这一行: 在这种情况下 usercontrol2

usercontrol_Clicked += usercontrol2Name_Clicked;

那么这是当你点击 control1 时 control2 中的方法被触发

  private void usercontrol2Name_Clicked(object sender, RoutedEventArgs e)
    {          
        //effort here what you want....
    }

【讨论】:

    猜你喜欢
    • 2013-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多