如何通过设置窗口实时控制程序的不透明度?

Posted

技术标签:

【中文标题】如何通过设置窗口实时控制程序的不透明度?【英文标题】:How can the opacity of a program be controled through a settings window in real time? 【发布时间】:2013-06-06 18:01:03 【问题描述】:

我正在尝试通过实时设置窗口弹出窗口更改主应用程序窗口的Opacity。这样做的正确方法是什么?

到目前为止,我已经尝试使用Slider 将值输出到设置文件。当设置弹出窗口关闭时,主窗口会根据设置文件刷新其 opacity 属性。此方法有效,但我希望能够更改不透明度并实时查看结果。

我尝试的第二种方法是使用Style 并将其应用于主窗口。然后在滑块移动时,样式将被滑块中的值覆盖。这是实时工作的。但无论出于何种原因,即使没有应用任何样式,设置弹出窗口的不透明度也会受到影响

这是一个名为OpacityTest 的示例项目,带有一个主窗口、一个用于打开设置弹出窗口的按钮和一个用于控制程序不透明度的滑块。

App.xaml:

<Application x:Class="OpacityTest.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <Style TargetType="Window" x:Key="wrapper">
            <Setter Property="OverridesDefaultStyle" Value="false"/>
            <Setter x:Name="opacitySetter" Property="Opacity" Value="1"/>
        </Style>
    </Application.Resources>
</Application>

MainWindow.xaml:

<Window x:Class="OpacityTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" Style="DynamicResource wrapper" Background="#FFCDCDCD" AllowsTransparency="True" WindowStyle="None">
    <Grid>
        <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
            <Button Content="Settings" HorizontalAlignment="Center" VerticalAlignment="Center" Width="75" Click="Button_Click"/>
        </StackPanel>
    </Grid>
</Window>

标有设置的新窗口,Settings.xaml:

<Window x:Class="OpacityTest.Settings"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Settings" Height="300" Width="300">
    <Grid>
        <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
            <Slider x:Name="ChangeTransparency" MinWidth="138" MinHeight="22" VerticalAlignment="Center" Padding="0" Orientation="Horizontal" HorizontalAlignment="Center" Value="1" Minimum=".05" Maximum="1" LargeChange=".01" SmallChange=".01" TickFrequency="100" IsSnapToTickEnabled="False" MouseMove="ChangeTransparency_MouseMove"/>
        </StackPanel>
    </Grid>
</Window>

MainWindow.xaml.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace OpacityTest

    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    
        public MainWindow()
        
            InitializeComponent();
        

        private void Button_Click(object sender, RoutedEventArgs e)
        
            Settings settings = new Settings();
            settings.ShowDialog();
        
    

Settings.xaml.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Shapes;

    namespace OpacityTest
    
        /// <summary>
        /// Interaction logic for Settings.xaml
        /// </summary>
        public partial class Settings : Window
        
            public Settings()
            
                InitializeComponent();
            

            private void ChangeTransparency_MouseMove(object sender, MouseEventArgs e)
            
                Style style = new Style  TargetType = typeof(Window) ;
                style.Setters.Add(new Setter(OpacityProperty, Opacity = ChangeTransparency.Value));
                Application.Current.Resources["wrapper"] = style;
            
        
    

【问题讨论】:

有点明显。不要更改样式,这会影响使用该样式的所有窗口。改为更改窗口的不透明度。 【参考方案1】:

看起来您的Style 的行为就像是在 XAML 文件中以影响所有 Windows 的方式声明的,而不仅仅是wrapper 样式,例如 p>

<Style TargetType="Window"> ... </Style>

代替:

<Style TargetType="Window" x:Key="wrapper"> ... </Style>

我不确定如何以您尝试的方式声明它,但完成您尝试做的事情的更简单方法是将其放入 MainWindow.xaml.cs:

private void Button_Click(object sender, RoutedEventArgs e)

    Settings settings = new Settings();
    this.SetBinding(OpacityProperty,
                  new Binding("Value")  Source = settings.ChangeTransparency );
    settings.ShowDialog();

ChangeTransparency 上的处理程序不需要这种方式。我可能会考虑修改 Style 的唯一原因是,如果您可以同时拥有多个 MainWindows,并且想要一个 Settings 窗口(从其中任何一个窗口打开)来一次控制它们。

顺便说一句,如果您确实发现需要附加到 ChangeTransparency,您应该将处理程序附加到其 ValueChanged 事件而不是 MouseMove(虽然 MouseMove 通常会起作用,但实际上不是相同;例如对于键盘输入,只有ValueChanged 会触发)。

如果Settings 可以在其他窗口中使用和/或具有更多属性,您可能希望将Settings 更改为在其构造函数中采用Window(或其他类型),并设置绑定(s ) 那里,以保持您的代码/逻辑集中和干净。

【讨论】:

我也同意在活动中使用ValueChanged。我选择MouseMove 的原因是因为一旦设置窗口打开,滑块的值就会从设置文件中加载。这会引发“System.NullReferenceException”错误,因为我在值上附加了一个标签来显示百分比。由于从设置加载导致值更改时标签为空,因此存在错误。 @MiddleCSharp 啊,我明白了。更好的(恕我直言)处理方法是在您的处理程序中放置一个空检查(例如if (myLabel != null) ...)或bool以指示您何时加载,以防止处理程序出错或做奇怪的事情,例如保存设置的默认值 1(例如,在构造函数的开头,将 bool isLoading 字段设置为 true;在其末尾,将其设置为 false;在您的 ValueChanged 处理程序中,只有在 @987654348 时才这样做@ 是假的)。 你是绝对正确的。我一直在检查if (myLabel == null) give it a value,但仍然导致错误。但是检查是否不相等是要走的路。是否可以使用相同的绑定方法将CornerRadius 绑定到Border?我还没有看到以这种方式工作的 BorderRadius 属性。 是的,应该可以。请参阅 CornerRadius 和 CornerRadiusProperty。如果它不能按原样工作,您可能需要编写一个IValueConverter 用作Converter,它接受double 并返回CornerRadius

以上是关于如何通过设置窗口实时控制程序的不透明度?的主要内容,如果未能解决你的问题,请参考以下文章

如何更改 Qt MainWindow 的不透明度?

如何设置Windows控制台背景为透明色?

Maxim实时时钟芯片设计指南5791-关于编写健壮的实时时钟控制代码的提示

C# - 实时控制台输出重定向

实时控制软件第四周作业

微信小程序如何实现根据实时天气弹出一个提示窗口