Search code examples
c#wpfbordertransparency

C# WPF transparent window with a border


I would like to make a simple application which is transparent but retains the 'normal' borders, close button, minimize and maximize button.

I know how to make the window transparent using the standard

<Window
    WindowStyle="None"
    AllowsTransparency="True"
    Background="Transparent">
</Window>

but this removes the borders and top right buttons. I read this thread,

Transparent window with a border

which sort of gives solution, but really, I just want to be able to keep the standard borders that would be there if I didn't make the window transparent. The means I can move the window, resize, close, etc... Is this possible?


Solution

  • I threw together a quick TransparencyConverter class based on this tutorial on Microsoft.com you can use for this purpose:

    using System;
    using System.Runtime.InteropServices;
    using System.Windows;
    using System.Windows.Interop;
    
    namespace WpfApplication2
    {
        class TransparencyConverter
        {
            private readonly Window _window;
    
            public TransparencyConverter(Window window)
            {
                _window = window;
            }
    
            public void MakeTransparent()
            {
                var mainWindowPtr = new WindowInteropHelper(_window).Handle;
                var mainWindowSrc = HwndSource.FromHwnd(mainWindowPtr);
                if (mainWindowSrc != null)
                    if (mainWindowSrc.CompositionTarget != null)
                        mainWindowSrc.CompositionTarget.BackgroundColor = System.Windows.Media.Color.FromArgb(0, 0, 0, 0);
    
                var margins = new Margins
                {
                    cxLeftWidth = 0,
                    cxRightWidth = Convert.ToInt32(_window.Width) * Convert.ToInt32(_window.Width),
                    cyTopHeight = 0,
                    cyBottomHeight = Convert.ToInt32(_window.Height) * Convert.ToInt32(_window.Height)
                };
    
                if (mainWindowSrc != null) DwmExtendFrameIntoClientArea(mainWindowSrc.Handle, ref margins);
            }
    
            [StructLayout(LayoutKind.Sequential)]
            public struct Margins
            {
                public int cxLeftWidth;
                public int cxRightWidth;
                public int cyTopHeight;
                public int cyBottomHeight;
            }
    
            [DllImport("DwmApi.dll")]
            public static extern int DwmExtendFrameIntoClientArea(IntPtr hwnd, ref Margins pMarInset);
        }
    }
    

    Once you have this in, add the Transparent Background attribute to your XAML and subscribe to the Window_Loaded event and call the MakeTransparent method:

    <Window etc etc Background="Transparent" Loaded="Window_Loaded">
    
    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        var transparencyConverter = new TransparencyConverter(this);
        transparencyConverter.MakeTransparent();
    }
    

    A screenshot is below:

    Screenshot