如何在WPF中创建半透明窗体

9

我需要在WPF中开发一个半透明表单,但控件不应该是透明的。

我尝试了不同的方法,比如设置opacity=0.5,但没有效果。

  • 我知道只有当窗口样式设置为None时,才能将AllowTransparency设置为True,但我也需要显示边框

更新: Pavlo Glazkov,你对此解决方案有什么看法

<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300" Opacity="1" AllowsTransparency="True" WindowStyle="None" Background="Transparent">
<Grid Background="Transparent">
    <Border Margin="2,2,12,34" Name="border1" BorderBrush="Lavender" BorderThickness="5" CornerRadius="20,0,20,0"></Border>
    <Button Height="23" Margin="93,101,110,0" Name="button1" VerticalAlignment="Top" Background="CadetBlue" Foreground="White">Hello WPF</Button>
    <Button Height="24" Margin="0,8,20,0" Name="button2" VerticalAlignment="Top" HorizontalAlignment="Right" Width="21" Click="button2_Click">X</Button>
</Grid>
</Window>

3
在WPF中不存在表单;您是指窗口还是其他内容? - Aaron McIver
关于“Pavlo Glazkov,您对这个解决方案有什么看法”……嗯,很难说。这取决于您的目标。如果这种边框是您想要的,那么这就是正确的方法。唯一的问题是,在这种情况下,您将拥有完全透明的窗口。实际上,您可以通过它进行单击。如果这不是所需的行为,则应将背景设置为不完全透明的颜色。 - Pavlo Glazkov
@ Pavlo Glazkov - 你说得对,这种答案只是临时解决方案。基本上,我很惊讶微软在WPF中没有提供这种功能。我知道早在2005年就有一些冗长而复杂的代码使用API来实现这种功能,但现在已经是2011年了,我们仍然需要编写冗长的代码,这很丑陋。那么你说的不完全透明的颜色是哪些颜色? - Student
2个回答

15

首先,您需要将 AllowTransperency 设置为 True。然后,您可以将窗口的背景设置为透明(到所需程度)的刷子:

<Window x:Class="MyWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        WindowStyle="None"
        AllowsTransparency="True"
        Background="{DynamicResource WindowBackground}">
    <Window.Resources>
       <SolidColorBrush x:Key="WindowBackground" 
                        Color="White"
                        Opacity="0.5"/>
    </Window.Resources>
    ...
</Window>
请注意,只有在将WindowStyle设置为None时,才能将AllowTransperency设置为True

更新: 如果你不想将WindowStyle设置为None,并希望保留标准边框和窗口按钮,则有一种替代方法,该方法仅适用于具有Windows Aero主题的Windows Vista/7。

诀窍是使用以下代码将“Glass”区域扩展到整个窗口:

public static class WindowUtils
{
    /// <summary>
    /// Extends the glass area into the client area of the window
    /// </summary>
    /// <param name="window">Window to extend the glass on.</param>
    /// <param name="thikness">Thickness of border to extend.</param>
    public static void ExtendGlass(this Window window, Thickness thikness) {
        try {
            int isGlassEnabled = 0;
            Win32.DwmIsCompositionEnabled(ref isGlassEnabled);
            if (Environment.OSVersion.Version.Major > 5 && isGlassEnabled > 0) {
                // Get the window handle
                var helper = new WindowInteropHelper(window);
                var mainWindowSrc = HwndSource.FromHwnd(helper.Handle);

                if (mainWindowSrc != null) {
                    if (mainWindowSrc.CompositionTarget != null) {
                        mainWindowSrc.CompositionTarget.BackgroundColor = Colors.Transparent;
                    }

                    // Get the dpi of the screen
                    System.Drawing.Graphics desktop =
                        System.Drawing.Graphics.FromHwnd(mainWindowSrc.Handle);

                    float dpiX = desktop.DpiX / 96;
                    float dpiY = desktop.DpiY / 96;

                    // Set Margins
                    var margins = new MARGINS {
                        cxLeftWidth = (int)(thikness.Left * dpiX),
                        cxRightWidth = (int)(thikness.Right * dpiX),
                        cyBottomHeight = (int)(thikness.Bottom * dpiY),
                        cyTopHeight = (int)(thikness.Top * dpiY)
                    };

                    window.Background = Brushes.Transparent;

                    Win32.DwmExtendFrameIntoClientArea(mainWindowSrc.Handle, ref margins);
                }
            }
            else {
                window.Background = SystemColors.WindowBrush;
            }
        }
        catch (DllNotFoundException) {

        }
    }
}

public class Win32
{
    [DllImport("dwmapi.dll")]
    public static extern int DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS pMarInset);

    [DllImport("dwmapi.dll")]
    public static extern int DwmIsCompositionEnabled(ref int en);

    [DllImport("user32.dll")]
    public static extern bool SetCursorPos(int X, int Y);


    [DllImport("User32", EntryPoint = "ClientToScreen", SetLastError = true, ExactSpelling = true, CharSet = CharSet.Auto)]
    public static extern int ClientToScreen(IntPtr hWnd, [In, Out] POINT pt);
}

[StructLayout(LayoutKind.Sequential)]
public struct MARGINS
{
    public int cxLeftWidth;
    public int cxRightWidth;
    public int cyTopHeight;
    public int cyBottomHeight;
}

[StructLayout(LayoutKind.Sequential)]
public class POINT
{
    public int x = 0;
    public int y = 0;
}

为了将玻璃扩展到整个窗口,您需要在窗口的SizeChanged事件处理程序中调用ExtendGlass扩展方法,并传递完整覆盖窗口的Thickness

public MyWindow() {
    InitializeComponent();

    SizeChanged += OnSizeChanged;
}

private void OnSizeChanged(object sender, SizeChangedEventArgs e) {
    double horisontalThickness = Width / 2;
    double verticalThickness = Height / 2;

    var glassThickness = new Thickness(horisontalThickness, verticalThickness, horisontalThickness, verticalThickness);

    this.ExtendGlass(glassThickness);
}

我也发过那个帖子,但似乎并没有解决控件不应该是透明的问题。我不知道怎么做。 - Botz3000
然后,您需要将窗口背景设置为透明颜色,而不是设置窗口本身的不透明度。我更新了我的帖子以展示如何实现。 - Pavlo Glazkov
谢谢你的回复。我知道只有在窗口样式设置为“None”时,才可以将AllowTransperency设置为True,但是我也需要显示边框。 - Student
那么你就必须自己创建一个。 - Pavlo Glazkov
好的,您需要自定义透明度设置吗?我可以向您展示如何使用Windows Vista/7玻璃效果使窗口半透明。 - Pavlo Glazkov
显示剩余4条评论

3
你可以尝试使用这个,它可以为你的窗口创建玻璃背景(看起来像Vista和Windows7的透明效果)。 这里有来自Microsoft的进一步解释。

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