11 November 2012 WPF Robert Muehsig

Die Standard-Fenster von Windows verschwinden immer mehr und werden ersetzt durch schicker anmutende Bedienelemente. Diesmal meine ich allerdings keine “Metro” Apps, sondern normale, full-power Windows Applikationen.

Achtung: Der Blogpost ist sehr “Low-Level”. Es gibt bestimmt einige Libraries oder NuGet Packages, die diese Sachen mitbringen. Die herangehensweise hat auch 2 Nachteile!

Aus dem Drögen Standard (für Windows Desktop Applikationen):

image

Wird zum Beispiel sowas:

image

image

image

 1. Schritt: WPF Window Rahmenlos machen

Um ein “Window” komplett rahmenlos zu bekommen muss man die Eigenschaften “WindowStyle” auf “none” setzen und den “ResizeMode” auf “NoResize”.

<Window x:Class="DropShadow.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" WindowStyle="None" ResizeMode="NoResize" WindowStartupLocation="CenterScreen">
    <Grid>
        
    </Grid>
</Window>

Ergebnis:

Man hat nun eine gänzlich weiße Fläche.

image

2. Schritt: Den Rahmen erzeugen

Ich hatte erst über diverse Styles es probiert, allerdings hab ich dann diese Lösung gefunden, welche direkt Betriebssystem Funktionen nutzt. Vorteil: Auf Windows 8 sieht es “dezenter” aus als auf Windows 7 – sprich: Es passt besser in das Gesamtbild des Betriebssystem.

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

        [StructLayout(LayoutKind.Sequential)]
        public struct Margins
        {
            public int leftWidth;
            public int rightWidth;
            public int topHeight;
            public int bottomHeight;
        }

        protected override void OnSourceInitialized(EventArgs e)
        {
            base.OnSourceInitialized(e);

            var helper = new WindowInteropHelper(this);

            int val = 2;

            DwmSetWindowAttribute(helper.Handle, 2, ref val, 4);
            var m = new MainWindow.Margins { bottomHeight = -1, leftWidth = -1, rightWidth = -1, topHeight = -1 };

            DwmExtendFrameIntoClientArea(helper.Handle, ref m);
            IntPtr hwnd = new WindowInteropHelper(this).Handle;
        }

        [DllImport("dwmapi.dll", PreserveSig = true)]
        public static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, ref int attrValue, int attrSize);

        [DllImport("dwmapi.dll")]
        public static extern int DwmExtendFrameIntoClientArea(IntPtr hWnd, ref Margins pMarInset);
    }

Resultat:

image

Was man dabei beachten sollte:

Durch das rahmenlose Fenster muss man sich natürlich jetzt selber darum kümmern, dass der Anwender es vergrößern bzw. verkleinern kann und das man das Fenster verschieben kann. Ich vermute es gibt hier (wie oben erwähnt) irgendwelche Frameworks/Libraries/NuGet Packges die einem das Leben vereinfachen.

Die kompletten Sourcen findet ihr auf GitHub.


Written by Robert Muehsig

Software Developer - from Saxony, Germany - working on primedocs.io. Microsoft MVP & Web Geek.
Other Projects: KnowYourStack.com | ExpensiveMeeting | EinKofferVollerReisen.de