Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Creating a WPF Frame Inside of a Window with AllowsTransparency Set to True

0.00/5 (No votes)
19 May 2011 1  
How to create a WPF frame inside of a window with AllowsTransparency set to true

As much as I love Microsoft, it's a wonder that they don't update some of their developer controls/tools to use the technology that they are writing everything else in.

Thankfully, the developer community is on top of it.

WPF: Using a Frame element in a custom shaped window

Here's my modified code to enable this functionality as a reusable class:

using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interop;
using System.Windows.Media;
using DrawingPoint = System.Drawing.Point;

namespace VisibleFrame
{
    /// <summary>
    /// Original code from: http://davidfulop.spaces.live.com/blog/cns!BC8EF43294ECB87!427.entry
    /// Converted window into reusable class: http://www.aronweiler.com
    /// </summary>
    internal class VisibleFrame
    {
        //The following two windows-calls will be necessary to draw the Frame onto the main window
        [DllImport("user32.dll")]
        internal static extern bool ClientToScreen(IntPtr hWnd, ref DrawingPoint point);

        [DllImport("user32.dll")]
        internal static extern bool MoveWindow
        (IntPtr hWnd, int x, int y, int width, int height, bool repaint);

        //The invisible window in which the Frame will be hosted
        Window w = new Window { WindowStyle = WindowStyle.None, 
        ShowInTaskbar = false, ResizeMode = ResizeMode.NoResize };

        Window targetWindow;
        Border targetControl;

        Frame frame;

        internal VisibleFrame
        (Window targetWindow, Border targetControl, string initialLocation)
        {
            this.targetWindow = targetWindow;
            this.targetControl = targetControl;

            targetWindow.Loaded += WindowLoad;

            frame = new Frame();

            if(!string.IsNullOrEmpty(initialLocation))
            {
                Navigate(initialLocation);
            }
        }

        internal void WindowLoad(object sender, RoutedEventArgs e)
        {
            //It is crucial to set the Owner, 
            //because if we don't the inner window won't be repainted after a task-change
            w.Owner = targetWindow;

            //Creating the Frame and registering to the repaint-related events
            w.Content = frame;
            targetControl.SizeChanged += delegate { RepaintFrame(); };
            targetWindow.LocationChanged += delegate { RepaintFrame(); };

            //Showing the Window that contains our Frame
            w.Show();

            //Initial call to the RepaintFrame 
            //lets us place the Frame to the correct location
            RepaintFrame();
        }

        private void RepaintFrame()
        {
            //We get a Win32 representation of the main window
            HwndSource hostWindow = HwndSource.FromVisual(targetWindow) as HwndSource;

            //We get a visual manager for point transformations
            CompositionTarget ct = hostWindow.CompositionTarget;

            //We need to translate the coordinates of the 
            //embedded window to the Border element (browserhost)
            //Note, that the ClientToScreen function don't understand 
            //WPF's Point struct, that's why we have to convert it
            Point loc = ct.TransformToDevice.Transform
            (targetControl.TranslatePoint(new Point(), targetWindow));
            DrawingPoint locD = new DrawingPoint((int)loc.X, (int)loc.Y);
            ClientToScreen(hostWindow.Handle, ref locD);

            //We have to calculate the size - basically the 
            //bottom right coordinate of the Border element
            Point size = ct.TransformToDevice.Transform(new Point
            (targetControl.ActualWidth, targetControl.ActualHeight));

            //Last thing to do: call a Win32 function to paint 
            //the Frame to the correct location
            MoveWindow((HwndSource.FromVisual(w) as HwndSource).Handle, 
            locD.X, locD.Y, (int)size.X, (int)size.Y, true);
        }

        internal void Navigate(string location)
        {
            frame.Navigate(new Uri(location));
        }
    }
}

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here