WPF发送单击事件穿透控件

4
我想向控件后面的应用程序发送鼠标点击。我有一个最上层的透明窗口和一些控件。我希望能够通过其中一些控件发送点击。
我已经尝试将IsHitTestVisible="False"属性设置为控件,但它不起作用。例如,它无法将点击发送到桌面。
我还尝试了这个问题中提出的解决方案:如何在WPF中创建一个半透明窗口,允许鼠标事件穿过
它可以工作,但我想使某些控件透明,而不是整个窗口。
我该如何将该问题的解决方案应用于单个控件,例如椭圆形?
解决方案:
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发送全局鼠标按下事件。 - Edza
我有一个椭圆形,它作为由Leap Motion控制器控制的光标。实际上,我可以将点击发送到椭圆形的左上角(靠近边界但在椭圆形外),但我想要的是将点击发送到椭圆形的中心。当我这样做时,椭圆形会接收到点击,而不是椭圆形后面的任何东西。例如,除非我将椭圆形的点击点放在椭圆形的边缘附近但在椭圆形外部,否则我无法使用椭圆形来单击文件夹。为了发送点击,我实际上正在使用mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo)。 - kevin
我也尝试使用sendInput和postmessage,但它们都没用,因为椭圆是Topmost并且始终接收鼠标事件。 - kevin
1个回答

0

以这种方式使用路由事件。 在控件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时,控制2中的此方法将被触发

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接