0

I found the implementation of WPF transparent window WITH BORDERS here C# WPF transparent window with a border. I tried implementing it, but my window is not transparent. No errors come out. Below are the xaml and code behind.

<Window x:Class="WpfApplication9.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Extended Glass in WPF" Height="300" Width="400" 
    Background="Transparent" Loaded="Window_Loaded">

    <Grid ShowGridLines="True" Background="Transparent">
    </Grid>
</Window>

Code behind

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.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Runtime.InteropServices;
using System.Drawing;

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

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            var transparancyConverter = new TransparancyConverter(this);
            transparancyConverter.MakeTransparent();
        }
        [StructLayout(LayoutKind.Sequential)]
        public struct MARGINS
        {
            public int cxLeftWidth;      // width of left border that retains its size
            public int cxRightWidth;     // width of right border that retains its size
            public int cyTopHeight;      // height of top border that retains its size
            public int cyBottomHeight;   // height of bottom border that retains its size
        };


        [DllImport("DwmApi.dll")]
        public static extern int DwmExtendFrameIntoClientArea(
            IntPtr hwnd,
            ref MARGINS pMarInset);
    }
    class TransparancyConverter
    {
        private readonly Window _window;

        public TransparancyConverter(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);
    }
}

In addition, I have tried setting basic transparency in the code behind WITHOUT keeping the border. One will also find my xaml and code behind for this below. The created window is not transparent and just has a white background. What am I doing wrong in both of these examples? I feel like there is a common thread.

<Window x:Class="WpfApplication10.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"
        x:Name="MainWindowGUI"
        >
    <Grid>
    </Grid>
</Window>

Code Behind

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 WpfApplication10
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.Loaded += MainView_Loaded;


        }

        void MainView_Loaded(object sender, RoutedEventArgs e)
        {
            Window yourParentWindow = Window.GetWindow(MainWindowGUI);
            yourParentWindow.WindowStyle = WindowStyle.None;
            yourParentWindow.AllowsTransparency = true;
            SolidColorBrush Transparent = new SolidColorBrush(System.Windows.Media.Colors.Transparent);
            yourParentWindow.Background = Transparent;
        }
    }
}
Community
  • 1
  • 1
Ben
  • 153
  • 9

1 Answers1

1

You need to set AllowsTransparency="True"; for that to work, you're required to set WindowStyle="None". WindowStyle="None" will lose you your non-client area (borders, titlebar, min/max/close buttons), but that's easy enough to work around.

<Window x:Class="WpfApplication9.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Extended Glass in WPF" Height="300" Width="400" 
    Background="Transparent"

    AllowsTransparency="True"
    WindowStyle="None"
    >

    <Grid ShowGridLines="True" Background="Transparent">
    </Grid>
</Window>
  • The point with the above code, though, is that I want a WindowStyle. The reference Stack Over Flow response is supposed to solve that. – Ben Jul 12 '16 at 16:25
  • @Ben You. Can't. Have. One. The non-client area is OS stuff. You might fake up something by creating a second window with nothing *but* a titlebar and kludging stuff to make the transparent window act like that's its titlebar. – 15ee8f99-57ff-4f92-890c-b56153 Jul 12 '16 at 16:31
  • I can't tell if that's sarcasm. If so, LOL. If not, please see the cited post. This code should enable me to do that. – Ben Jul 12 '16 at 16:34
  • @Ben Should, but it doesn't? – 15ee8f99-57ff-4f92-890c-b56153 Jul 12 '16 at 16:35
  • Exactly. I can't figure out what I've written wrong. – Ben Jul 12 '16 at 16:37
  • Please see my altered question. I tried implementing the code you have in the xaml in my code behind. It doesn't work. – Ben Jul 13 '16 at 14:55
  • @Ben Did it say something about "Cannot change AllowsTransparency after a Window has been shown or WindowInteropHelper.EnsureHandle has been called."? – 15ee8f99-57ff-4f92-890c-b56153 Jul 13 '16 at 15:01
  • It doesn't give me any error when I try to capture the error. I also try putting the transparency code in the MainWindow() constructor, and it won't run. – Ben Jul 13 '16 at 15:05
  • @Ben Which constructor, the constructor for the window you're setting the properties on, or some other constructor? What do you mean by "won't run"? And why not set attributes in the XAML? – 15ee8f99-57ff-4f92-890c-b56153 Jul 13 '16 at 15:14
  • The constructor for the window I'm setting the properties on. I start debugging and the constructor MainWindow() fires, but it crashes upon reaching this code if this code is before IntializeComponent(). If this code is after InitializeComponent(), it runs. HOWEVER, I need this code to be in the MainView_Loaded method. – Ben Jul 13 '16 at 15:18
  • @Ben Never put anything before IntializeComponent() in a WPF control/window constructor. And it'll crash if you do it in MainView_Loaded. Why do you say need it to be in MainView_Loaded? – 15ee8f99-57ff-4f92-890c-b56153 Jul 13 '16 at 15:34
  • The above code is a Greatly simplified version of my problem. In my real, much more massive and un-post-able chunk of code, a user control is initiated on start-up. If I try to grab the Parent Window before MainView_Loaded, the window hasn't been created yet, so Window.GetWindow(MainWindowGUI) returns null. However, as seen in the code above, if I try to set all of those properties in MainView_Loaded, they don't actually take affect. – Ben Jul 13 '16 at 18:02
  • @Ben I don't know enough about your application to understand what that has to do with my question. Are you saying that your child control must be the one who makes the parent window transparent? If you're absolutely set on doing that, you might rig up some kind of an event on the App that the MainWindow raises in its constructor after InitializeComponent();. Controls could handle that event. I'm guessing. – 15ee8f99-57ff-4f92-890c-b56153 Jul 13 '16 at 18:24
  • @Ben You still haven't told me why this is necessary. Is the window created at different times with different content? Why not pass the content to the window's constructor? – 15ee8f99-57ff-4f92-890c-b56153 Jul 13 '16 at 18:31
  • The control creates the main window of the program. The main xaml of the program isn't structured . It's structured . – Ben Jul 13 '16 at 19:58
  • @Ben It might be simplest to create the window differently. You can put anything in a Window's Content property, including the usercontrol. – 15ee8f99-57ff-4f92-890c-b56153 Jul 13 '16 at 20:01