如何使用可点击控件创建半透明叠加层

How to create a semi transparent overlay with clickable controls

提问人:elmor6942 提问时间:11/12/2023 更新时间:11/14/2023 访问量:78

问:

我想创建一个带有一些控件的半透明窗口(黑色,带有一些不透明度)(可能是一个 + 和 - 来增加/减少不透明度)。我正在使用 WPF,并查看了以下 stackoverflow 答案

如何制作一个“覆盖”窗口,允许鼠标单击传递到其下方的窗口,但仍允许单击某些控件?

只有当窗口完全透明时,这才有效,添加一些不透明度会破坏叠加行为

如何在 WPF 中创建允许鼠标事件通过的半透明窗口

使用这种方法时,我丢失了控件的单击功能。

如何将这两者结合起来?我可以更改为其他框架,例如 winforms、winui,如果这会让事情变得更容易

C# WPF、 Windows WinForms XAML

评论


答:

0赞 MIHOW 11/14/2023 #1

根据WS_EX_TRANSPARENT解释

WS_EX_TRANSPARENT使您的事件(如鼠标点击)落入您的窗口等。不透明度是一个单独的概念,它指示窗口管理器在绘制表单时应用 alphablending。

所以,如果我理解你的问题是正确的,你希望有一个允许单击它下面的对象,但该窗口上也有可点击的控件。Transparent Window

为此,您需要找到折衷方案。

因为当您应用它时,它不再可点击,因此为了返回正常窗口,您需要以某种方式触发重置方法。WS_EX_TRANSPARENTWS_EX_TRANSPARENT

我在 中创建了一个示例。NET6 和 WPF,我在其中切换 ,在事件上。 当然,有必要在尝试重置此示例时将 Window 集中注意力。WS_EX_TRANSPARENTPreviewKeyDownWS_EX_TRANSPARENT

XAML

<Window x:Class="WpfApp8.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:local="clr-namespace:WpfApp8"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        Title="MainWindow"
        Width="300"
        Height="300"
        WindowStyle="None"
        AllowsTransparency="True"
        Topmost="True"
        BorderThickness="5"
        BorderBrush="LimeGreen"
        Background="Transparent"
        PreviewKeyDown="Window_PreviewKeyDown"
        mc:Ignorable="d">

    <DockPanel>
        <Border Height="40"
                DockPanel.Dock="Top"
                Background="Blue"
                MouseDown="Border_MouseDown"/>

        <Button x:Name="button"
                Grid.Row="2"
                Width="75"
                Height="50"
                Margin="10"
                DockPanel.Dock="Bottom"
                Content="Button"
                Click="button_Click"/>

        <Border Background="Black" Opacity="0.5"/>
    </DockPanel>
</Window>

代码隐藏

namespace WpfApp8
{
    public partial class MainWindow : Window
    {
        private bool _borderClicked;

        private IntPtr _handle;

        public MainWindow()
        {
            InitializeComponent();
        }

        protected override void OnSourceInitialized(EventArgs e)
        {
            base.OnSourceInitialized(e);
            _handle = new WindowInteropHelper(this).Handle;
            WindowsServices.SetWindowExNormal(_handle);
        }

        private void button_Click(object sender, RoutedEventArgs e)
        {
            this.BorderBrush = !_borderClicked ? new SolidColorBrush(Colors.Red) : new SolidColorBrush(Colors.LimeGreen);
            _borderClicked = !_borderClicked;
        }

        private void Window_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
        {
            if (e.Key == Key.D1 && (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
            {
                WindowsServices.SetWindowExNormal(_handle);
            }
            else if (e.Key == Key.D2 && (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
            {
                WindowsServices.SetWindowExTransparent(_handle);
            }
        }

        private void Border_MouseDown(object sender, MouseButtonEventArgs e)
        {
            // Drag window
            this.DragMove();
        }
    }

    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);
        }

        public static void SetWindowExNormal(IntPtr hwnd)
        {
            int extendedStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
            SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle & ~WS_EX_TRANSPARENT);
        }
    }
}

Example