允许鼠标事件通过半透明弹出窗口

我正在尝试从Popup的控件执行拖放操作。 被拖动的内容将被放置在拖放的位置,因此当拖动开始时,我想让Popup半透明以允许放置在它下面。 但到目前为止,我没有让鼠标事件通过我的半透明Popup

以下xaml工作正常,当使用鼠标hoverRectangle时, Button仍然可以单击

   

在此处输入图像描述

但是当鼠标hover在PopupRectangle时,以下xaml无法允许鼠标事件通过。

     

在此处输入图像描述

我试图获取RectanglePopupRoot顶级父级,并为可视树中的每个元素显式设置IsHitTestVisibleOpacity ,但它仍然不起作用。 我可以让它工作的唯一方法是将Background / Fill设置为Transparent但它看起来很奇怪并且hover非Transparent的部分仍然失败。

我已经阅读了以下链接,但据我所知,这只适用于Window而不是Popup 。 如何在WPF中创建一个允许鼠标事件通过的半透明窗口

有没有人有任何解决方案或建议? 🙂

感谢@NETscape发表的评论,我试图抓住Popup Window的实际Window 。 它使用以下代码(在Popup最初显示后我可能会添加..)

 // FromVisual can take any Visual inside the Popup.. HwndSource popupHwndSource = HwndSource.FromVisual(rectangle) as HwndSource; 

将此与此问题的答案相结合,我创建了一个附加行为,它添加了可以在Popup任何子项上设置的属性IsPopupEventTransparent 。 起初,此解决方案导致一个错误,在Popup丢失其事件透明度后,该错误迫使用户单击两次以重新激活Window 。 我用“ Mouse.Capture -workaround”解决了这个问题。

 elementInPopup.Dispatcher.BeginInvoke(new Action(() => { Keyboard.Focus(elementInPopup); Mouse.Capture(elementInPopup); elementInPopup.ReleaseMouseCapture(); })); 

可以这样使用

         

PopupBehavior

 public class PopupBehavior { public static readonly DependencyProperty IsPopupEventTransparentProperty = DependencyProperty.RegisterAttached("IsPopupEventTransparent", typeof(bool), typeof(PopupBehavior), new UIPropertyMetadata(false, OnIsPopupEventTransparentPropertyChanged)); public static bool GetIsPopupEventTransparent(DependencyObject obj) { return (bool)obj.GetValue(IsPopupEventTransparentProperty); } public static void SetIsPopupEventTransparent(DependencyObject obj, bool value) { obj.SetValue(IsPopupEventTransparentProperty, value); } private static void OnIsPopupEventTransparentPropertyChanged(DependencyObject target, DependencyPropertyChangedEventArgs e) { FrameworkElement element = target as FrameworkElement; if ((bool)e.NewValue == true) { FrameworkElement topParent = VisualTreeHelpers.GetTopParent(element) as FrameworkElement; topParent.Opacity = 0.4; HwndSource popupHwndSource = HwndSource.FromVisual(element) as HwndSource; WindowHelper.SetWindowExTransparent(popupHwndSource.Handle); } else { FrameworkElement topParent = VisualTreeHelpers.GetTopParent(element) as FrameworkElement; topParent.Opacity = 1.0; HwndSource popupHwndSource = HwndSource.FromVisual(element) as HwndSource; WindowHelper.UndoWindowExTransparent(popupHwndSource.Handle, element); } } } 

WindowHelper 基于这个问题的答案

 public static class WindowHelper { private static Dictionary _extendedStyleHwndDictionary = new Dictionary(); 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) { int extendedStyle = GetWindowLong(hwnd, GWL_EXSTYLE); SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle | WS_EX_TRANSPARENT); if (_extendedStyleHwndDictionary.Keys.Contains(hwnd) == false) { _extendedStyleHwndDictionary.Add(hwnd, extendedStyle); } } public static void UndoWindowExTransparent(IntPtr hwnd, FrameworkElement elementInPopup) { if (_extendedStyleHwndDictionary.Keys.Contains(hwnd) == true) { int extendedStyle = _extendedStyleHwndDictionary[hwnd]; SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle); // Fix Focus problems that forces the users to click twice to // re-activate the window after the Popup loses event transparency elementInPopup.Dispatcher.BeginInvoke(new Action(() => { Keyboard.Focus(elementInPopup); Mouse.Capture(elementInPopup); elementInPopup.ReleaseMouseCapture(); })); } } } 

问题不在于弹出窗口,但问题是当应用于矩形时颜色为Green ,这有效地阻止了鼠标事件通过

尝试使用透明背景下面的示例,我放置了一个边框来显示存在

       

所以任何具有non zero alpha分量的颜色都会阻止鼠标事件

请参阅下面的alpha示例

  • #FF00FF00绿色Fail
  • #9900FF00半透明绿色Fail
  • #0100FF00几乎看不见绿色Fail
  • #0000FF00全透明绿色Pass

所以你需要有透明的颜色才能传递鼠标事件

由于弹出窗口是在应用程序窗口顶部生成的分层窗口,因此如果您需要背景,则可能需要实现如何创建半透明窗口解决方案。 在wpf中似乎没有构建解决方案